Getting callbacks of FSPathCopyObjectAsync in ARC - objective-c

I'm looking to use FSPathCopyObjectAsync and I'm failing. In order to get my head around the problem I've been looking for examples of it elsewhere and although I was experimenting with the slightly dated source code from Matt Long's tutorial over on Cocoa is my Girlfriend, I then found a bit more elaborate example in a project on github, as a category on NSFileManager. Since my project is running under ARC, I tried porting it, and succeeded only at the half of it.
In its current form, the actual copying works, yet the callback method MZCopyFSPathFileOperationStatusProc is never called. That callback method happens to be the sole reason for using asynchronous copying, otherwise one might as well run a synchronous one in the background. I'm assuming the reason for the callback not being called is that some object is incorrectly released by ARC, but there could be something else going on. I am holding on to the return object of the copyItemAsyncAtPath:toPath:destName:options:statusChangeInterval:error: method, so that can't be it, right?
Who can spot the error and explain why this category isn't generating any callbacks? Is it ARC? Is it something else?
Much obliged. EP.
P.S. For redundancy reasons, here is the gist: https://gist.github.com/6f3715753896ccf6fd35

Your delegate needs to be strongly referenced by something. NSFileManager will only hold a weak reference to it (as it should do), so if you don’t have a strong reference to it, your delegate will get released and the callbacks won’t be seen.
Have you considered using blocks for the callbacks? That would probably be preferable.

Related

Is there a way to rewrite dealloc in Automated Reference Counting? Why doesn't it work?

I am a second year Computer Programming student who is working on a program in Objective C. (Xcode, if it matters). Right now, we are working on animation and moving animated objects across the screen. Right now, I am dealing with an error that is driving me insane. My program is using ARC, Automated Reference Counting, which supposedly is supposed to help with memory management. However, for some reason, I can't seem to use
[super dealloc];
It always gives me an error that says "ARC forbids explicit message send of 'dealloc'
Why is this? How do I fix it? It works in my other programs, just not this one?
Also, release doesn't seem to work either. For example, the following code gives me 2 errors:
[fireBall release];
The error says "'release' is unavailable: not available in automatic reference counting mode" and the next error says "ARC forbids explicit message send of 'release'." Why does this happen, how can I fix it? This code works in my other programs. Can someone please explain, or at least provide a link that can solve all my problems? Thanks for reading
You should take some time to fully go through Apple's Guide on ARC
It will save you tons of time and it's something definitely worth understanding.
You can define your own dealloc method, you just cant call [super dealloc] (ARC calls it automatically). The same is true for release, you dont need to call it as ARC handles placing it in your code
Simple, just remove that line. ARC takes care of all release/autorelease/dealloc calls.
ARC has 100% (pretty much) insight in the lifetime of your objects and inserts these calls for you.
You can still override the dealloc method to do some cleanup though.

How to keep a strong reference around?

I am wrapping AVAudioPlayer with a very simple class that allows me to specify and url and immediately play it and then call a completion block, like this:
[AudioPlayer playAudioWithURL:url
completionBlock:^{
//finished playing
}];
Reason why I wrote this is because it's very easy, simple. No need to implement delegate, etc...Problem is, this won't work. Doing this in a function will obviously allocate it on stack and it will be de-allocated soon, causing the sound to stop playing.
So, what's the best way to implement this kind of wrapper, to keep a reference around until the sound is finished playing?
Thanks
You should not have any problem. What makes you think that it "will obviously allocate it on stack and it will be de-allocated soon"? Have you tried it? You obviously don't have a good understanding of how memory management in Objective-C works.
In your implementation of playAudioWithURL:urlcompletionBlock:, you will inevitably have some kind of asynchronous dispatch. This dispatch will inevitably have to retain your audio player object, in order to have it play stuff. So no, it won't get deallocated, unless you are doing something wrong.
I'm not sure how possible this would be using ARC since you can't really manage the retain/release cycles. I've done something similar to this using a wrapper for UIAlertView, and what I have done -- not using ARC, of course -- would be to simply to call [self retain] on the wrapper class during the show method and then, when the delegate method is called on the wrapper, call the completionBlock and then [self release]. This guarantees (so long as you're following retain/release rules!) that the wrapper class will be alive at least until the callback is called and, in the usual case, the wrapper will suicide itself once it's done doing its job. Again, since you can't manage retain cycles using ARC, I'm not sure if this will work.
The alternative for you might be to look into simply subclassing AVAudioPlayer or creating a category version of it, setting the delegate to itself. That may be able to keep it alive long enough for it to persist until the full sound plays -- though I am a bit fuzzy on how ARC works.
Best of luck!

UIApplicationWillTerminate: NSNotificationCenter vs Application Delegate

This is just a theoretical question. It was born from a real problem in my app, but I re-designed the problem out of the application. But the question remains:
If in my app delegate I write my singleton object to disk upon applicationWillTerminate: but also use NSNotificationCenter to call updateSingletonData upon UIApplicationWillTerminateNotification in some view controller, which will happen first? Will my data be written to the singleton, then the singleton be written to disk, then the app terminates? Or will the reverse happen, with the singleton being serialized and then the singleton updated (worse), or will the app just terminate after a certain amount of time if the serialization takes too long (much worse!)?
I guess this shows my lack of understanding of the guts of Springboard... thanks to anyone who can shed some light here.
A couple of things to note here:
Only Apple know the order these will happen in, as they wrote the code that does it.
You shouldn't care about the order these will happen in. If you do care, then you've designed your code badly.
In reality, you could go and check what order the happen in - for your particular device, for your particular iOS version, etc.
But really, you shouldn't care what order they happen in. From the sounds of it, you should be either firing off to the view controller to write the data before saving in applicationWillTerminate:, or letting the view controller handle saving after it's written its data.
This question is old and the response by #mattjgalloway is correct in terms of code quality but, for the sake of the knowledge, I just saw in the docs that the notification is posted after the UIApplicationDelegate method is called (emphasis mine):
After calling this method, the app also posts a UIApplication​Will​Terminate notification to give interested objects a chance to respond to the transition.
https://developer.apple.com/reference/uikit/uiapplicationdelegate/1623111-applicationwillterminate

