On 3 Mar 2014, at 7:48 pm, Quincey Morris <[email protected]> 
wrote:

> What are you suggesting that these rules are? AFAIK, there isn’t any “rule” 
> about whether an init method can return nil — it’s part of the API contract 
> in each individual case, isn’t it?


The documentation for -init states:

"If the new object can’t be initialized, the method should return nil. In some 
cases, an init method might return a substitute object. You must therefore 
always use the object returned by init, and not the one returned by alloc or 
allocWithZone:, in subsequent code."

This has also been the subject of much discussion that I've seen over the years 
of how to actually do this, and what I do is to call [self autorelease]; then 
self = (either a new retained object or nil); return self;

This then gets further complicated by designated initializers and the like, but 
the basic idea remains.


- initWithCoder: is just the designated initializer used when dearchiving, so 
my reading of it is that it "inherits" the rules about returning nil or another 
object from -init.

The documentation for -initWithCoder: states (and this seems to be something 
added recently) that -initWithCoder: must return self. However it does not say 
anything about self being reassigned or set to nil like any other init method 
is permitted to do.

> IAC, I don’t think it’s exactly about whether initWithCoder returns nil. 
> Surely it’s about the fact that decoding a NSArray can’t deal with a nil 
> element, since it can’t be inserted into the array. Simply dropping nil 
> elements doesn’t even seem like a possible strategy.

Why not? If I decode a list of objects into an array, it would be a very simple 
matter when looping over those objects to skip nil items. If the code uses 
-arrayWithObjects: instead, then that's a choice made by its designer, not the 
only possible way to do it. I would argue that it's definitely the wrong choice 
- it's making an assumption about how external code is operating.

Looking at it from the opposite point of view, if you have five objects in an 
archive but only the first one is invalid and can't be initialized, then why 
should it go on to drop the remaining four objects in that array? It certainly 
doesn't stop it from dearchiving further objects in a different array. Or, if 
the first two objects were fine, but number 3 was nil, then you end up with two 
objects in the array instead of four. How is that behaviour useful or 
consistent? What you get depends on the order of the items in the array, which 
seems to me unintentional - if there were a (documented) rule that says if any 
object is nil the whole array ends up empty then OK, but right now it contains 
the objects up to, but not following, the nil object.

> I think you have to assume that it’s your responsibility not to return nil 
> when the object being decoded is part of a collection**. After all, it was 
> certainly non-nil when it was originally archived.

Yes, but the discussion for -init says it's fine to return nil "if the new 
object can't be initialized". There are many good reasons why an object could 
be archived but when dearchiving it would be better to skip it, such as the 
case I am faced with.

> I’d also say there’s a parallel problem when *not* dealing with array 
> elements. If in unarchiving an object (*not* in a collection) you return nil 
> from ‘initWithCoder’ (under the assumption that the object wasn’t nil when 
> archived), you’ll end up with a “hole” in your data model, and you won’t know 
> about it.

I'm not sure about that. If your code deliberately does work to discontinue 
initialization, then you definitely know about it.


> Putting those two things together, it seems that simply returning nil from 
> initWithCoder should *never* be done, which is the policy I’ve always 
> followed.

If that's the conclusion, which I'm not yet convinced about, then it should be 
documented. I can't find anywhere that says that. It would also be a simple 
matter to enforce it - NSKeyedUnarchiver could throw an exception if an object 
was allocated but returned nil from -initWithCoder:. It does not do that, so 
it's obviously not considering it as an error. (This is distinct from having a 
nil value actually archived - in that case there is no object allocated).

--Graham



_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to