Circular references in Objective-C and clang - objective-c

Why doesn't the static analyser detect circular references with blocks? I remember it used to do it when I had retains on my delegates instead of assign, pre-blocks introduction. I remember the nice little lines it used to draw on my code (i think...)
If I do this, without using weakSelf, I know I'm going to get a circular reference.
// Note 1: myObject is 'retained' by self.
// Note 2: myObject retains the block for the future
[self.myObject registerBlockOfCodeForFutureExectution:^{
[self doSomething];
}];
Sample Project Exploiting Issue
Now if I know this, and I'm a stupid human, then why doesn't my intelligent computer know this is bad and warn me that I'm being stupid?
There must be a logical reason why it can't detect it, and I want to know what that reason is.
This question is regarding clang and static analysis, please don't suggest how I fix circular references - I know how to do this.

If you use self inside of block it does not automatically mean that you get retain cycle. You get retain cycle only if life-time of block depends on life-time of self object. That may be the case if self has strong reference to myObject or some more complex dependencies are also possible (I assume that it indeed 'saves' block passed to a method, so you already have strong reference there).
So to have retain cycle in your example you need to have two following conditions met (neither of them follows from the code you posted), and compiler needs to be aware of them:
1. Life-time of myObject is tied to self - lets assume that self has strong reference to it
2. saveThisBlockInMyObject: retains block passed to it
I made a small sample that gives compiler warning about capturing self - to address 1st point I declared myObject as a strong property of some class:
#property (strong) MyTestClass* myObj;
...
self.myObj = [MyTestClass new];
For 2nd point I could not find a way to specify that method retains its argument (there're source annotations for returned values, but there's no relevant annotations for method parameters). But you declare block as a strong property of your test class, then compiler is happy to warn you about possible retain cycle:
typedef void (^MyVoidBlock)();
// MyTestClass
#property (nonatomic, copy) MyVoidBlock voidBlock;
self.voidBlock = ^{
[self doSomething]; // Warning!
};
Hope that makes sense :)

The code posted to github does cause a retain cycle.
Current github code:
#interface MyObject ()
#property (nonatomic, copy) dispatch_block_t codeToRunInFuture;
#end
#implementation MyObject
- (void) registerBlockForFuture:(dispatch_block_t)block {
self.codeToRunInFuture = block;
}
// Call in ViewController
self.myObject = [MyObject.alloc init];
[self.myObject registerBlockForFuture:^{
[self runThisInFuture];
}];
I can see where this would be difficult to catch since the Analyzer can not know what block might be and therefore can not tell if there is a self reference either strong or weak. It would have to examine all instances where registerBlockForFuture: is called and the block in each case.
The answer might be to submit a bugreport to Apple.

Related

Objective C: Differentiating iVars and Accessors

#interface RandomObject : NSObject
{
NSString* someObject; // I know I don't have to explicitly declare. Just to clarify my point.
}
#property (nonatomic, strong) NSString *someObject;
#end
#implementation RandomObject
#synthesize someObject;
#end
Given the code above and Xcode 4.3 is used (hence, no auto-synthesizing), here is my question.
The property/synthesize will create accessors for someObject, namely getter and setter. So if I want to assign a value to someObject, I can do this.
self.someObject = #"Tomato"; // [self setSomeObject: #"Tomato"];
If my understanding is correct, self will send #"Tomato" to setSomeObject method. But what if you do this?
someObject = #"Tomato"; // or maybe _someObject = #"Tomato" if you are doing auto-synthesizing
Directly accessing an iVar object seems like a bad idea, but since someObject is a private variable, within the same class you have access to that, right?
I understand why you would need to use self.someOject if you want to manipulate someObject from another class. But why is it that you'd need to do the same even though you are still in the same class. Why is it that it's a bad idea to directly access iVar.
Generally speaking accessors have more pros than cons and I use them everywhere I can.
The main issue is that every place you reference the ivar directly is another potential place your code will need to change.
For example imagine you have referenced someObject in multiple places throughout your class. Then the requirements change and now you decide that when the value of someObject is assigned you need to so some other work. Due to the fact that you have accessed the ivar directly throughout the class you now have to either duplicate this new code everywhere you assign someObject or refactor. If you was using an accessor you just have one piece of code to change
- (void)setSomeObject:(id)anObject
{
if (anObject != someObject) {
someObject = anObject;
[self doSomeWork];
}
}
You can have the same issue with the getter - imagine you store an array of objects in someObjects - this works great but then later down the line you decide that you don't actually need to store someObjects as it can be dynamically computed from other values. If you have directly accessed the ivar everywhere then this becomes a big chore. If you stick to abstracting someObject behind a getter then all you now have to do is
- (NSArray *)someObjects
{
return [self calculateSomeObjects];
}
This is exactly the idea with non-ARC code, which puts the memory management of the ivar in one place (behind accessors) so that you do not have to litter your code with repetitive code.
The property does more than just assigning an object to the ivar.
If you don't use ARC, the property will auto-generate retain/release code to handle memory management. Just calling someObject = #"Tomato" creates a memory leak (if someObject is assigned)
If your property is atomic, the property will provide thread safety, while accessing the ivar would not be thread safe.
See https://stackoverflow.com/a/589348/1597531 for examples of auto-generated property code.

