Is Cocoa's Application Delegate Scope Limited? - objective-c

Let's say I want to create new objects than exist throughout the duration of the program. I need them to be created at startup and continuously run background tasks throughout the program. If I put them in the application's delegate under applicationDidFinishLaunching, do the objects exist throughout the duration of the program or just the scope of applicationDidFinishLaunching? After applicationDidFinishLaunching returns, do my objects go out of scope or do they keep running background tasks? If so, how do I ensure the objects exist throughout the duration of the program and continue to run background tasks?
The "background tasks" are being run on separate threads. I am using Objective-C with Xcode 3.2.6 on Mac OS X Snowleopard.

The lifetime of Objective-C objects is controlled manually (assuming you're not using garbage collection or ARC). You shouldn't ask if they exist throughout the duration of the program—instead, you should make sure that each reference to an object, no matter where it is (main thread, background thread) is properly retained. See the basic memory management rules.
Specifically, if you create an object with [[MyClass alloc] init], you now have an owning reference to that object (that you are responsible for eventually releasing). If you then start a new thread and give that thread a reference to your object, that thread should call [obj retain] to ensure that the object will continue to exist, and [obj release] when it's done with the object.

Related

Non-ARC library object sent to ARC code. Overreleased?

A non-ARC precompiled static library I'm using is sending my ARC app "event" NSObjects on my main thread, that it has placed in the main-thread's autorelease pool. My app acts on the event object in a handler function, but doesn't retain or release it, and doesn't use it again.
With Zombies on, I am occasionally getting a break when the main event loop drains the top level autorelease pool and one of these event NSObjects is being deallocated. It smells like ARC has already released the event object (perhaps when it went out of scope in my handler) and then the main event loop releases it again.
Is this a plausible theory, or is this impossible and I have another bug?
If it is possible, what can I do in my app to prevent this?
From your description, the autorelease works as it should - the function has autoreleased the object, meaning that you can use it but then it's released at the end of the auto release pool.
By default you use autorelease pool in the main loop. However nothing stops you from wrapping your call into #autorelease block and checking that the object is released at the correct time.

Release/dispose of a UIViewController in MonoTouch

As I understand it, we need to hold references to our Cocoa objects when dealing with them in MonoTouch. The reason for this is that the ObjC runtime might still hold references to the objects, and if we have no "MonoTouch references" on them, they could be garbage collected, which results in a EXC_BAD_ACCESS as soon as the ObjC runtime tries to access them.
Say, we have two UIViewController subclasses, VC1 and VC2. If the user clicks on a button on VC1, the UI navigates to VC2, and the user can navigate back and forth. If I create a new instance of VC2 every time the user navigates to it, then the references to the old instances get lost, so they're garbage collected and the app crashes the next time a didReceiveMemoryWarning is propagated to the UIViewControllers.
How can I release the old references, so I don't have to use the same instance of VC2 every time? Dispose seemed to not be enough.
As I understand it, we need to hold references to our Cocoa objects when dealing with them in MonoTouch.
Not quite. MonoTouch managed instances will keep a reference to native instances. As long as the managed instance exists the native instance will be alive (since they are reference counted and MonoTouch won't release it's reference).
IOW your need to hold references to the MonoTouch managed instances as long as their native part are required.
The reason for this is that the ObjC runtime might still hold references to the objects ... they could be garbage collected,
Native (Objective C) instances are reference counted, not garbage collected. Native instances won't be released until their reference count reach 0 (which won't happen while an associated managed instance exists);
Also native instances can hold references to other native instances. Not every native instances have a corresponding managed instance.
which results in a EXC_BAD_ACCESS as soon as the ObjC runtime tries to access them.
That won't happen, at least not this way. OTOH it's hard to tell you what's happening in your case (without seeing the code and/or the crashes).
I suspect you're disposing (manually or not) your managed instances before they have completed their jobs. Here's a simplified of what could happen:
you create a managed MT.X instance (e.g. an UIView);
this creates and reference a native X (native reference count == 1);
you override an event (or add a delegate...) `ViewWillUnload' on MT.X (which also exists natively);
you assign the MT.X instance to another (managed) instance, e.g. an UIViewController;
the native UIViewController will add a reference to the native X (native reference count == 2);
application executes happilly...
you stop having a reference to the MT.X instance (e.g. set the variable to null or a different instance);
since there's no reference to MT.X anymore the Garbage Collector will dispose the managed instance, calling Dispose which will reduce the reference to native X (native reference count == 1). But the native instance won't be freed since it's still referenced (not 0) by the view controller;
the UIViewController does something that triggers, natively, X.ViewWillUnload (e.g. it tries to load a new UIView);
since X still exists natively (ref count == 1) it will call it's ViewWillUnload which will try to go back to the managed instance... that was disposed.
The solution to this problem is to ensure ensure you're not disposing managed instance until their native part have completed their jobs.
I've the same situation in my app and GC collects objects correctly. In other words, I never experienced a problem simply nulling reference to a VC and letting GC do the rest.
However, I DID have problems when called for Dispose method as you do. It seems we shouldn't do this manually. Instead we should wait for GC to collect objects and free its resources. Base NSObject class has a call to Dispose in its finalizer, so all unmanaged resources will be freed upon object is collected.
You may also call for GC.Collect in some of the root VC's DidReceiveMemoryWarning method.

NSPrivateQueueConcurrencyType context can only operate within performBlock?

I wonder if NSPrivateQueueConcurrencyType context only operate within -performBlock and -performBlockAndWait.
and NSManagedObject return from NSPrivateQueueConcurrencyType context can not accessed outside the performBlock?
I found the following sentence from apple doc "What's new in iOS 5.0"
When sending messages to a context created with a queue association, you must use the performBlock: or performBlockAndWait: method if your code is not already executing on that queue (for the main queue type) or within the scope of a performBlock... invocation (for the private queue type). Within the blocks passed to those methods, you can use the methods of NSManagedObjectContext freely.
if so, why MagicalRecord and XMPPFramework do not operate the context and NSManagedObject within the block?
I have no idea what the code in MagicalRecord and XMPPFramework does or does not do. You will need to contact them through their normal support means.
I can, however, tell you that if you create a MOC with NSPrivateQueueConcurrencyType, then the only way you should ever access that MOC or managed objects owned by that MOC is through the performBlock* API.
If you create a MOC with NSMainQueueConcurrencyType, then you can access it if you are running in the main thread, or via the performBlock* API.
If you create a MOC with NSConfinementConcurrencyType, then you must only access the MOC from the thread in which the MOC was created. If concurrency is not specified, Confinement is used as the default.
Those are the only current ways to create a MOC, and a summary of the rules for their use.
I believe MagicalRecord uses confinement and keeps a MOC per thread, but I have never used it, and have only looked at older versions of the code base, so it could have changed greatly with the advent of nested contexts.

performSelector: afterDelay: without retaining the target?

I've got a class which uses NSURLConnection to open a long-running connection to a server. When the connection's closed, either in connectionDidFinishLoading: or connection:didFailWithError:, I want to wait 15 seconds then retry the connection.
At the moment I'm using [self performSelector:#selector(restartConection) withObject:nil afterDelay:15.0];, but this leads to the undesired situation that when the object is released by its creator, the performSelector and NSURLConnections perpetually retain 'self', and it never gets deallocated.
How can I do this without perpetually retaining the object? Any help'd be much appreciated.
Thanks, -Alec
I think your only option is to send
[NSTimer cancelPreviousPerformRequestsWithTarget: object];
at some point, probably, before releasing the object. If the timer hasn't been scheduled, this is a no-op, but is not free performance-wise.
You cannot avoid retaining the object. It is retained in order to save you from ugly crashes when in the next main loop cycle the runtime is going to call your selector on the released object.
If you really insist on having your object released immediately without waiting for your delayed selector, I would suggest you to create a separate proxy class. Say your class is called A, create proxy class B which will have a weak reference to your class A (i.e. __weak A* a) and restartConnection selector which will check if the weak reference is valid. If so it would invoke restartConnection on your A object. Then, do, of course, a delayed selector on B's restartConnection
But first of all, I would really suggest that you reevaluate whether you really cannot live with the retain.

Does releasing an object destroy the object?

I am new to cocoa-touch, and really unmanaged languages all together. While I have a firm grasp of the syntax, I am questioning whether I am releasing an object correctly.
I have a view that creates an object,
Communication *comm = [[Communication alloc] init];
[comm doSomething];
[comm release];
I understand that I have to destroy this object because I am allocating it and it will not auto release.
I call a method on the object that goes out to my server and grabs information. When the data returns it throws an event which my "message dispatcher" responds to. I do not want to destroy the object until it returns back from the server -- and this is where my confusion is at.
If I release this object directly after I make the call, will it destroy the object? (Which I don't want to do.)
How do I properly destroy this object after it throws the event with the data I am waiting for? This would occur within a DataFinishedLoading event on my comm object. Should it destroy itself, and is this the right way to do it?
The view calling my object essentially says, create this object, call this method, and go about your merry way. It doesn't care about what happens after it calls the method -- whether it brings back information or not. It simply listens on a method for any data that may come across at a later time. I have no reason to hang onto a reference of the object, as I will never use the same instance after I make the call -- that is besides cleaning up after myself.
A release only destroys the object if the last retainer released it.
For example, say you allocate your Communication object. It is implicitly retained once. Then you retain it five times. You need to release/autorelease the object six times until it gets destroyed (its dealloc method is called).
There is an internal counter, the retainCount. When you create an object, it is set to 1. Now every retain increases the counter, and every release decreases it. autorelease also decreases the counter, but not immediately. Once the counter drops to 0 Objective-C knows that the object is no longer needed and destroys it (by calling the object's dealloc). Warning: do not rely on the retainCount, do not even look at it. You should only care that your alloc/copy/new/retain calls are balanced with a corresponding release/autorelease later on.
In your above example, comm will likely be destroyed when you call release. It depends on something else retains it during doSomething.
If you want to hold onto an object while it does something asynchronously, put it in a retained property. When it informs you that it is done, set the property to nil which will release it.