Why is NSOpenPanel/NSSavePanel showing memory leak? - objective-c

Not sure why, but making a simple [[NSOpenPanel openPanel] runModal]; creates a memory leak - seen in Leaks Instrument.
Seems off.
It's an auto-released object, shouldn't it be automatically released after ARpool is drained?
Is there a way to fix this?

NSOpenPanel is a singleton, which means you always get the same instance of the object every time you use it. This means that the first time you call [NSOpenPanel openPanel], an instance of NSOpenPanel is created and not released.
This is not a leak, it's an optimisation. However, sometimes the Leaks instrument picks up such once-only instantiations as leaks because the instances are (by design) never released.
NSOpenPanel is such a widely-used and tested class that any leaks in its standard implementation are unlikely to exist.

NSOpenPanel is not a singleton. It may have been at one time but looking at the latest NSOpenPanel.h file makes it explicitly clear it is not a singleton or at the very least Apple doesn't want you taking advantage of this implementation detail.
As for the leak, I was confused on when I should release my open panel and was retaining it. From the Using the Open and Save Panels section of the File System Programming Guide your life is a lot easier in 10.7 and above:
Important: In OS X 10.6 and earlier, you must retain an open panel prior to displaying it and release it when you are done with it. Because the openPanel method returns an autoreleased object, the panel is normally released shortly after it appears on screen. Retaining the panel prevents it from being deallocated and dismissed prematurely. You do not need to retain the panel if it is attached to a window and you do not need to retain the panel in OS X 10.7 and when using ARC.
Once I stopped retaining it things got easier and became a lot easier :)

Instruments is not perfect at detecting leaks - particularly for autoreleased objects, and has a tendency to have false positives. You might try creating a new NSAutoreleasePool, then draining it when you are finished with the NSOpenPanel to force release early - but I suspect you don't actually have a leak. If you are confident that the code looks good and it is autoreleased, then its probably fine.

I was seeing "leaks" reported in Xcode's memory graph tool when using NSOpenPanel in an unsandboxed app built on OS X 10.11.6 using the 10.12 SDK and Swift 3.0.1. The "leaks" were reported in PlugInKit classes (PKHostPlugin, PKDiscoveryDriver, etc.) and would show up even if the only line of code was let openPanel = NSOpenPanel().
NSOpenPanel's documentation states
In a sandboxed environment, Open panels are drawn in a separate
process by the powerbox, not by AppKit itself. When the user chooses a
file to open, macOS adds that file to the app’s sandbox.
After I sandboxed the application, the "leaks" did not show up in Xcode's memory graph as the NSOpenPanel implementation code was no longer in the application's address space, so I no longer had to worry about it.

Related

NSCFString memory leak in Cocoa's animator proxy

After spending several hours on finding some leaking NSCFStrings in Instruments I seem to have realized that calling Cocoa's -animator proxy is causing this.
It is always reproducible: Just create a new Xcode project, add a new NSTableView in IB, fill it with some test data and run Instruments with Leaks. Once you hover over the NSTableView so that the scrollers fade in and out, you'll notice at least one leaking object in Instruments.
Although I've already filed a bug to Apple, can anyone confirm this leak?
Demo-Project: https://www.dropbox.com/s/lszveuwrsuaxxg5/TableViewMemoryLeakStackOverflow.zip
Screencast: https://www.dropbox.com/s/vqtwbkus3jygdb3/ProxyAnimatorMemoryLeak.mov
This bug was resolved in OS X 10.9.3.

ARC: Heapshots shows growing heap, but no own classes

How can I track down abandoned memory if in Xcode Instruments don´t show my custom classes?
So I can see the heap is growing after I perform an action with my app (open a view and go back to the previous in my case) and I could fix some memory issues before by tracking down my mistakes in my code.
Now however, I only see things like in Generation N (= Heapshot N), non-object and I don´t know any more how I can fix the leaks. The responsible caller (not seen in the screenshots) also show no own classes/objects.
Edit
The Showing View is a UIWebView. I searched the web and found rumors that UIWebView doesnt properly releasing data. Could that be the issue? I can´t find any solution.
UIWebView is notorious for causing memory issues.
Make sure you set the UIWebView object's delegate property to nil if you assigned an object to it as documented in the class reference. You can do this in dealloc.
Cleanup the web view in viewWillDisappear:animated: by stopping URL loading with a call to stopLoading and/or setting the HTML string to nil by calling loadHTMLString:baseURL: to workaround any memory being held.

Managing View outlets in ios 5.0 and ios 6.0

