How to extract an object from NSString - objective-c

It's quite easy get the class/address of an object as a string, using:
NSString* objectInfoString = [object description];
The string returned is something like <ClassName: fk10009567>, with the letters and numbers representing it's unique address in memory, as I understand it.
Or, for just the address, simply using a formatted NSString with the %p place holder.
NSString* addressString = [NSString stringWithFormat:#"%p",myObject];
Is it then possible to create a pointer from this string information?
For Example:
NSObject* foo = [[NSObject alloc]init];
NSString* fooAddressString = [NSString stringWithFormat:#"%p",foo];
Then, I'd like to be able to do something like:
NSObject* newFoo = [NSObject objectForAddressString:fooAddressString];
such that newFoo = foo is true.

The foundation APIs provide a specific mechanism for doing this, without using 'magic strings', although you could do it using stringWithFormat, I guess. (It would be somewhat fragile, as noted).
To get a pointer reference to the object:
//Value now contains a pointer to the object, be careful it doesn't become dangling
NSValue* value = [NSValue valueWithPointer:(__bridge void*) myObject];
To get the object back from the pointer reference:
//If not using ARC you can skip the (__bridge id) here, and change the above cast to just (void*)
MyObjectType* myObject = (__bridge id) [value pointerValue];
Fragility?
It was noted that using '%p' to obtain a pointer value is fragile - while all Objective-C implementations currently return a hex value, the implementation of this could change. In any case, there's a specific API to do it.
Consider also that saving a reference to a pointer is fragile by nature in any case: Having obtained a pointer its necessary to ensure that it doesn't become 'dangling' - meaning the object being referenced goes away before the pointer does. The same strategies as using the __unsafe_unretained (aka assign) memory option should be applied. (No automatic weak references here!)
There are certainly valid applications of this kind of thing, however they are quite specialized and it would be unusual to find yourself doing this in everday apps programming. (I gathered you were asking the question simply to get a deeper understanding of Objective-C - kudos for that).
What is a valid use of this technique?
One valid application is to keep a reference to an Objective-C object in a C++ class. The Box2d physics engine (C++) allows this to provide an integration point with various Objective-C sprite engines.

This does not seem something sane or good thing to do. Relying on the - description of an object is very, very fragile. Why would you need to recover the object from its description? If you want to serialize and deserialize objects, you can do that by implementing the NSCoding protocol. If you want to associate objects with indices or keys, you can use NSArray or NSDictionary, etc...
That said, however, you can make a pointer out of a string:
NSString *addr = #"0xbadf00d";
uintptr_t ptr = strtoull(addr.UTF8String, NULL, 0);
id obj = (id)ptr;

Related

Objective C casting (id) vs. casting as an explicit class

Often in objective C, you know an object is a kind of particular class, so you cast it into that class to continue using it:
NSObject *object;
NSString *string = (NSString *)object;
But, this has bothered me for some time - is there any advantage to writing out "NSString *" in that cast as opposed to the shorter (id):
NSObject *object;
NSString *string = (id)object;
I typically favor verbose Objective-C because the language is designed for readability, but I can't figure out any advantage of being verbose in this case.
Anything you can do to give the compiler more precise and accurate information about the types in play, the more the compiler can validate your code. The id type basically means *this thing responds to any method I've ever seen declared` to the compiler wherein a specific cast narrows it to only the methods that class supports.
In general, casts are to be avoided. They generally indicate poor architecture. Not always, though, as they are oft unavoidable when dynamically generating UI or parsing JSON.
In that case, a construct that boils down to this is oft helpful:
NSObject *object;
NSAssert((!object) || [object isKindOfClass:[NSString class]]);
NSString *string = (NSString *)object;
That forces verification of the I know better than the compiler to runtime. (And, yes, it explicitly allows nil to pass through in this case.... your specific needs may vary.)
I think that the best way is not using down-casting at all by developing more thought-out architecture.
Constructions like this NSString *string = (NSString *)object; simply hide compiler warning and don't make any run-time casting.
But there are some situations when compiler can't know what kind of object is returned by method. For example: [NSDictionary valueForKey:] returns object of id type that is reference to object of any class. It is so because NSDictionary could contain any objects of any class and Objective C doesn't support templates where you could provide class of objects that collection will contain due initialisation.
In such situations usually used constructions like this:
id object = dictionary[key];
NSString *string = object;
Update:
However if consider situation when method returns object of kind NSObject that is really NSString then for compiler it doesn't matter what kind of casting you use: (id) or (NSString *) . But logically it's better to use (NSString *) as it shows kind of object that you expect. I mean that it is more clear for person who will read your code.

Is there any real point to the (copy) attribute in a property?

I had assumed that the purpose of the copy attribute was so that I could just assign one property to another (say) and have the underlying getter/setter methods handle everything properly. But having reviewed a number of articles (including some on stackoverflow) it's not clear to me that there's any real benefit over simply using the appropriate methods to copy stuff explicitly. For a start, I discovered that assigning a mutable string to another mutable string still leaves you with a non-mutable string, so what good is that?
Does this work properly for other classes? In other words, in general, if I have
#property (copy) Foo* f1;
#property (copy) Foo* f2;
....
#property (copy) Foo* fn;
can I generally write
f1 = f2
f3 = f2
and get proper copies, i.e. completely independent objects?
(copy) will call the copy method on the item being set, so it will depend on the object. Let's see an example with NSString and see if that helps?
Two classes ObjectWithCopy
#interface ObjectWithCopy : NSObject
#property (copy) NSString *aString;
#end
and ObjectWithoutCopy
#interface ObjectWithoutCopy : NSObject
#property (strong) NSString *aString;
#end
Pretty easy so far, and we all know NSString is immutable, so what will "copy" do? Well remember NSMutableString is a subclass of NSString. So we could pass that in to the setter instead. What happens when we do this?
NSMutableString *aMutableString = [[NSMutableString alloc] initWithString:#"Hello World"];
ObjectWithCopy *objectWithCopy = [[ObjectWithCopy alloc] init];
objectWithCopy.aString = aMutableString;
NSLog(#"ObjectWithCopy.aString = %#", objectWithCopy.aString);
//Now we change aMutableString
[aMutableString appendString:#" and every other world"];
NSLog(#"ObjectWithCopy.aString after aMutableString was modified = %#", objectWithCopy.aString);
NSLog(#"Now what happens without copy?");
// Reset aMutableString
aMutableString = [[NSMutableString alloc] initWithString:#"Hello World"];
ObjectWithoutCopy *objectWithoutCopy = [[ObjectWithoutCopy alloc] init];
objectWithoutCopy.aString = aMutableString;
NSLog(#"ObjectWithoutCopy.aString = %#", objectWithoutCopy.aString);
//Now we change aMutableString and see what objectWithoutCopy.aString is?
[aMutableString appendString:#" and every other world"];
NSLog(#"ObjectWithoutCopy.aString after aMutableString was modified = %#", objectWithoutCopy.aString);
The output?
2014-02-02 10:40:04.247 TableViewCellWithAutoLayout[95954:a0b] ObjectWithCopy.aString = Hello World
2014-02-02 10:40:04.248 TableViewCellWithAutoLayout[95954:a0b] ObjectWithCopy.aString after aMutableString was modified = Hello World
2014-02-02 10:40:04.248 TableViewCellWithAutoLayout[95954:a0b] Now what happens without copy?
2014-02-02 10:40:04.248 TableViewCellWithAutoLayout[95954:a0b] ObjectWithoutCopy.aString = Hello World
2014-02-02 10:40:04.249 TableViewCellWithAutoLayout[95954:a0b] ObjectWithoutCopy.aString after aMutableString was modified = Hello World and every other world
Whoa - our immutable string was changed on ObjectWithoutCopy!?!? That's because it really was a NSMutableString after all and without copy we are simply pointing to whatever was passed in. So any changes that occurred with that passed in object will be seen in both the class and the function variable. That is why it's so often suggested that when you have an NSString property you use (copy), you don't expect an NSString to change.
Copy makes the assign statement this _aString = [passedInString copy];. As some have pointed out can do anything so long as it conforms to the NSCopying protocol, but should create an independent copy of the object to make sure change the outside world makes doesn't affect your class. So someone could create a subclass of NSString (which you probably should never do) that overrides copy to do nothing and you could still see your NSString change out from under you, but in general it's a pretty safe bet that NSCopying was done correctly. At least that's the best you can really do.
Edit 1:
As #David mentions in his comment (and is maybe his real question?), [aMutableString copy] actually returns a object of type NSString. I completely agree this is confusing. If I was making NSMutableString I would have copy return a NSMutableString. Actually I think the real WTF here is that Apple has created a mutable subclass of a non-mutable class. In C#/Java, you don't have a mutable string, instead you use another class called StringBuilder.
So if this is so confusing, why do so many people use copy on NSString properties? Because it most likely does what you actually want it to. If your class has an NSString property, you picked that because you don't want to worry about the string changing out from under you. To do that you really want a copy of the string passed in. And if it's a NSMutableString you probably want an NSString copy because you don't want to give that mutable string out and have it changed out from under you. If copy on a NSMutableString returned an NSMutableString I don't think people would use the copy attribute, but create a custom setter that set _aString = [[NSString alloc] initWithString: inputString]. This is probably clearer, and if you think it is that it is maybe what you should do. But at this point it's convention to use copy on NSString properties, so I'll probably continue to use it. You may or may not agree with it, but your question is why do people use copy then this is why I do personally.
Edit 2:
#David asks why doesn't copy work this way? "If I copy a string then I want a subsequent call to be able to change it." I think if you really want the side effects you probably should be declaring an NSMutableString without the copy modifier (you probably should never use copy and NSMutableString, but create your own setter).
I really can't think of a reason in my nearly 15 years of programming why I would not want the person setting the string's side effect but I would want any old person who get's the string's side effect. That's really weird.
Further I can't for the life of me think of why I would want that situation but advertise it as an NSString instead. I mean why? Why would want for your immutable property to be sometimes mutable, but only when the setter (which you don't control) tells you too but you don't want the side effects from from object that was set with. AND you don't tell any one about it and they have to just figure it out? My head hurts.
My guess is this is why Apple did what it did. But it's only a guess.
Further, if you can get away with an immutable data type you should. It reduces all sorts of complexity especially with multithreading.
Of course Objective-C (and most OOP languages) let you do all of this if you really really want to. That's up to you programmer and your team. You can also test the accelerometer by bashing your phone against your skull. I don't think Apple recommends either approach though.
Yes, you get completely independent objects. What else would the copy attribute do?
I think that the copy specifier creates a new instance of an object if it is necessary. For example if the object is mutable (object passed to the setter of course). If not it usually just retains it.
Consider that copy means that the instance is logically copied. The way it is implemented (memory copied or just extra retain) does not matter that much actually.
The copy specifier just means that the -copy method of the object in question will be called during assignment (see: the NSCopying protocol). This method's purpose is usually to return a "completely independent object" so that's usually what you'll get. There are exceptions though.
For instance, if your object is an immutable value (NSString being the canonical example), then there's no reason to -copy it to get an "independent object". So in that case, as an optimization, -copy only results in a retain, not a new object.
Of course, any custom class or subclass can override -copy or -copyWithZone: to do any number of unpredictable, destructive things. But the convention is to return, as you say, an "independent object" — or self in contexts where "independent" doesn't mean anything.

How to cast from id __autoreleasing * to void ** in ARC?

I'm trying to cast from an id __autoreleasing * to a CFTypeRef * (void **).
I've tried:
id __autoreleasing *arg = [OCMArg setTo:mockData];
CFTypeRef expectedResult = (__bridge CFTypeRef) *arg;
[[[self.mockSecItemService expect] andReturnValue:OCMOCK_VALUE(mockCopyStatus)] copyItemMatching:queryCheck
result:&expectedResult];
But the code crashes when the autorelease pool is drained.
How does one convert to void** in an ARC environment?
I do not know the APIs you are using, so I'm not 100% sure of what's going on. I googled and they seem to be part of OCMock. I downloaded it and (without installing it as I'm not interested) I rapidly browsed the source.
I see something very fishy in that code. Here's how they implement the first method you call:
#implementation OCMArg
....
+ (id *)setTo:(id)value
{
return (id *)[[[OCMPassByRefSetter alloc] initWithValue:value] autorelease];
}
So they are returning an id* which is really just an id.
To me that's either a nonsense/error or an attempt to manipulate ObjC internals (even if undocumented, the first thing an ObjC object stores is in fact a pointer to the object class and is therefore of type Class which is compatible with id, therefore it somehow is valid to cast a pointer to an object or an id that refers to an object, to Class* or id*). I have no time or interest in going and studying the whole API to figure out why they do that. They may actually have a good reason (for example if you only pass that result to another API that knows what it's supposed to be, but you are doing more than that here). Instead of studying OCMock I'll try to explain you what is happening as far as I can say (ObjC and ARC).
id __autoreleasing *arg = [OCMArg setTo:mockData];
ARC will do absolutely nothing in this line of code.
What that method does you can see above. Class OCMPassByRefSetter is a simple class that just stores the argument after retaining it, so mockData is retained. The OCMPassByRefSetter is autoreleased and will disappear at the next drain (releasing the mockData and making *arg reference to released memory).
Note that arg in fact points to the isa of the OCMPassByRefSetter (the isa is the "first" ivar of any object, it's of type Class and points to the class of the object. But this is undocumented and may change at any time).
CFTypeRef expectedResult = (__bridge CFTypeRef) *arg;
*arg is of type id which is compatible with CFTypeRef, so the cast is valid. You use __bridge so ARC does absolutely nothing.
If arg pointed to a "toll free bridged" CF/Cocoa class this would be perfectly valid code but you'd have to be careful that expectedResult would become invalid at the next drain (it's not retained, but it's live as an autoreleased instance).
[[[self.mockSecItemService expect] andReturnValue:OCMOCK_VALUE(mockCopyStatus)] copyItemMatching:queryCheck
result:&expectedResult];
No idea what this line does. Given the prototype you posted in the comment above, ARC does nothing on the part result:&expectedResult.
You say it's a wrapper around SecItemCopyMatching, but as I understand it it's more than that. If it was just immediately calling SecItemCopyMatching passing it the result: argument, you'd likely be messing things up. But the name expectedResult and the fact that this is OCMock makes me think this is a little more complex than that.
You'll have to investigate it yourself a bit. But remember:
as soon as the current function exits, the argument you passed (&expectedResult) will become invalid as it's a local variable.
as soon as there is a drain, the value of expectedResult will become invalid, as that address points to memory that is going to be deallocated by the drain.
doing anything with the value of expectedResult is likely do be going very wrong as I do not think that a Class qualifies as "toll free bridged".
I suspect, but I may be very wrong, that you are not using the OCMock apis the way they are intended to be used. But on this front I cannot help you, and maybe you are actually doing it right.
Rather than try and figure out how to cast the variable into the correct format (OCMock is doing some complex things internally), I added another method, to handle the conversion.
- (OSStatus)findItemMatching:(NSDictionary *)query result:(id __autoreleasing *)outResult {
NSAssert(outResult, #"outResult is required");
CFTypeRef result = nil;
OSStatus status = [self copyItemMatching:query result:&result];
if (result) {
*outResult = CFBridgingRelease(result);
}
return status;
}

When does -copy return a mutable object?

I read in Cocoa and Objective C: Up and Running that -copy will always return an immutable object and -mutableCopy will always return a mutable object:
It’s important to know that calling -copy on a mutable object returns an immutable
version. If you want to copy a mutable object and maintain mutability in the new version,
you must call -mutableCopy on the original. This is useful, though, because if you want
to “freeze” a mutable object, you can just call -copy on it.
So I have something like this:
NSMutableURLRequest *req = [[NSMutableURLRequest alloc] init];
NSLog( #"%#", [req className] ); // NSMutableURLRequest
NSLog( #"%#", [[req copy] className] ); // NSMutableURLRequest
NSLog( #"%#", [[req mutableCopy] className] ); // NSMutableURLRequest
According to this previous answer:
You cannot depend on the result of copy to be mutable! Copying an NSMutableArray may
return an NSMutableArray, since that's the original class, but copying any arbitrary
NSArray instance would not.
This seems to be somewhat isolated to NSURLRequest, since NSArray acts as intended:
NSArray *arr = [[NSMutableArray alloc] init];
NSLog( #"%#", [arr className] ); // __NSArrayM
NSLog( #"%#", [[arr copy] className] ); // __NSAraryI
NSLog( #"%#", [[array mutableCopy] className] ); // __NSArrayM
So...
When does -copy return an immutable object (as expected) and when does it return a mutable object?
How do I achieve the intended effect of getting a "frozen" copy of a mutable object that refuses to be "frozen"?
I think you've uncovered a great rift between documentation and reality.
The NSCopying protocol documentation claims:
The copy returned is immutable if the consideration “immutable vs. mutable” applies to the receiving object; otherwise the exact nature of the copy is determined by the class.
But this is clearly wrong in some cases, as you've shown in your examples (and I've sent feedback to them about this via that documentation page).
But(#2) in my opinion, it doesn't actually matter and you shouldn't care.
The point of -copy is that it will return an object you can use with the guarantee that it will behave independently of the original. This means if you have a mutable object, -copy it, and change the original object, the copy will not see the effect. (In some cases, I think this means that -copy can be optimized to do nothing, because if the object is immutable it can't be changed in the first place. I may be wrong about this. (I'm now wondering what the implications are for dictionary keys because of this, but that's a separate topic...))
As you've seen, in some cases the new object may actually be of a mutable class (even if the documentation tells us it won't). But as long as you don't rely on it being mutable (why would you?), it doesn't matter.
What should you do? Always treat the result of -copy as immutable, simple as that.
1) When does -copy return an immutable object (as expected) and when does it return a mutable object?
you should always treat it as the immutable variant. the mutable interface of the returned type should not be used. apart from optimizations, the answer should not matter and should be considered an implementation detail unless documented.
the obvious case: for a number of reasons, objc class clusters and class designs can be complex. returning a mutable copy could simply be for convenience.
2) How do I achieve the intended effect of getting a "frozen" copy of a mutable object that refuses to be "frozen"?
using the copy constructor of the immutable class is a good way (similar to St3fan's answer). like copy, it's not a guarantee.
the only reason i can think of as to why you would want to enforce this behaviour is for performance or to enforce a restricted interface (unless it's academic). if you want performance or a restricted interface, then you can simply encapsulate an instance of the type which copies on creation and exposes only the immutable interface. then you implement copy via retain (if that's your intent).
alternatively, you can write your own subclass and implement your own variant of copy.
final resort: many of the cocoa mutable/immutable classes are purely interface - you could write your own subclass if you need to ensure a particular behaviour -- but that's quite unusual.
perhaps a better description of why this should be enforced would be good - the existing implementations work just fine for the vast majority of developers/uses.
Bear in mind that there is not one copy implementation -- each class implements its own. And, as we all know, the implementation of the Objective C runtime is a little "loosey goosey" in spots. So I think we can say that mostly copy returns an immutable version, but some exceptions exist.
(BTW, what does this do:
NSArray *arr = [[NSMutable array] init];
?)
The best way to turn an object into an mutable one is to use the mutable 'constructor'. Like for example:
NSArray* array = ...;
NSMutableArray* mutableArray = [NSMutableArray arrayWithArray: array];
Copy is used to make a copy of an object. Not to change it's mutability.

Cocoa: Testing to find if an NSString is immutable or mutable?

This produces an immutable string object:
NSString* myStringA = #"A"; //CORRECTED FROM: NSMutableString* myStringA = #"A";
This produces a mutable string object:
NSMutableString* myStringB = [NSMutableString stringWithString:#"B"];
But both objects are reported as the same kind of object, "NSCFString":
NSLog(#"myStringA is type: %#, myStringB is type: %#",
[myStringA class], [myStringB class]);
So what is distinguishing these objects internally, and how do I test for that, so that I can easily determine if a mystery string variable is immutable or mutable before doing something evil to it?
The docs include a fairly long explanation on why Apple doesn't want you to do this and why they explicitly do not support it in Receiving Mutable Objects. The summary is:
So don’t make a decision on object
mutability based on what introspection
tells you about an object. Treat
objects as mutable or not based on
what you are handed at the API
boundaries (that is, based on the
return type). If you need to
unambiguously mark an object as
mutable or immutable when you pass it
to clients, pass that information as a
flag along with the object.
I find their NSView example the easiest to understand, and it illustrates a basic Cocoa problem. You have an NSMutableArray called "elements" that you want to expose as an array, but don't want callers to mess with. You have several options:
Expose your NSMutableArray as an NSArray.
Always make a non-mutable copy when requested
Store elements as an NSArray and create a new array every time it mutates.
I've done all of these at various points. #1 is by far the simplest and fastest solution. It's also dangerous, since the array might mutate behind the caller's back. But Apple indicates it's what they do in some cases (note the warning for -subviews in NSView). I can confirm that while #2 and #3 are much safer, they can create major performance problems, which is probably why Apple has chosen not to use them on oft-accessed members like -subviews.
The upshot of all of this is that if you use #1, then introspection will mislead you. You have an NSMutableArray cast as an NSArray, and introspection will indicate that it's mutable (introspection has no way to know otherwise). But you must not mutate it. Only the compile-time type check can tell you that, and so it's the only thing you can trust.
The fix for this would be some kind of fast copy-on-write immutable version of a mutable data structure. That way #2 could possibly be done with decent performance. I can imagine changes to the NSArray cluster that would allow this, but it doesn't exist in Cocoa today (and could impact NSArray performance in the normal case, making it a non-starter). Even if we had it, there's probably too much code out there that relies on the current behavior to ever allow mutability introspection to be trusted.
There's no (documented) way to determine if a string is mutable at runtime or not.
You would expect one of the following would work, but none of them work:
[[s class] isKindOfClass:[NSMutableString class]]; // always returns false
[s isMemberOfClass:[NSMutableString class]]; // always returns false
[s respondsToSelector:#selector(appendString)]; // always returns true
More info here, although it doesn't help you with the problem:
http://www.cocoabuilder.com/archive/cocoa/111173-mutability.html
If you want to check for debugging purposes the following code should work. Copy on immutable object is itself, while it's a true copy for mutable types, that's what the code is based on. Note that since it's calling copy it's slow, but should be fine for debugging. If you'd like to check for any other reasons than debugging see Rob answer (and forget about it).
BOOL isMutable(id object)
{
id copy = [object copy];
BOOL copyIsADifferentObject = (copy != object);
[copy release];
return copyIsADifferentObject;
}
Disclaimer: of course there is no guarantee that copy is equivalent with retain for immutable types. You can be sure that if isMutable returns NO then it's not mutable so the function should be probably named canBeMutable. In the real world however, it's a pretty safe assumption that immutable types (NSString,NSArray) will implement this optimization. There is a lot of code out including basic things like NSDictionary that expects fast copy from immutable types.