I'm creating a ViewController object an pushing it to a navigation controller.
When the object is being popped from the stack - it is not being release and Deinit is not being called. What can be the reason for that?
Here's the code that pushes:
self.navigationController?.pushViewController(CustomViewController(), animated: true)
And here's the code that pops:
self.navigationController?.popViewControllerAnimated(true)
I had similar problem. I added empty deinit method to my class and added breakpoint:
deinit {
}
As result it's never called.
As soon as I add some code to the body it started working as expected:
deinit {
print("deinit called")
}
So be sure that your deinit method isn't empty.
PS. I am using Swift 2, Xcode 7.1
Do any of your classes, or properties they contain make a reference to the view controller you've popped?
If your UIViewController has created an instance of an object, which in turn makes a 'strong' reference to that view controller (e.g. a reference that's not explicitly declared 'weak' or 'unowned'), and your view controller keeps a strong reference to that object as well, neither will be deallocated. That's called a strong reference cycle, documented here (a must read for serious Swift developers):
The Swift Programming Language (Swift 3.0.1): Automatic Reference Counting
Closures are a more insidious case where you can get into trouble.
One thing you might try as an experiment is pushing the controller and popping it before you do anything in viewDidLoad or in the initialization, and see if the deinit method is being called. If it is, then you should be able to incrementally discover what you're doing that's leading to the symptom you're seeing.
Another thing that can thwart diagnosis (as other answers have pointed out), which I learned the hard way, is that the debugger breakpoint won't be taken for deinit() if the deinit method contains no executable statements, because the OS or compiler optimizes the deinit invocation away if it's empty, so at least put a print statement there if you want to verify deinit() is getting called.
I was using this tutorial Custom TabBar with a custom seque on the given page. The memory problem was due a subview which had a strong reference the the parent viewcontroller.
class WBMNewsFeedV: UIView
{
var parentVC:WBMHomeTabVC!
}
WBMNewsFeedV - subclass
parentVC:WBMHomeTabVC - parent class ViewController
I changed it to :
class WBMNewsFeedV: UIView
{
weak var parentVC:WBMHomeTabVC!
}
So, the strong reference was nested inside a subviews and not visible at first. Hope this helps anyone. After the change deinit was always called in
WBMHomeTabVC
I had the same issue when the NotificationCenter was holding a strong reference to the presented view controlled and thus it was never getting released. So I had to add [weak self] to the block like this:
(in the viewDidLoad)
NotificationCenter.default.addObserver(forName: .showFoo, object: nil,
queue: OperationQueue.main) { [weak self] (notification) in
if let foo = notification.userInfo?["foo"] as? Foo {
self?.afooButton!.setImage(UIImage(named: "foo"), for: .normal)
}
}
add some line code of in deinit. If You put breakpoint at Empty deinit ,compiler will not stop you there
put this:
deinit {
print("any thing")
}
It will work ;)
I had a timer in my view controller, running every minute to update a label. I put a call in deinit to invalidate the timer, which I'm pretty sure is what I've always done in Objective-C (in dealloc) and it's worked. But it seems a little different in Swift so I moved the time creation/invalidation code to viewWillAppear/viewWillDisappear (which makes more sense really) and everything seems fine now!
I just ran into a similar issue. My problem appears to have been caused by a strong reference to a control that had delegate assignment not specified as 'weak' with a class type protocol.
I had same issue what I found is I didn't make weak reference for my other class delegate
protocol SomeClassDelegate : AnyObject {
func someClassDelegateMethod(<param>)
}
class SomeClass: NSObject {
// Make delegate weak reference
weak var delegate:InfractionDataManagerDelegate? = nil
< some code >
}
now deinit is being called on my implementation class.
Just to add an edge case which I found very difficult to detect:
If you allocate any UnsafeMutablePointers and provide self (the UIViewController) as pointee inside of your view controller, make sure to call pointer.deinitialize(count:), not just pointer.deallocate().
Otherwise, the reference to self will remain and the UIViewController will not deinitialize.
I faced the same Problem. In my case a never ending cycle of UIView.animateWithDuration... holds the ViewController in Memory and blocks the call of deinit. If you use something like this you have to stop it first bevor you remove the ViewController. Hope that helps.
I had a similar issue: I had some UIViews as arranged subviews of a *stackview" contained in a scrollview in a detail view controller. It worked when I removed the UIViews from the stackview on back button tap (willMove(toParent parent: UIViewController?)). Another thing to check is when in your view controller you have something like: let session = URLSession(configuration: .default, delegate: self, delegateQueue: OperationQueue()) (that self could in some cases prevent a detail view controller to be deallocated when you click Back and move to the master)
First of all make sure to define deinit
deinit {
print("OverlayView deinit")
}
Use Xcode's object graph to check number of instances being created and if they are not getting deallocated then they will keep growing.
I was creating property of another ViewController on top of the file so i move it and place it in the scope it was being used that solved my problem. And its deinit started calling.
Moreover i was using a uiview property to show a overlay that need to be accessed from my viewcontroller at some places i make it optional and set it nil when after calling removefromsuperview on it.
var overlay: OverlayView?
overlay = nil
If still dealloc not calling then there could be a retain cycle issue as described above in that case you will have to check another viewcontroller(B) too if its calling back this controller(A) then set one of them as a weak variable.
the most helping material that I could find in this problem is link
But for me the problem was typealias
Related
I have a UIView defined in
class InteractViewController: UIViewController {
#IBOutlet weak var tipsView: UIView!
var tipslayer: CALayer {
return tipsView.layer
}
}
There are a number of constraints also attached in the class as well as labels for example.
#IBOutlet weak var tips1Top: NSLayoutConstraint!
#IBOutlet weak var tips1Right: NSLayoutConstraint!
#IBOutlet weak var tipsTitle: UILabel!
#IBOutlet weak var tipsDesc: UILabel!
All are connected on the storyboard to their correct outlets. Referencing these within the actual InteractViewController itself I am able to adjust opacity, update labels on the layer etc.
However, these are not needed unless the user is first using the application so a simple if else on the InteractViewController calls a function to either display and update properties of these or not show them at all.
The function that controls and updates these properties is in another class (Swift file in the project called.
class TipsViewController: UIViewController {
func tips() {
InteractViewController().tipslayer.transform = CATransform3DMakeScale(0.8, 0.8, 1.0)
}
}
Causes the app to crash creating
Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
on
return tipsView.layer (the InteractViewController)
tipsView and tipslayer are of cause not optionals and are not declared as optionals.
I have three questions I hope I can get assistance with.
Is having the physical reference to the outlets on the ViewController class InteractViewController: UIViewController the problem? If so is it because they are supposed to be programmatically added instead on the class TipsViewController: UIViewController (which does not have a physical visual view controller in Xcode)?
Does having a physical reference to the outlets on the
class InteractViewController: UIViewController
create unnecessary memory use if on InteractViewController the call to the function on the second ViewContoller TipsViewController.tips() is never called so in other words the answer to question 1 is essentially any physical outlets should be programmatically added on lass TipsViewController: UIViewController?
If there is no memory issue and knowing that tipsView and the returning tipslayer are not optionals why am I simply unable to reference them from the tips() function in the other class (TipsViewController: UIViewController)? I have seen multiple posts about "passing data between view controllers" but I am not passing data between variables or arrays. I want/ need to simply update label string, constraints (objects in one view controller class from another view controller class.
I know people are busy so just to say in advance I appreciate all feedback and assistance with the problem.
It was suggested that my question was a duplicate of [What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?
But this is not my question. MY question relates specifically to accessing an Outlet from another ViewController which is then generating a Nil response to the Outlet because as explained InteractViewController is apparently not referencing the ViewController. Please read the explanations and answer provided by Rob which answers this specific question.
Your title says "IBOutlet returns Fatal error: when referenced from another UIViewController class". The bottom line is that one view controller should never access another view controller's outlets.
In your code snippet, you employ the InteractViewController() syntax. Unfortunately, this just instantiates view controller, but does not hook up outlets in storyboard. You need to instantiate via storyboard and, even then, you can’t reference your outlets immediately, but only after viewDidLoad is called later. Only the view controller itself should be trying to access its own outlets, anyway.
The TipsViewController() or InteractViewController() syntax says "create a new, blank instance of that view controller". It's equivalent to saying TipsViewController.init() or InteractViewController.init(). And, worse, it's not using the storyboard at all (and thus no outlets will be hooked up). That's not what you want. You should avoid using this ViewController() syntax, as outlets will never been accessible that way.
InteractViewController should determine whether TipsViewController should be presented (e.g. checking user defaults), and if so, present it. The only thing InteractViewController should do, though, is:
figure out whether to present TipsViewController;
if so, present that TipsViewController; and
pass model data (e.g. whatever InteractViewController retrieved from UserDefaults) to the TipsViewController instance that is created for you.
But anything and everything about how TipsViewController presents its subviews, is the purview of TipsViewController alone. InteractViewController should never interact directly with any outlets of TipsViewController.
It has been a while since I’ve tackled CoreData and macOS, back in the days of xib and nibs. With a xib, there’s the “File’s Owner” that can give you access to your document and the managedObjectContext. Easy.
With NSPersistentDocument and my storyboard, I’m having a bit of a chicken and egg problem. In my Document class, subclassed from NSPersistentDocument, I have the following:
override func makeWindowControllers() {
// Returns the Storyboard that contains your Document window.
let storyboard = NSStoryboard(name: "Main", bundle: nil)
let windowController = storyboard.instantiateControllerWithIdentifier("Document Window Controller") as! NSWindowController // <- when I need the moc
self.addWindowController(windowController)
windowController.contentViewController!.representedObject = self // <- when I set the representedObject
}
This seems to be what many folks, including Apple, are suggesting.
My problem is this: In the MainViewController, I want to have an Object Controller and it needs to be bound to the managedObjectContext but when it needs to have the managedObjectContext, I haven’t yet set the representedObject to self. So an exception is thrown. Setting the representedObject at the end of the makeWindowControllers method is too late but I don’t see anyway to get it in earlier.
Okay. So. I don’t know what was happening last night but there was no way I could get this working.
This morning, I re-read the documentation on representedObject:
The representedObject property is key-value coding and key-value observing compliant. When you use the represented object as the file's owner of a nib file, you can bind controls to the file's owner using key paths that start with the string representedObject.
The docs are clearly telling me that the magic is in representedObject. So I made sure that my makeWindowControllers method was as above and I made sure that my Object Controller in my storyboard was as the docs said it should be.
I wasn’t surprised that the path has a little (!) because representedObject is just an AnyObject.
I then dutifully launched the app, fully expecting it not to work.
But it worked. No idea why yesterday it didn’t but not much I can do about the hours already lost.
Follow up: As an experiment, I tried one of the twists from yesterday. To get rid of the (!) and to have a reference handy to the moc, I added this method to the MainViewController:
var moc:NSManagedObjectContext? {
if let doc = self.representedObject as? Document {
return doc.managedObjectContext
}
return nil
}
And then I used “self.moc” as the Model Key Path for my Object Controller. This didn’t work and the familiar exception was thrown. Restore the Model Key Path to “self.representedObject.managedObjectContext” and all works nicely. … like magic.
Ok so awhile back in testing I had a random crash with no error, and I have no clue why. So i went into analyze things and I came up with the following data.
As it would appear my memory usage is getting higher and higher and higher until it sorta plateus. Notice how at the beginning the slope of the general curvature is greater then later on. (as you might notice this is my first time going in and analyzing this sort of thing).
Now what happens in the game is that basically their are two screens.
1. Menu: this screen has quite a few textures but does nothing except has button to play game
2. Game: this has TOOONS of textures and has the bulk of the cpu usage because its the actual game.
3. Death: This screen has one asset, and it is a button that allows you to replay the game. This should not be using much memory OR cpu. However it still has memory. To me this screams whatever a "memory leak" is, is going on.
If you will look at the chart basically what was going on in the game was the menu started, and the first spike was loading up the actual game, then I died. Then from then on I was switching between the Game and Death screens, each spike signals the Game scene being loaded.
If this data were the way I would predict it you would se an oscillation between a very small memory use for the death screen, and then a return to a game memory usage.
Moral of the story is I am pretty sure that sprite kit isn't properly cleaning up after switching scenes and I need to know why if possible.
Btw in order to switch scenes I am using the method made by maxkargin detailed
here
BTW I am working in swift with sprite kit and SKScenes, and SKSpriteNodes
Thanks much!
There is a few reasons why this is, I had a similar problem with my games. If you do it correctly there is no need to remove stuff such as textures. Removing textures on every scene changes is also not ideal, you want to keep them in memory for performance so they do not have to be reloaded each time.
Here is a basic checklist you can use to see if you create a memory leak.
1) Add the deinit method with a print statement to each scene/class. If deinit gets called your scene deallocated correctly.
deinit {
print("Deinit GameScene")
}
2) Are you creating strong reference cycles somewhere by creating references between 2 classes?
The classic Apple example of a strong reference cycle
class Person {
var dog: Dog?
}
class Dog {
var person: Person?
}
To fix it you would have to make 1 of those 2 properties weak
class Person {
var dog: Dog?
}
class Dog {
weak var person: Person?
}
Also good practice with optionals is to set them to nil when they are no longer needed.
person = nil
Maybe check google and the Apple Swift documentation on how to deal with this. I also asked a similar question a while back
Swift SpriteKit ARC for dummies
3) Are you using closures? They can cause memory leaks.
A more common scenario in SpriteKit is these 2 examples which could/will cause a memory leak and makes your scene to not deallocate. (action 2 is a closure which captures self)
// Example 1
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run(someMethod)
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))
// Example 2
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run {
self.someMethod()
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))
A good rule of thumb is that when the compiler forces you to use self than you most likely will create a memory leak without using weak/unowned.
So to fix the above 2 SKAction examples you could either make sure you always remove all actions when you change scenes or IMO even better would be to change your code to this to avoid creating a memory leak in the first place.
let action1 = SKAction.wait(forDuration: 1)
let action2 = SKAction.run { [weak self] in
self?.someClassMethod()
}
let sequence = SKAction.sequence([action1, action2])
run(SKAction.repeatForever(sequence))
Note in all those above example you could also write
.... { [unowned self] in
and than you would not need to use the ? in the closure
self.someMethod()
When you use unowned you basically say self will never be nil which could cause a crash if it is actually nil when the closure is called. If you use weak self you tell the compiler self might become nil before the closure is called therefore self is an optional to avoid the crash.
I think it is almost always better to use "weak" instead of "unowned" to avoid this. In one of my games I was using unowned self in a closure that was called when it fetched StoreKit products from iTunes. This caused me subtile crashes because I could exit the SKScene before the closure was called. If you use weak self you will not crash because you use optionals.
Hope this helps a bit
sprite kit uses cache to retain perforemce between scenes that why switching between scenes spike up memory and this memory does not release at any case either you remove all children from scene or [self.view presentScene:nil]; their are better solution for this...
read this article carefully
https://developer.apple.com/library/ios/qa/qa1889/_index.html
manage scene with view's and remove SKView's from those view's to maintain memory in multi screen game
So based on what everyone said this is what I did. Before changing to a new scene I run functions that basically takes all textures, and sprite nodes and sets them to an empty constructor so that they are smaller, then I remove all actions, and children. This has seemed to do the trick! Their might still be other memory problems, however I need to look more carefully and tweak some things before I can be sure.
Thanks for the advice everyone!
As a side-dish answer, I had a complex scene with a lot of custom sprite kit subclasses and actions interacting together, and the only thing that prevented my SKScene subclass from calling its deinit was one delegate I forgot to define as weak or unowned, which created a classic strong reference cycle problem. So if you assigned any delegates to self in your scene's setup like this:
myCustomNode.delegate = self
Then check the definition of the delegate, it should look like this:
weak var delegate:MyCustomProtocol?
or this:
unowned var delegate:MyCustomProtocol?
If you do not have access to myCustomNode's source code, then try assigning the delegate to nil in your scene like this:
override function willMove(from view:SKView) {
myCustomNode.delegate = self
}
Also, if you get the error
weak / unowned may only be applied to class and class-bound protocol types
This is because your custom protocol must include : class like this:
protocol MyCustomProtocol : class {/*protocol definition here*/}
I have a little problem with my code so that I can't call a function. I created a function func changeLabelText(text: String) { mylabel.stringValue = text } in the ViewController with that I can update the Text in the Label. When I try to call the function from another class in the Project, I get a runtime error(EXC_BAD_Instr...) and the Debugger holds on the line where I try to change the Label's text, with the error: fatal error: unexpectedly found nil while unwrapping an Optional value. Where is the problem? Can someone help me please!
Regarding the "unexpectedly found nil while unwrapping an Optional value" error, the problem is that you have an optional (judging from the code snippet you've provided, it must be an implicitly unwrapped optional) that is nil. Most likely, mylabel is nil. Either print the value or add a breakpoint and examine the property in the debugger to confirm.
If it is nil, you then have to figure out why. In our discussion, it turns out that you're trying to call the Log event in the view controller:
ViewController().Log("asdf")
The problem is that this doesn't call Log in the existing view controller, but rather the ViewController() expression ends up instantiating a new, completely unrelated view controller with its outlets not hooked up to anything. Thus the attempt to update the implicitly unwrapped outlet will cause the error you shared with us.
If you want this separate class (a database manager object) to inform the view controller of event in order to allow the view controller to update the UI, there are three common approaches:
Completion/progress handlers that are closures/blocks.
This is used for simple interface where the database needs to inform view controller when the request is done.
Delegate-protocol pattern.
The delegation pattern (usually conforming to some well-established protocol) is used for rich interfaces where the database needs to inform the view controller of a variety of different types of events.
Notification pattern.
Notifications are used when you want a loosely coupled interface between the database object and whatever is handling these notifications. The view controller might register itself as an observer of any notifications of a particular name with the defaultCenter() of the NSNotificationCenter. The database object can then post notifications of that name (supplying details via the userInfo dictionary) and the view controller will be informed of these events.
A few things are you calling an instance of the view controller properly
e.g if the class name is ViewController, in the the view controller that you are calling the function make sure you use
let VC = ViewController ()
and then use VC.yourFunctionName
also instead of stringValue use .text
I know that when we're using ARC and blocks, we should use __weak to prevent capturing strongly self and prevent a retain cycle !
But I was wondering if in the following example I need to use __weak ?
__weak MyViewController *weakSelf = self;
[self.personObject.gallery downloadLogoCompletionBlock:^(UIImage *image) {
if (image) {
weakSelf.logoImageView.image = image;
}];
Gallery is retaining the block not self, right ? If so I could write :
self.logoImageView.image = image;
Thanks for your answers
With a strong reference self inside the block you would have a (temporary) retain cycle
self -> _personObject -> _gallery -> BLOCK -> self
assuming that the properties personObject, gallery
are backed up by instance variables _personObject, _gallery.
The retain cycle will be "destroyed" as soon as the completion block is called.
If the completion block is never called then self can never be deallocated.
Therefore, if self should possibly be deallocated before the completion block is called,
you should use a weak reference.
This would cause an cycle, just longer than many.
self -> personObject -> gallery -> block
^---------------------------------|
However, this block will live only long enough to be called once, then the gallery should release it, breaking the cycle.
It depends.
Lets say you pop this MyViewController instance from a navigation controller and you expect it to deallocate.
Assuming gallery holds a strong reference to the block, if you didn't use a weak reference you will run into a retain cycle.
personObject.gallery won't get deallocated, because your view controller didn't get deallocated either, since it is getting retained by personObject.gallery's block in the first place.
The other scenario is that gallery does not retain the block, in which case you won't run into the retain cycle.
If for some reason, you don't what goes on with the block inside the implementation of gallery, it's always a good idea to use a weak reference, just in case!