I am working on an iPad application which is converted to ARC. Application is for os >= ios 5.0. So my doubt is that, how do I manage viewOutlets? I use -(void)didReceivememoryWarning to set ViewOutlets to nil. But in ios 5.0 and 5.1 application shows lots of memory leaks. As -(void)viewDidUnload is deprecated in ios 6.0 , I am not using the same in the application. Is the correct way to manage outlets? Please give me a quick reply.
ARC (automatic reference counting) features is available in iOS 5 and ahead (iOS 6 and so on..) version.
When you are using ARC unable in your project, you dont need to `manually release any object` that you have allocated for your stuff.
ARC will automatic handle this one.so it will beneficial for `Memory Management`.
Hope ,You understand what i m trying to say.
for more clarification , please refer below link:
To ARC or not to ARC? What are the pros and cons?
ARC, worth it or not?
Good Luck !!!
There is NO DIFFERENCE in how you code for iOS 5 vs. iOS 6.
If you are having problems, it's because you don't understand what viewDidUnload does and when it's called.
viewDidUnload is called when the view of the controller is unloaded. In iOS 6, views are never unloaded. In iOS 5 and before, views were almost never unloaded either. So in both cases, pretty much viewDidUnload is never called.
If your program is leaking stuff, it's because you are not releasing things. You always need to release instance variables in dealloc. I suspect that this is your problem.
When the controller's view is unloaded (which only happens in iOS 5 and before, but this is irrelevant), viewDidUnload allows you to optionally discard some resources to save memory, as long as they are resources that will be re-created when the view is loaded again. This usually includes properties and instance variables that are outlets (since when the view is loaded, it will load the Xib again and re-connect the outlets to new objects), as well as any variables that are set in viewDidLoad.
If you coded your program correctly, I can go in there and remove viewDidUnload, and it would not have any effect on the correctness of the program. (Since viewDidUnload is almost never called anyway.)
You should almost never have to use didReceiveMemoryWarning either.

ARC: Memory does not get reclaimed?

I am working on an iPad (only) app and I stumbled across a weird problem. The app gets terminated after a memory warning on iPad 1 but works fine on iPad 2.
I am using ARC and targeting iOS 5. I use nibs and most of my assets are displayed using UIImageViews. I also have a few hundred buttons and plenty of gesture recognizers... I re-watched the WWDC11 videos (sessions 323 and 322) on ARC and I don't seem to be doing anything special.
The app is UIImage intensive, I am doing lots of animations using UIImage. I am however using the initWithContentsOfFile constructor rather than the imageNamed call. I'm trying to prevent the images from being cached by the system.
I'm also using GCD to schedule sound effects and to animate views. I'm always doing this on the main thread.
The app uses a UINavigationController that never has more than 1 UIViewController on it's stack. I can confirm that this is true because the didReceiveMemoryWarning only gets called on the current view controller (I'm logging the call).
The thing I don't understand is why Instruments is reporting high numbers (as if the view controllers don't get deallocated) in both the Allocations and VM Tracker instruments. The Allocations instrument shows a small drop when I navigate from one view controller to another (which is what I expect) but the VM Tracker Instrument shows that the Dirty Size is not dropping when I do the same thing. Eventually the app uses too much memory and gets terminated (on iPad 1). When I get memory warnings on the iPad 2 the app does NOT get terminated though...
It feels as if my images, sounds or views don't get destroyed and the memory does not get reclaimed... My object hierarchy is very basic and there should not be any retain cycles of any sort. I don't even have simple delegates...
Do you have any suggestions? I really don't want to release this app only for the iPad 2 or newer... It's an app for kids and it would be a pitty... I'd be so much happier to learn that I'm doing something wrong, as I really want to make sure this app is the best it can be...
Cheers,
Nick
There are ways to say, 'optimise' your objects by setting their properties to nil when certain things aren't needed -- so while you can't write a dealloc method anymore, you can do self.object = nil (when pertinent) which ends up doing something like this in a non-ARC world for an 'retain' (i.e., strong) property:
- (void)setObject:(id)newObject
{
[object release]; // send release message to current object
object = newObject; // set reference to newObject
[object retain]; // send retain message to newObject
}
Now while in ARC you don't/can't write retain/release yourself in your code, the compiler inserts these calls for you, meaning that in practise, setting a property to nil would do this in the above example:
[object release]; // send release message to current object
object = nil; // set reference to nil
[object retain]; // send retain message to nil (no effect)
Moreover, this is just the tip of the iceberg -- you should make sure that there are no retain cycles in your code, which could be resulting in objects leaking without recourse to their destruction. This means, that there may be places where you're using strong references to a property (i.e., an object), when you should be using a weak property. The difference being, that strong references are retained, and weak references are assigned, the former having its retainCount incremented and the latter resulting in a property assignment that looks like this if handwritten:
- (void)setObject:(id)newObject
{
object = newObject;
}
I don't like answering my own question but I figured it could be helpful to future googlers. I implemented my own UIImage based animation and I no longer use the animationImages property. Turns out my memory issues are now gone as I no longer need to store all the images in memory and I load them as they are required using a timer.
I actually think that rolling out a custom animation is beneficial since it allows for callbacks and more powerful customisation options.
Once I'm happy with it and I feel like it's ready to be shared I will post the class(es) on GitHub.

What's a smart method to track class properties history in Xcode ?

What's a smart method to track class properties history in Xcode ?
I have a zombie property, and I don't understand when it is over released.
Also, I don't want to introduce memory leaks by erroneously over retaining it in the wrong place.
Thanks
I'm not sure what you exactly mean by tracking the history but on overreleasing objects there is an excellent tool called Instruments that can be used in conjunction with the NSZombieEnabled flag. The latter enables tracking that catches access to already-released objects (e.g. when overreleasing you access the release selector one more time on an already released object).
To do this in XCode 4 you select your app, select it to run in the simulator and Choose (in the Menu) Run -> Profile. Now Instruments should launch and present a selection of profiling options. You now select Zombies, the app starts and as soon as you hit a zombie object, a little flag will pop up in the timeline. There (clicking the arrow) you can access the offending object, the object's history (i.e. who retained and released that object) and if you enable the right sidebar, you also get a stacktrace for every entry.