Now i have had this problem clouding my mind for quite sometime and i really need someone to clarify this for me.
1) what is a unique identifier that causes the init method to return a different object other than the one you were initially trying to allocate with the call?
.. What should you do in such a case?
2) When a designated initializer from one class assuming that class has more than one method, invokes the designated initializer in its parent class consequently invoking NSObject's init method; what exactly is happening when the parent class init method is invoked? what is "self" in that method explicitly referencing to, as well as the "self" returned from its root class?
Maybe this will answer your questions:
An init method is just a method like any other, there is nothing special about them per se;
Method parameters are local variables which are assigned an initial value, that value being the one given in the call;
self is a hidden method parameter, a value for it is passed in the call as with all other parameters;
The result of the method is implicitly marked with the ns_returns_retained attribute; and finally
The self parameter is implicitly marked with the ns_consumed attribute.
The attributes mentioned effect how ARC manages the references returned (ns_returns_retained) by, or passed to (ns_consumes), a method. These attributes can be explicitly applied to any method.
The attribute ns_returns_retained is applied implicitly to methods in the alloc, copy, init, mutableCopy, and new families; while ns_consumes is implicitly applied to the hidden self parameter of init methods.
The ns_consumes attribute is the only "unusual" feature of init methods. It tells ARC that the method being called takes ownership of the passed object reference, and hence is responsible for releasing it when required. So in the common statement found in init methods, a call to the superclass init method:
self = [super init];
the current reference stored in self is passed to the called method along with the callers ownership of that reference. When the result of the call is assigned back to self ARC does not need to relinquish ownership (aka "release") the old reference stored there - ownership was already passed to the called method - or take ownership (aka "retain") of the new reference - as the called transfers its ownership back to the caller.
The above allows an init method to return a different reference than the one it was passed, and releasing the one it was passed. This feature is not commonly used in user classes but a number of common system classes, e.g. NSString and NSNumber, take advantage to reduce the number of objects needed.
The above sounds more complicated than it is! If you have specific questions then ask new specific questions as #MichaelDautermann suggests in the comments.
HTH
Addendum
In response to comments maybe the following will help. All code typed directly on an iPad, expect errors!
How does the following method work?
- (NSString *) doSomething:(NSString *)aLocal
{
aLocal = [super aLocal];
return aLocal;
}
In the call:
NSString *someResult = [someObjectRef doSomething:someLocalVariable];
where someObjectRef is a variable holding a reference to an object that declares the above method, and someLocalVariable holds a reference to a string.
In outline it is:
a new method invocation is created along with its local variable aLocal
the reference stored in the callers someLocalVariable is copied (it's value not the object it references) and stored in aLocal
the statements of the method are executed
the first statement is a call to the same method implemented in the super class, the value of the reference in aLocal is passed to this method, and the reference returned by the call is stored into aLocal - replacing the reference previously stored there.
the second statement returns the value of the reference stored in aLocal as the method result, and that reference is stored into the caller's someLocalVariable.
None of that should be surprising, and the reference return is probably not the reference passed in (it could be, we've no idea what the inherited doSomething method does, it may just return what it was passed).
Now all you have to understand is that self is an implicitly passed parameter. What that means is the above method is effectively declared as:
- (NSString *) doSomething:(NSString *)aLocal selfRef:(instancetype)self
and Objective-C automatically supplies the reference passed as selfRef and stored into the method's local variable self.
Finally changing the name of doSomething to, say, initAndDoSomething changes the way ARC automatically handles the references passed as self and the one returned to ensure no unwanted objects get left lying around - this is done by implicitly adding the attributes mentioned in the original answer.
That's it, init methods are just methods. Don't think of them as special, it inflates their ego ;-)
HTH
Related
I am trying to understand the methods generated when properties are used.
Say I have the following declaration
#property int myint;
Now I know I could access this variables as such (say d was my instance of the class)
d.myint = 12; //this is equivalent to [d setMyint:12];
NSLog(#"The value is %d",d.myint); // what method is generated ?
What is the getter method called ? I was under the impression it was called getMyint however that isnt available ? Any suggestions if I might be missing something here?
As stated in the other answers, the proerty declaration gives you a getter and a setter for that instance variable for free! The notation is that you can either get [self myInt]; or self.myInt;. Both calls are 100% equivalent, i.e. they will both call the method - (int)myInt. This method is not visible (or rather, it's not explicitly implemented, see below) by default, however, you can implement it to provide some custom logic (e.g. check for specific values, error handling or lazy instantiation). If you want to override it, put this in your .m file.
- (int)myInt {
NSLog(#"getter of my int called, current value %d", _myInt);
return _myInt;
}
I only want to add to the the previous answers that in Objective-C, you have the possibility to rename your getters and setters when declaring the property, like so:
#property (getter=getMyInt) int myInt;
you can call those in the exact same way that you would use your normale getter:
int myInt = [self getMyInt];
// or
int myInt = self.getMyInt; // (will work but is not recommended since the compiler will interpret this as calling the getter of a property named `getMyInt` and only when this one is not found will actually fall back to the custom getter (thx to #NikolaiRuhe again for pointing this out))
Update:
Agreeing with most of what #NikolaiRuhe stated in his comment, here is a clarification of my answer referring to the mentioned issues:
This is indeed a typo, of course the way to use the property getter is by either calling [self myInt] or using dot notation self.myInt, and not [self getMyInt]. These calls are however 100% equivalent since they both invoke the actual getter.
About the visibility, indeed I should have been more explicit here. In OOP terms, visibility is a concept that describes the accessibility of instance variables from the outside of a particular class. I meant it exactly in the way that #NikolaiRuhe suggested, i.e. that this method is not explicitly implemented (so, it's not visible in the code by default). Sorry about this misunderstanding!
I am actually not sure about this point. For me this didn't make much of a difference in the past, I don't insist on this point. So I'd well acknowledge that the act of explicitly implementing a getter is not actually an override but rather a replacement of the synthesized method.
After explicitly renaming the getter to getMyInt like I suggested above, I don't see anything "wrong" with calling self.getMyInt. Why would this be the wrong way to access the property?
The getter method would be:
[d myInt];
Per the Apple docs :
You access or set an object’s properties via accessor methods:
NSString *firstName = [somePerson firstName];
[somePerson setFirstName:#"Johnny"]; By default, these accessor methods are synthesized automatically for you by the compiler, so you
don’t need to do anything other than declare the property using
#property in the class interface.
The synthesized methods follow specific naming conventions:
The method used to access the value (the getter method) has the same
name as the property. The getter method for a property called
firstName will also be called firstName.
The method used to set the value (the setter method) starts with the
word “set” and then uses the capitalized property name. The setter
method for a property called firstName will be called setFirstName:.
The syntax of getter method would be-
-(int)myint{
return myInt;
}
It will return myInt property of the receiver if this message i.e. d in your case.
If you are creating a property in objective-c, it creates 3 things for you.
an instance variable which you can access by using an underscore before the property name. Ex: _myint
a getter method which you can call directly by using the property name. Ex: [self myint]; / self.myint, this will actually call - (int)myint {} method.
a setter method which you can call by using a 'set' keyword before it. Ex: [self setMyint:12]; / self.myint = 12, this will actually call - (void)setMyint:(int)myint {} method.
Source
So when you write d.myint = 12; this is equivalent to writing [d setMyint:12];
And when you write NSLog(#"The value is %d",d.myint); this is equivalent to writing NSLog(#"The value is %d",[d myint]);
Custom Getters and Setters
Credits
You can also give custom names to your property Getters and Setters. This is how it is done
#property (getter=getMyInt, setter=setMyIntWithInt) int myint;
Ex:
[d setMyIntWithInt:12]; //This will set the instance variable to 12.
NSLog(#"The value is %d",[d getMyInt]);
Also, you can override these methods in your implementation(.m) file for error handling or lazy instantiation.
I have to perform a selector by name on a Class (not an instance) and use its return value:
id obj = [objClass performSelector:NSSelectorFromString(methodName) withObject:p1];
The selector creates a new instance of the Class. I need to use the returned instance. Obviously I get the usual performSelector may cause a leak because its selector is unknown warning since this project is compiled with ARC.
If I understand correctly (from the answers here and others), in this instance the performSelector will cause a leak (do correct me if I'm wrong, then I could just disable the warning and be done with it). The selectors are implemented as follows:
+ (id) objectWithFile:(NSString*)p1
{
return [NSKeyedUnarchiver unarchiveObjectWithFile:p1];
}
What are my options when I have to use selector from string and the selector creates and returns a new instance of the object?
I considered NSInvocation but its getReturnValue method requires me to provide my own allocated buffer in which the return value is stored. I'm not sure if this even works with ARC and class methods, or whether I simply have to __bridge_transfer cast the malloc'ed return value buffer to id and that's all there is to it.
objectWithFile: is not a method of the "alloc, copy, init, mutableCopy, and new family"
and therefore is
a "Unretained return values" method in the sense of the "Clang/ARC documentation":
A method or function which returns a retainable object type but does
not return a retained value must ensure that the object is still valid
across the return boundary.
...
In the worst case, this may involve an autorelease, but callers must
not assume that the value is actually in the autorelease pool.
So no matter what you do inside the method, the caller does not have to release the
returned object.
Therefore I don't think that you have a memory leak in your code.
I'm overriding - (BOOL) isEqual:(id)object in a custom class.
Out of the 4 choices, which are __weak, __strong, __autoreleasing, and __unsafe_unretained, which should I be using on the parameter for the isEqual: method signature?
I'm thinking this is where the problem is, since when I'm trying to add an instance of my class to a NSMutableDictionary, I'm getting an EXC_BAD_ACCESS(code=2, address=0x10) at the declaration of the method.
In other words, the line at which the debugger gets the EXC_BAD_ACCESS is:
- (BOOL) isEqual:(id __strong)object {
before any of the method body is executed.
The correct answer was "If you're getting bad access, then you're trying to read or write to an area that doesn't have what you think it has in it.", per #Dustin Rowland in the comments.
By default, ARC uses __strong, which means that the argument is held via a retain/release for the duration of its use inside the method. To lead to EXC_BAD_ACCESS, an object (either the argument itself, or any other object used in the method calls inside the isEqual: implementation) has to be over-released when accessing it. This cannot be fixed by changing the qualifier.
Sidenote: Be careful though by expecting to see anything to change when you change the qualifier. The compiler optimizations may decide that it is safe to skip some calls. For example, add the following code to a file and look at the assembly (Product -> Generate Output -> Assembly File) for Archiving (which uses -Os).
- (void)logObject:(id)o
{
NSLog(#"%#", o);
}
- (void)call
{
id o = [[NSObject alloc] init];
[self logObject:o];
}
Although the parameter of logObject: is the default __strong, no retain/release is done in the assembly output. Changing the parameter of -logObject: to __strong, __weak, __unsafe_unretained or __autoreleasing gives exactly the same assembly output. If you duplicate the line with the NSLog however, the assembly code changes for the different type qualifiers.
How would you return an object from a method, so it is read-only for the caller?
Please note that this isn't a property that can be simply set to read-only when it's getter is declared
i.e #property(nonatomic,retain,readonly) NSDate* pub_date;
For example:
-(SomeClass*)getObject
{
SomeClass* object = [[SomeClass alloc] init];
//Don't allow writing to 'object'
return object;
}
Thanks.
Short answer: there's no simple way of doing this.
Longer answer: Apple's framework defines a sort of standard for its collection classes where the immutable collection is the base class and the mutable collection is the inheriting class. So, for example, NSMutableArray inherits from NSArray. You can follow that standard, and have methods that return MyClass to clients while using MyMutableClass inside them. Technically the client can still send the mutating messages, of course, but IMHO that's not a big risk (after all, the client doesn't know your implementation details).
There are other, more complicated options - you can use pointer swizzling, or subclass and override all mutating methods, or simply copy the mutable class into an immutable counterpart (that's not complicated but may incur a performance hit). But for best results you should probably follow Apple's example.
It depends what the object is. If it has a mutable / immutable pair (like NSString/ NSMutableString) then your getter method can return the immutable version.
Otherwise, you can't control the behaviour of other objects - once you've returned an object, there is no control over it from the object that originally provided it.
If you are concerned that another object may alter an object returned from a getter, and thereby amend the property held within the original object, then you should return a copy of the object instead.
Example:
Object A has a mutable string property, object B asks for this mutable string, the getter directly returns the instance variable backing the property.
Object B then changes the string - the property of object A has also been amended because both objects have a pointer to the same mutable string.
In this case, you would return a copy of the object rather than the object itself. If your object is a custom one, you must implement the NSCopying protocol to allow this.
A further note - declaring a property as read only simply means that no setter accessor will be generated - i.e. objectA.property = newValue; will result in a compiler error.
I have a C struct that contains a function pointer. Now, I have used this setup within C with no problems, but now I'm using this C struct in Objective-C and I need to pass a function (or selector) pointer that is defined in the Objective-C class.
1. Here is what I have for the Objective-C selector that needs to be passed as a pointer to the C function:
- (void)myObjCSelector:(int*)myIntArray
{
// Do whatever I need with myIntArray
}
2. And here is where I run into a wall, Within Objective-C I'm trying to pass the selector as a pointer to the C function call: In place of "myObjCSelectorPointer" I need the proper syntax to pass the selector as a function pointer in this C function call:
passObjCSelectorPointerToCContext(cContextReference, myObjCSelectorPointer);
I did investigate this issue, but could mainly find several different ways of doing similar things, but I couldn't find anything specific for calling C functions and passing an Objective-C selector pointer.
In objc a selector is not a function pointer. A selector is a unique integer that is mapped to a string in a method lookup table stored by the objc runtime. In the above case your method name would be myObjCSelector: and to get the unique selector for it you would type #selector(myObjCSelector:). However this would be of no use to you because it doesnt represent a particular implementation of a function.
What youre looking for is IMP. Refer to this SO question.
EDIT 2:
IMP myObjCSelectorPointer = (void (*)(id,SEL,int*))[self methodForSelector:#selector(myObjCSelector:)];
Then you can call the method using
myObjCSelectorPointer(self,#selector(myObjCSelector:),myIntArray);
However, what this means you will need to make sure that you add the pointer to self in the c function call passObjCSelectorPointerToCContext.
So it should look like this
passObjCSelectorPointerToCContext(cContextReference, self, myObjCSelectorPointer);
when called from within the object that contains the method.
It is important to note though that using IMP is almost never the right technique. You should try to stick with pure Obj-C. Obj-C is quite efficient after the first call to a message because it uses temporal caching.
EDIT 1:
It's useful to understand why objc works in this way. The Apple documents explain it in depth. However a short explanation is as follows:
When you send a message to an object such as [myobject somemethod] the compiler won't immediately know which particular implementation of somemethod to call because there might be multiple classes with multiple overriden versions of somemethod. All of those methods have the same selector, irrespective of its arguments and return values and hence the decision about which implementation of somemethod is deffered to when the program is running. [myobject somemethod] gets converted by the compiler into a C function call:
objc_msgSend(myobject, #selector(somemethod))
This is a special function that searches each myobject class layout to see whether that class knows how to respond to a somemethod message. If not it then searches that class's parent and so on until the root. If none of the classes can respond to somemethod then NSObject defines a private method called forward where all unknown messages are sent.
Assuming that a class can respond to the somemethod message then it will also have a particular pointer of type IMP that points to the actual implementation of the method. At that point the method will be called.
There is considerably more to this procedure than I have described but the outline should be enough to help you understand what the goal of a selector is.
One final point is that the reason method names are mapped to unique integers via the #selector directive is so that the runtime doesn't have to waste time doing string comparisons.
Basically, the answer is: Objective-C selectors are different from function pointers. You need two pieces of data to perform a selector. That is an object and the selector itself. You will need some glue to accomplish your task.
Check this question.
Do you have to use a function pointer? In Objective-C, you can get the function pointer to an arbitrary method implementation (known as an IMP), but this is extremely uncommon, and usually not a good idea. Calling objc_msgSend() directly is also not the greatest idea, because there are several different variants of objc_msgSend(), and the compiler automatically chooses different ones to use based on the return type of the method. Methods that return an object go through objc_msgSend(), but objects that return structs might go through objc_msgSend() or they might go through objc_msgSend_stret(). And if the method returns a double, then it goes through objc_msgSend_fpret()...
Documentation: Objective-C Runtime Reference: Sending Messages
Instead, I might recommend using a target-action pair, or using a block. Then you might do something like:
myContextRef->target = anObjcObject;
myContextRef->action = #selector(invokeMe:);
And when you're done, do:
[myContextRef->target performSelector:myContextRef->action withObject:someReturnInformation];
Or maybe use a block:
myContextRef->completionHandler = [^(id returnInformation) {
[anObjcObject invokeMe:returnInformation];
} copy];
And then when you're done, do:
myContextRef->completionHandler(someReturnInformation);
(and don't forget to -release the block when you free the context)