Shorthand way of releasing all retained properties?

We all know an object's properties should be released through its dealloc method, but often for objects with many properties this can be pretty cumbersome. It's kind of a headache especially when adding or removing new properties to remember to go back to dealloc and add and remove release calls.
Is there any method of releasing all of an object's properties generically? I wasn't able to find anything while looking through the docs, but could this be done through reflection if it's not already implemented?
I guess another simple option might be to just place all the properties in an array or other container object and always just release the container. Any other options?
I saw one once (and even used it). It involves using the Objective-C Runtime to loop through the properties of a class, check which ones have either a retain or copy flag, and then set them to nil. Then, your -dealloc implementation can be reduced to something like [self cleanupProperties] or something.
The long story short, however, I've stopped using that because of really wacky problems that I can't explain. I don't know for sure that this is what caused it, but it just seems clever enough that it would have some sort of nasty, unforeseen side-effects.
So, in answer to your question: it's definitely possible, but I'd advise you don't. Use garbage collection if possible! :)
Unless you can turn on garbage collection you're pretty much down to two options. As you suggested you could stuff all the property references into a single NSDictionary (which you would release in -dealloc). Otherwise you're stuck with the way it's usually done.
You can see more about garbage collection in Objective-C 2.0 here.

In ObjC, how to describe balance between alloc/copy/retain and auto-/release, in terms of location

As is common knowledge, calls to alloc/copy/retain in Objective-C imply ownership and need to be balanced by a call to autorelease/release. How do you succinctly describe where this should happen? The word "succinct" is key. I can usually use intuition to guide me, but would like an explicit principle in case intuition fails and that can be use in discussions.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
Sometimes the release should be in the same block. Other times the alloc/copy/retain happens in one method, which has a corresponding method where the release should occur (e.g. -init and -dealloc). It's this pairing of methods (where a method may be paired with itself) that seems to be key, but how can that be put into words? Also, what cases does the method-pairing notion miss? It doesn't seem to cover where you release properties, as setters are self-paired and -dealloc releases objects that aren't alloc/copy/retained in -init.
It feels like the object model is involved with my difficulty. There doesn't seem to be an element of the model that I can attach retain/release pairing to. Methods transform objects from valid state to valid state and send messages to other objects. The only natural pairings I see are object creation/destruction and method enter/exit.
Background:
This question was inspired by: "NSMutableDictionary does not get added into NSMutableArray". The asker of that question was releasing objects, but in such a way that might cause memory leaks. The alloc/copy/retain calls were generally balanced by releases, but in such a way that could cause memory leaks. The class was a delegate; some members were created in a delegate method (-parser:didStartElement:...) and released in -dealloc rather than in the corresponding (-parser:didEndElement:...) method. In this instance, properties seemed a good solution, but the question still remained of how to handle releasing when properties weren't involved.
Properties simplify the matter (the rule is auto-/release happens in -dealloc and setters), but sometimes properties aren't a viable option (e.g. not everyone uses ObjC 2.0).
This is a misunderstanding of the history of properties. While properties are new, accessors have always been a key part of ObjC. Properties just made it easier to write accessors. If you always use accessors, and you should, than most of these questions go away.
Before we had properties, we used Xcode's built-in accessor-writer (in the Script>Code menu), or with useful tools like Accessorizer to simplify the job (Accessorizer still simplifies property code). Or we just typed a lot of getters and setters by hand.
The question isn't where it should happen, it's when.
Release or autorelease an object if you have created it with +alloc, +new or -copy, or if you have sent it a -retain message.
Send -release when you don't care if the object continues to exist. Send -autorelease if you want to return it from the method you're in, but you don't care what happens to it after that.
I wouldn't say that dealloc is where you would call autorelease. And unless your object, whatever it may be, is linked to the life of a class, it doesn't necessarily need to be kept around for a retain in dealloc.
Here are my rules of thumb. You may do things in other ways.
I use release if the life of the
object I am using is limited to the
routine I am in now. Thus the object
gets created and released in that
routine. This is also the preferred
way if I am creating a lot of objects
in a routine, such as in a loop, and
I might want to release each object
before the next one is created in the
loop.
If the object I created in a method
needs to be passed back to the
caller, but I assume that the use of
the object will be transient and
limited to this run of the runloop, I
use autorelease. Here, I am trying to mimic many of Apple's convenience routines. (Want a quick string to use for a short period? Here you go, don't worry about owning it and it will get disposed appropriately.)
If I believe the object is to be kept
on a semi-permanent basis (like
longer than this run of the runloop),
I use create/new/copy in my method
name so the caller knows that they
are the owner of the object and will
have to release the object.
Any objects that are created by a
class and kept as a property with
retain (whether through the property
declaration or not), I release those
in dealloc (or in viewDidUnload as
appropriate).
Try not to let all this memory management overwhelm you. It is a lot easier than it sounds, and looking at a bunch of Apple's samples, and writing your own (and suffering bugs) will make you understand it better.