I have a property that sometimes needs to be a strong reference, and other times needs to be a weak reference. I thought I'd cracked it with the following custom getter/setter:
- (PropertyData *)property
{
return _strongProperty? _strongProperty : _weakProperty;
}
- (void)setProperty:(PropertyData *)newProperty
{
_strongProperty = newProperty;
_weakProperty = nil;
}
- (void)weaken
{
if (_strongProperty != nil) {
_weakProperty = _strongProperty;
_strongProperty = nil;
}
}
Previously there was an ivar called property and an #synthesize property. I removed both and replaced with:
PropertyData __weak *_weakProperty;
PropertyData *_strongProperty;
The class using this class calls weaken when it wants to convert to a weak reference to prevent a retain cycle.
This all works fine on iOS, but running the same code on OS X doesn't work at all. In the debugger, setProperty: has no effect on either of the new ivars right from the outset, and it crashes before weaken is ever called.
I'm confused about whether you need a #synthesize a=b statement when writing custom getter/setters (deployment target OS X 10.10). Not obvious how to do that in this case because there are two backing ivars.
Follow the conventions, or you confuse anyone including yourself.
Start your instance variables with an underscore. Don't use synthesise.
Apart from that, you have two problems. One, calling weaken twice sets the property to nil. Second, there's a good chance that your property has only one reference count and goes away when you call weaken.
Related
What does self mean in Objective-C? When and where should I use it?
Is it similar to this in Java?
self refers to the instance of the current class that you are working in, and yes, it is analagous to this in Java.
You use it if you want to perform an operation on the current instance of that class. For example, if you are writing an instance method on a class, and you want to call a method on that same instance to do something or retrieve some data, you would use self:
int value = [self returnSomeInteger];
This is also often used for accessor methods on an instance (i.e. setters and getters) especially with setter methods, if they implement extra functionality rather than just setting the value of an instance variable, so that you do not have to repeat that code over and over when you want to set the value of that variable, for example:
[self setSomeVariable:newValue];
One of the most common uses of self is during initialization of a class. Sample code might look like:
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
This invokes the superclass's (via super) initializer, which is how chained initialization occurs up the class hierarchy. The returned value is then set to self, however, because the superclass's initializer could return a different object than the superclass.
self is an implied argument to all Obj-C methods that contains a pointer to the current object in instance methods, and a pointer to the current class in class methods.
Another implied argument is _cmd, which is the selector that was sent to the method.
Please be aware that you only get self and _cmd in Obj-C methods. If you declare a C(++) method, for instance as a callback from some C library, you won't get self or cmd.
For more information, see the Using Hidden Arguments section of the Objective-C Runtime Programming guide.
Yes, it's exactly the same as "this" in Java - it points to the "current" object.
Two important notes:
The class itself, e.g. UIView (I'm NOT talking about a UIView object) is itself an object, and there is a self associated with it. So for example, you can reference self in a class method like this:
// This works
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Class method!
+(void) makeTheMostOfYourself { }
Note that the compiler does NOT raise any warnings or errors, even if the self you mean to reference is an object and not a class. It is VERY easy to cause crashes this way, for example:
// This will crash!
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Object method!
-(void) makeTheMostOfYourself { }
// This will crash too!
-(void) showYourself2 { [self performSelector: #selector(makeTheMostOfYourself2)]; }
// Class method!
+(void) makeTheMostOfYourself2 { }
Sadly, this makes class methods a bit harder to use, which is unfortunate because they are a valuable tool for encapsulation through information hiding. Just be careful.
Wow, that many half-correct answers and misleading hints. This let me answer the Q even there is a accepted answer for years:
First of all: It is really hard to compare a concept of messaging/calling in the context of an early binding, static typing language as Java with a late binding, dynamically typing languages as Objective-C. At one point this will break. I would say: No, this is not similiar, since the typing and dispatching concepts of both language are fundamental different so nothing can be similar to the other one. However, …
Then we should differ between the "two sides" of self.
A. Using self
When you use it in a message, it is simply an object reference as any other:
[self doSomething];
[anotherObject doSomething];
Technically both lines works identically (accept of having a different receiver, of course). This especially means, that the first line does not lead to an execution of a method inside the class of self, because self does not necessarily refer to "that class". As every message inside Objective-C (single exception: messages to super)this can lead to the execution of a method in a subclass:
#interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
#end
#implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
- (void)doAnotherThing
{
NSLog( #"B" );
}
In a code like this
B *b = [B new;]
[b doSomething];
The line
[self doAnotherThing];
in class A will lead to the execution of -doAnotherThing (B), because messages to self are late bound as every other message. The result on the console will b "B", not "A". Using self as a receiver you should not think of a single special rule. There is completely none.
(And the above example is a very good example for using self in class methods, because the same situation can occur on class methods. Using the class itself breaks polymorphism, what is one of the worst idea at all in OOP. DO use self in class methods, too.)
B. Getting self
What is self pointing to? It points to the object to whom the message is sent that caused the execution of the current method.
Having …
…[someObject doSomething]… // some object is a reference to an instance object
… as a message, a method is called, in the most simple case …
- (void)doSomething
{ … }
In such a case, self can point to an instance of the class, the method belongs to. And it can point to an instance of a subclass, the method belongs to, too. You don't know. (And this information is preserved using self to send a message as explained above.)
If the message is sent to a class object, self points to the class object, that was the receiver of the message. This is completely analogous. Therefore it is possible that self points to a subclass object:
#interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
#end
#implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
+ (void)doAnotherThing
{
NSLog( #"B" );
}
Having this classes
…[A doSomething]…
self inside -doSomething (A) points to the class object of B. Therefore [self doAnotherThing] of B(!) is executed. This is clearly different from
+ (void)doSomething
{
[A doAntoherThing];
}
The latter version causes relevant harm to the principles of OOP.
As a side note it is possible that self inside a class method of a root class points to an instance object of the root class or any subclass. You have to keep this in mind, when writing categories on NSObject.
self is an object pointer to the current instances dispatch table. It is an implicit first argument to every member function of an object, and is assigned when that function is called.
In functions like init, you need to be careful that when you call the super class init you reassign self to be the return value as the super class init may redefine what self points to.
super is similar to self except it points to the superclass dispatch table.
I know the instance variable in ARC are by default __strong. How can I release an instance variable when the containing class is still retained. In the following example v is __strong
and c is allocated when object of A is created some where and retained. I want to release the
c instance variable. How to should I do that?, What should be in releaseC method that will release the c instance variable.
#interface A {
Obj *c;
}
#implementation A {
- (id)init {
if((self = [super init])){
c = [[Obj alloc] init];
}
return self;
}
- (void)releaseC {
//what should be here?
}
}
Obj *c; = [[Obj alloc] init];
- (void)releaseC {
c = nil;
}
You cannot directly control when an object is released BUT you can indirectly cause it to happen. How? Remember what ARC does EXACTLY. Unlike human coding convention, ARC parses your code and inserts release statements AS SOON AS OBJECTS CAN be released. This frees up the memory for new allocations straight away, which is awesome/necessary. Meaning, setting an object to nil, or simply allowing a variable to go out of scope ... something that CAUSES A 0 RETAIN COUNT forces ARC to place its release calls there. It must ... because it would leak otherwise.
- (void)releaseC {
c = nil;
}
c = nil;
But some would argue it isn't productive from an efficiency standpoint. And while the release will be immediate in the sense it isn't any longer usable, the memory may not be freed immediately.
there is no need to release the variable in ARC. it done automatically
You are probably miss understanding what you want to do. I suppose you want to release the variable for memory issues. All you have to do is nil it. Instance variables are pointers to objects. As long as an object is pointed by something it is kept alive. As soon as you dont need something you can "stop pointing at it" and it will be released automagically.
As for the design, I am not so sure why you would have a public method that releases an instance variable. (I'm assuming its public because if it was not you would just nil it without actually having to write a method). If you do indeed intend to be able to release an instance variable from outside the class, I would simply make the Instance variable public and release it from anywhere setting it as nil.
I've linked a button to the following method:
- (IBAction)searchButton
{
NSString *searchText = _searchField.text;
NSLog(#"lol");
[_search testSearch:searchText];
}
The last line calls the method testSearch within an object named search, defined as follows:
#property (strong, nonatomic) Search *search;
Within Search, testSearch is defined as follows:
-(void)testSearch:(NSString *)testString
{
NSLog(#"HELLO");
}
My final output, when I click search, is only "lol" (each time I click the button). It does NOT print "HELLO", as testSearch should be doing. I have included testSearch in Search.h, so it should be accessible...why isn't this method being called?
You should start by initializing your _search ivar to an instance of Search in your designated initializer (or in viewDidLoad or some other "user gonna use this" method).
- init {
if ((self = [super init])) {
_search = [[Search alloc] init];
}
return self;
}
You should generally avoid lazy initialization in getter methods for a variety of reasons:
It adds unnecessary code; use #property and the default synthesized implementations. Leads to simpler code and less of it.
a getter that does lazy initialization yields a getter that causes mutation. That is inconsistent it is quite odd to see a KVO change notification when calling a getter (unless, of course, you don't fire the KVO notification... at which point, you have non-observeable mutation).
a getter that causes mutation is inherently not thread safe unless you add the code, tricky code, to make it so.
lazy initialization is generally a premature optimization. Unless you have an identifiable memory or CPU performance issue caused by initializing a resource "too soon", then adding the complexity of lazy initialization is wasted effort.
lazy initialization can lead to weird ordering dependencies and other complexities. Far better to have a known entry point for initializing a subsystem than to rely on subsystem X being initialized prior to Y, both by side effect.
The search object you are sending the message to has not been instantiated so you are sending a message to nil. In Obj-C this does not crash the program, instead it does nothing. Its a best practice in Objective-C programming to perform lazy instantiation in the getter method of the iVar. Additionally, you would have to couple this best practice with not accessing your iVars directly and use the setters and getters for whichever iVar you are trying to access. Below is an example of lazy instantiation in the getter method for your search iVar:
-(Search *)search
{
if(!_search){
_search = [[Search alloc]init];
}
return _search;
}
Here is your method call while NOT accessing the iVar directly:
[search testSearch:searchText];
I get the above message in XCode 4.6. I've done a pretty thorough search and but nothing seems to match the exact circumstances surrounding my issue. Admittedly, I'm relatively new to iOS dev, and memory-management has never been my strong suit, but this just has me completely miffed.
I have an instance variable theLink which is defined in the class Game as follows:
#interface Game : NSObject
// Class objects
#property(nonatomic,retain) NSMutableArray *queryItems;
#property(nonatomic,retain) NSMutableArray *theArray;
#property(nonatomic,retain) NSString *theLink;
#property(nonatomic,retain) NSString *thePath;
theLink is set in the makeGame method which is called in the method initialiseGame in my view controller:
- (void) initialiseGame
{
bool gameCreated = FALSE;
while (!gameCreated)
{
gameCreated = [theGame makeGame:#"ptl"];
}
[loadingIndicator stopAnimating];
[loading setText:#"Tap to Start"];
[self performSelector:#selector(setLabels) withObject:nil afterDelay:0.0];
}
(Note: the performSelector afterDelay is used to allow the view to update before continuing. Bit of a hack but I couldn't work out a better way!)
The app then loads the game, and when the user taps the screen to start, the next method which is called from the view controller is:
- (void) setupLink
{
...
for(int i=0; i<[theGame.theLink length]; i++) {
...
}
}
It is on this reference to theGame.theLink where I'm am getting the crash.
What has me most confused is that if I call theGame.theLink from inside the initialiseGame method, it is displays correctly, and also calling any other variable from the Game class (such as thePath or theArray works perfectly, so theGame object has not been deallocated in it's entirety, only the variable theLink.
It seems to me that the variable is being deallocated somewhere as the view controller is being updated. I haven't released the variable, and can't work out why only this variable is being deallocated. As I said at the start, memory-management is not my strength!
Any help/ideas would be hugely appreciated. Let me know if you require any more details.
Thanks heaps,
Andrew
EDIT: Setting of theLink within makeGame
- (bool) makeGame:(NSString*)gameType
{
...
[self getLink];
}
- (void) getLink
{
...
if (... && ((arc4random() % 10) > 8))
{
theLink = #"Animals";
}
}
There are many different ways theLink may be set, depending on random numbers and other factors. This is the most basic form which simply sets it to a static string. It doesn't matter how theLink is set or what it is set to, the program always crashes at the same point.
If theLink is being set to the parameter being passed to it ,#"ptl" or some similar temporary string, it will give you a problem, because it is just a pointer pointing at the current location that is holding #"ptl". After the makeGame method is completed, your system will assume that it is all done with #"ptl" and just free it up.
When you make an #"stringwhatever" in your code, it is supposed to be the equivalent of making an NSObject that is an immutable literal instance of #"stringwhataver". It should, in theory handle all the reference counting in a nice way, but when you are doing your own memory management, there are so many ways to lose count of your references.
There's a pretty simple rule to follow. If you've declared properties, access them via the property. To do otherwise (as you are doing above, with theLink = ...) bypasses all of the memory management built into the property accessors.
self.theLink = ...
Would have solved this problem under MRC. Switching to ARC has "solved" your problem without you understanding the root cause.
I have a situation where troops can attack buildings. Each troop keeps a pointer to its target.
#property (nonatomic, weak) Building *target;
In an update loop, the troops periodically cause damage to their target.
if (_target)
{
if (/*enough time has passed since last attack, attack again*/)
{
[_target attack];
if (_target.health <= 0)
{
[_target removeFromParentAndCleanup:YES]; //Cocos2d
_target = nil;
}
}
}
else /* Find new target */
The problem is:
troop1 deals the blow that fells building1 and moves on to building2
troop2 was attacking building1 but waits until its next attack to determine that building1 is now nil.
I realise the problem is that troop2's pointer has not been set to nil and instead I should be checking that the value of the pointer is nil.
I tried using if (*_target) but was met with the message
Statement requires expression of scalar type
If there a way to achieve this kind of comparison in Objective-C? What other options are there for determining when a value has changed? KVO? Some extensive delegate pattern?
It is the pointer itself that is set to nil when the object it points to is deallocated. if (objectPointer == nil) is always the way to check if an object is nil in Objective-C/Cocoa. If the pointer is not nil, it means the object in question has not in fact been deallocated. If you dereference a pointer to an object, you get a struct, hence the compiler error about needing a scalar value in the if expression.
So, in your case, if if(self.target != nil) is not giving you the result you expect, you should look for remaining strong references to the target (from other objects).
More broadly, as hinted at by trojanfoe's answer, you're relying on ARC's zeroing weak reference behavior for real program logic. In theory this is OK, as (contrary to his initial statement), ARC's zeroing weak behavior is reliable/deterministic. But, it does mean that you have to ensure that targets are always deallocated when they're no longer on the playing field (or whatever). This is a bit fragile. Zeroing weak references are intended as a way to avoid retain cycles (essentially a form of memory leak), rather than as a way to implement logic the way you're doing. The gist of trojanfoe's solution, where you explicitly register and unregister targets as necessary, is probably a more robust solution.
There may be something that I have overlooked here, but to check if the target2 property is nil, just do:
if ( self.target2 == nil ) {
// Something
}
I think you are relying too heavily on the implementation of ARC in that you only know if an object has been removed if the pointer is nil. This is non-portable and can you make any guarantee between the object being released and the pointer becoming nil?
Instead, use a central dictionary of objects, mapped against their unique ID and store just this unique ID rather than the object pointer itself. In this example I'm using a NSNumber for the key using an incrementing integer, but there are probably better keys that can be used. Also Object is the base class of any object you want to store in this dictionary:
// Probably ivars in a singleton class
unsigned _uniqueId = 1;
NSMutableDictionary *_objects;
- (NSNumber *)addObject:(Object *)object
{
NSNumber *key = [NSNumber numberWithUnsignedInt:_uniqueId++];
[_objects setObject:object forKey:key];
return key;
}
- (void)removeObjectForKey:(NSNumber *)key
{
[_objects removeObjectForKey:key];
}
- (Object *)getObjectForKey:(NSNumber *)key
{
return [_objects objectForKey:key];
}
And in your target, simply store the building key:
#property (strong) NSNumber *buildingKey;
and get the building via the methods provided:
Building *building = (Building *)[objectDictionary objectForKey:buildingKey];
if (building != nil)
{
// building exists
}
else
{
// building does not exist; throw away the key
buildingKey = nil;
}
Since target is a weak reference, your code should work "as-is", assuming that [_target removeFromParentAndCleanup:YES]; removes all strong references to the target.
When the last strong reference is removed, all of the weak properties pointing to it will automatically be set to nil. If they are not automatically set to nil, then there is still a strong reference to the target somewhere.
Find and remove that reference, and this will work fine.