How do I release properties that are added at runtime in a category?

Given the following category definition how might I handle -dealloc both with and without ARC? I am currently using ARC and to the best of my knowledge and poking around in Instruments, the properties are being cleaned up but I am not 100% confident in that.
#interface NSObject (SuperUsefulThingIWishAllNSObjectsHad)
#property (nonatomic, copy) NSString *foo;
#end
#import <objc/runtime.h>
#implementation NSObject (SuperUsefulThingIWishAllNSObjectsHad)
static const void *MyPropertyKey = &MyPropertyKey;
#dynamic foo;
- (NSString *)foo
{
return objc_getAssociatedObject(self,
MyPropertyKey);
}
- (void)setFoo:(NSString *)foo
{
objc_setAssociatedObject(self,
MyPropertyKey,
foo,
OBJC_ASSOCIATION_COPY);
}
This is more for my own edification but if the solution isn't too hacky I may have some places I actually want to use this.
You don't need to do anything special in dealloc to “clean up” an associated object. The runtime takes care of it for you. This is independent of ARC.
If you're not using ARC, you need to be sure to call [super dealloc] in your own dealloc overrides. But you need to do that regardless of your use of associated objects, and the compiler will warn you if you forget.
UPDATE
In response to your comment: You're right that the Objective-C Runtime Reference doesn't explicitly say the associated object is released (if appropriate based on the association policy) when the main object is deallocated. But that is the only reasonable action, because the point of an associated object is to attach a subordinate object to a main object without changing the main object's source code.
Anyway, the source code of the Objective-C runtime is open source, so we can inspect it to verify that this is indeed what's implemented.
Look at NSObject.mm and you'll see that -[NSObject dealloc] calls _objc_rootDealloc, which calls object_dispose.
The object_dispose function is in objc-runtime-new.mm, and it calls objc_destructInstance, which calls _object_remove_assocations.
The _object_remove_assocations function (yes, it has a typo in the source code) is in objc-references.mm. It removes all objects associated with the object being deallocated, releasing them if appropriate. If you look at objc_removeAssociatedReferences, which is part of the public API and is defined in objc-runtime.m, you 'll see that it also calls _object_remove_assocations.

Does the absence of a "likely to lead to a retain cycle" warning imply a strong reference cycle will not be created?

Per the transitioning to ARC release notes, when referencing self within a block one should use weak references in order to avoid a strong reference/retain cycle:
MyViewController *myController = [[MyViewController alloc] init…];
// ...
MyViewController * __weak weakMyController = myController;
myController.completionHandler = ^(NSInteger result) {
MyViewController *strongMyController = weakMyController;
if (strongMyController) {
// ...
[strongMyController dismissViewControllerAnimated:YES completion:nil];
// ...
}
else {
// Probably nothing...
}
};
Sometimes, I will get a compiler warning that referencing self in the block is likely to lead to a retain cycle. Does the absence of the warning imply that a retain cycle will not be created? Why is the warning qualified as "likely" to lead to a retain cycle?
Does the absence of the warning imply that a retain cycle will not be created?
No. The compiler is able to determine certain conditions from which you may create a retain cycle but it is impossible for it to rule out the possibility that you may create one. As an example consider the following class:
#interface MyClass : NSObject
#property (readwrite, strong) id myObject;
#end
and the code fragment in a different class:
MyClass *one = [MyClass new];
MyClass *two = [MyClass new];
one.myObject = two;
two.myObject = one; // created a strong cycle...
For a compiler to even spot this simple cycle requires flow analysis across multiple classes, and in general this problem is unsolvable by the compiler (you can scan for/spot the creation of cycles at runtime, ARC does not do this).
Why is the warning qualified as "likely" to lead to a retain cycle?
Creating a cycle itself is not wrong or bad. A cycle is only an issue if it becomes orphaned; i.e. no live references refer to it and it is only the cyclic references which cause the objects in the cycle to remain alive.
When the compiler sees a strong reference to self within a block being created it knows a live strong cycle will be created, but it cannot determine (i.e. unsolvable in general as above) whether that cycle will be later broken before the block is no longer required or whether the creating object and the block will form an orphaned cycle. Hence the use of a non-definitive "likely".

Why does the Xcode 4.5 static analyzer tell me that I have a potential memory leak when I try to use __attribute__((NSObject))

I have a property that holds a Core Foundation object, specifically a CFHTTPMessageRef. I've tried using the attribute((NSObject)) macro to tell the compiler to treat the referenced object as a normal NSObject and handle the retaining and releasing of that object for me rather than having to CFRelease myself. I've tried changing the property to weak instead of strong, but nothing seems to work, the static analyzer still tells me I have a memory leak, and from the looks of the output from CFGetRetainCount, it would that it's right. Does anyone know why my property would cause a memory leak:
typedef __attribute__((NSObject)) CFHTTPMessageRef HTTPMessageRef;
#interface ABRemoteConnection : NSObject
#property (strong) HTTPMessageRef message;
#end
- (void)dataReceived:(NSNotification *)notification {
self.message = CFHTTPMessageCreateEmpty(kCFAllocatorDefault, TRUE);
// do some stuff and if the message is complete, use it and release the
// message object
if (messageIsComplete(self.message)) {
self.message = NULL;
}
}
From the documentation, it looks like __attribute__((NSObject)) is only meant to be used with retain.
But switching strong to retain means you're now adding another ref which the prop is going to manage for you; there's still the original ref that you have to CFRelease.
If you think about it, this makes sense. Imagine doing the same thing with a property(retain) NSObject *:
- (void)dataReceived:(NSNotification *)notification {
self.o = [[NSObject alloc] init];
}
This works fine—but only because ARC sees the alloc and automatically inserts a corresponding release for you at the end of the scope. With a CF___Create function, there's no automatic CFRelease at the end of the scope, so you have to manually write one.
If you really want HTTPMessageRef to be as convenient as, say, NSDictionary, it can't just be a typedef; it has to be a toll-free bridged class.

IBOutlets, instance variables and properties: Best Practices

I've done all sorts of research today on best practices with regards to declaring IBOutlets and instance variables, managing them, using the correct accessors and properly releasing them. I'm pretty much there, but I've got some niche questions that I hope somebody will be able to advise the best practice on. I'll format them as code and comment the questions so as to make it easier to understand. I've excluded some obvious parts that I didn't think were relevant and can be safely assumed to work (like pre-processor stuff, #end, required implementation methods etc).
MyViewController.h
#class OtherViewController;
#interface MyViewController : UIViewController {
NSString *_myString;
BOOL _myBOOL;
}
// The first two properties aren't declared in the interface
// above as per best practices when compiling with LLVM 2.0
#property (nonatomic, retain) OtherViewController *otherViewController;
#property (nonatomic, retain) UIButton *myButton;
#property (nonatomic, copy) NSString *myString;
#property (readwrite) BOOL myBOOL;
MyViewController.m
#implementation MyViewController
// Synthesizing IBOutlets on iOS will cause them to be
// retained when they are created by the nib
#synthesize otherViewController;
#synthesize myButton;
// Assign instance variables so as to force compiler
// warnings when not using self.variable
#synthesize myString = _myString;
#synthesize myBOOL = _myBOOL;
- (void)viewDidLoad {
// QUESTIONS:
// 1. Ignoring convenience methods, can you still alloc and init in dot notation
// even when it's being properly synthesized?
self.myString = [[NSString alloc] initWithString:#"myString"];
self.myString = existingNSStringObject;
// 2. Should you always call methods for IBOutlets and instance variables using dot notation?
// Is there any difference seeing as these aren't directly invoking setters/getters?
[self.myButton setText:self.myString];
[myButton setText:self.myString];
[self.otherViewController.view addSubview:mySubview];
[otherViewController.view addSubview:mySubview];
[self.myButton setAlpha:0.1f];
[myButton setAlpha:0.1f];
self.myButton.alpha = 0.1f;
myButton.alpha = 0.1f;
// 3. How fussy are scalar variables in terms of getters and setters,
// given that there is a #synthesize declaration for them?
self.myBOOL = YES;
myBOOL = NO;
if(self.myBOOL) { ... }
if(myBOOL) { ... }
// 4. On instantiation of new view controllers from NIBs, should you use
// dot notation? (I haven't been doing this previously).
otherViewController = [[OtherViewController alloc] initWithNibName:#"OtherView" bundle:nil];
self.otherViewController = [[OtherViewController alloc] ... ]
}
- (void)viewDidUnload {
// 5. Best practice states that you nil-value retained IBOutlets in viewDidUnload
// Should you also nil-value the other instance variables in here?
self.otherViewController = nil;
self.myButton = nil;
self.myString = nil;
}
- (void)dealloc {
[otherViewController release];
[myButton release];
[_myString release];
}
I always declare and explicitly set a property's underlying instance variable. It's a little more work up front, but in my mind it's worth it to explicitly differentiate variables and properties and see at a glance what instance variables a class has. I also prefix instance variable names, so the compiler complains if I accidentally type property instead of object.property.
Calling alloc / init creates an object with a retain count of 1. Your synthesized property will also retain the object, causing a memory leak when it's released (unless you release your property right after, but that's bad form). Better to alloc / and release the object on a separate line.
Dot notation is effectively the same as calling [self setObject:obj]. Not using dot notation accesses the underlying instance variable directly. In init and dealloc, always access the instance variable directly as the accessor methods can include extra operations (such as key value observing notifications) that are not valid when the object is being created or destroyed. All other times use the synthesized accessor methods. Even if you're not doing anything special now, you might later override these methods later to change what happens when the variable is set.
Scalars work the same way, only you don't have to worry so much about memory.
One accesses the synthesized accessor methods, the other accesses the instance variable directly. See questions one and two again, and be careful about memory leaks!
The view controller may be pushed onto the screen again, in which case your viewDidLoad method will be called a second time. If you're setting initial values in viewDidLoad, go ahead and set your properties to nil here. This makes sense for properties that use a lot of memory and aren't going to affect the state of the view. On the other hand if you want the property to persist until you're sure it's no longer needed, create it in your init method and don't release it until dealloc.
1) You've slightly misunderstood #synthesize. #synthesize does nothing with the object. It only tells the compiler to generate the getter and setter methods according to the options used in your #property declaration
// Synthesizing IBOutlets on iOS will
cause them to be
// retained when they
are created by the nib
The outlets aren't retained (outlets are just notices to interface builder and don't affect the code), the objects are retained when the setter generated by #synthesize is used. When the nib is loaded, the loading system calls your generated setter.
2) Deciding whether to use accessors in objective C is no different from deciding to use accessors in any other object oriented language. It is a choice of style, need and robustness. That the accessor is serving as an IBOutlet makes no difference.
But in objective C I would suggest you should NOT use accessors in two places: dealloc and within the var's accessor method itself.
And if you ARE using the accessors in init then you need to be careful about your retain counts.
self.myString = [[NSString alloc] initWithString:#"myString"];
This line leaks memory. Using your copy accessor retains the object, so you should release it here after creating it.
3) Not sure what you mean by fussy. Possibly see answer to 2)
4) See 2) and be careful about memory management. If you call alloc/init you are now responsible for releasing the object - this is entirely independent of the retains/releases used by accessors and dealloc.
5) No, you should not nil other instance variables in viewDidUnload. Your controller is expected to maintain its state even if the view goes away. viewDidUnload is only for cleaning up potentially memory-heavy view objects when the controller's view is not currently on screen.
Consider a navigation controller. View controller 1 is on the stack and then view controller 2 is pushed and is now visible. If memory conditions get low, the system could attempt to unload view controller 1's view and will then call viewDidUnload.
Then popping view controller 2 will not create the view controller 1 object again, but it WILL load view controller 1's view and call viewDidLoad.
Re comments
2) That's exactly right - you can use a convenience constructor or release immediately after your alloc/init and assignment, or release before the block exits, or autorelease. Which you choose is mostly a matter of style (though some would argue against autorelease - but not me!)
3) There are accessors for scalars - you have created some in your code
#property (readwrite) BOOL myBOOL;
This creates methods myBOOL and setMyBOOL on your class.
Remember that there is nothing special about dot notation. It is only a convenience and when the code is compiled myObject.property is exactly equivalent to [myObject property] and myObject.property = x is exactly equivalent to [myObject setProperty:x]. Using dot notation is purely a style choice.
Dot notation and brackets notation are pretty much the same.
By self.myVariable you are accessing the getter of the property of the instance variable myVariable and by myVariable you are accessing the local variable. They're not the same thing.
You can customize the setters and the getters by overriding the methods and specific some certain conditions for them.
See first answer ( brackets are preferred - better understanding of the code )
Better make a separate method.
Like:
- (void) releaseOutlets {
self.firstOutlet = nil;
self.mySecondOutlet = nil;
……………………
self.myLastOutlet = nil;
}
and then call this method both in viewDidUnload and in dealloc methods.
Hope it helps !