I came across this scenario where my app was crashing with exec_bad_access when I call a block on a nil object. I was able to fix the issue by add a if condition but I want to know why calling block on a nil object causes bad_access?
#interface CustomView :UIView
#property (nonatomic, strong) UIImage* sourceImage;
#property (nonatomic, copy) void(^doneSwipingBlock)();
- (void)testMethod;
#end
//Another Class
//Sample Code (this is not the actual code but shows the crash
CustomView view = nil;
view.sourceImage = [UIImage imageNamed:#"image.png"]; //no error as view is nil
[view testMethod]; //no error as view is nil
view.doneSwipingBlock(); //Crashes here
/*
//This works fine
if (view.doneSwipingBlock) {
view.doneSwipingBlock();
}
*/
Because while blocks are objects, operations on blocks should not be perceived as respecting Objective-C semantics. Just like reading from NULL causes a bad access, invoking a NULL block causes a bad access. This is consistent with the behavior of a function pointer (calling a NULL function pointer crashes your program), and since blocks are available in C and C++ as well, it may have made more sense to use this behavior than a purely Objective-C behavior.
The invoke method is not called through objc_msgSend, which handles and cancels calls to nil objects on Objective-C objects.
Blocks are variables, not methods. You can expect the same things out of a block property than you can out of an int property. They're just like you had some class called Block that had an invoke method on it, and you subclassed it every time you needed it to do something different, except that the compiler does all the subclassing part.
Related
First of all my task is to download something via a socket with HTTP protocol. For that I chose to open a socket connection with GCDAsyncSocket which works fine. Also the http-protocol implementation works fine.
The class is structured basically like this:
//REQUEST OBJECT
#implementation HttpRequest{
//completion and fail block which will be called to the receiver
void (^_failBlock)();
void (^_completionBlock)();
}
-(void)performRequest:completionBlock andFailBlock:failBlock{
//assigning blocks for later use
_completionBlock = completionBlock;
_failBlock = failBlock;
//start the request
}
-(void)receiveAsyncSocketCallback{
//receive the answer and parse it
// if the request is complete call completionBlock or failBlock
}
My problem is that my request object gets deallocated instantly after I start the request like this (and not holding a strong reference to it):
-(void)viewDidLoad{
HttpRequest* request = [[HttpRequest alloc] init];
[request performUrlRequest:#"https://someurl.com/someFile"
completionBlock:^(int statusCode, NSDictionary *httpHeader, NSData *body) {
//Do something with the retrieved data
}
failBlock:^(int statusCode, NSDictionary *httpHeader, NSData *body) {
//connection failed for some reason
}];
}
What I understand is that no object is retaining my request object because I don't hold a strong reference from any other object on it. Okay.
But my previous understanding was that when I implement a code block in another object which is still alive this will retain my request object until the code block is called. And I have done this in other projects where it worked exactly like that but I cannot spot the difference.
To avoid the deallocation of the object I could assign it to some ivar in the object where I created it and where I need the response of that request. But I don't like to hold those references because it feels kind of senseless so I choose to let the object retain itself with
__strong HttpRequest *_retained_self;
which I also don't like because of potential memory leaks. I feel like I am missing a good architecture here.
Can someone give me a proposal for how to lay out that correctly?
Make them as properties with (copy) and then implement dealloc method where you set them nil to avoid memory leaks.
If you are accessing request inside of the two blocks, you are fine when you copy the block. The runtime will than keep strong references to the object. The easiest way to do this is to use properties with type copy for the blocks. Strong references to the blocks are not enough.
#property (copy, nonatomic) void (^failBlock)();
#property (copy, nonatomic) void (^completionBlock)();
Well I'm just confused when the lazy instantiation should be used.
I understand the basic concept of lazy instantiation though.
" I understand that all properties start out as nil in Objective-C and that sending a message to nil does nothing, therefore you must initialize using [[Class alloc] init]; before sending a message to a newly created property. "(Lazy instantiation in Objective-C/ iPhone development)
m.file:
#property (strong, nonatomic) NSMutableArray *cards;
- (NSMutableArray *)cards
{
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
- (void)addCard:(Card *)card atTop:(BOOL)atTop
{
if (atTop) {
[self.cards insertObject:card atIndex:0];
} else {
[self.cards addObject:card];
} }
Well, what I really don't get is when I'm supposed to use this type of instantiation?
Mostly I see the code like this:
h.file:
#interface Card : NSObject
#property (strong, nonatomic) NSString *contents;
m.file:
if([card.contents isEqualToString:self.contents]){
score = 1;
}
*This might be a stupid question but I'm really confused. I'm new here, Thanks.
There is no reason to use Lazy Instantiation/Lazy Initialization if you find it confusing; simply initialize your instance variables/properties in the class init methods and don't worry about it.
As the object is created as a side-effect of calling the getter method, it's not immediately obvious that it is being created at all, so one alternative, which would also mean you can use the default compiler-generate getter method, is to explicitly check for it in addCard:
- (void)addCard:(Card *)card
atTop:(BOOL)atTop
{
if (!self.cards)
self.cards = [NSMutableArray new];
if (atTop) {
[self.cards insertObject:card atIndex:0];
} else {
[self.cards addObject:card];
}
}
(and removing the user-supplied getter method)
However the net-effect is the same as the code you posted, with the exception that self.cards will return nil until addCard is called, however I doubt this will cause a problem.
When using dot notation to access your instance variables, you are calling your getter method for that given property. Therefore, by using dot notation and lazy instantiation, your getter will always assert that a property is not nil before you send it a message. Therefore, code such as
[self.cards insertObject:card atIndex:0];
will actually call the getter at self.cards; if you use dot notation on your objects and program the getters accordingly, you will always ensure that your instance variables are allocated and initialized, while simultaneously cleaning up your init method for code that is much more important.
Lazy instantiation is a common practice among Objective-C programmers; I suggest getting into the flow of the convention.
EDIT: thanks for Raphael mentioning this in a comment previously.
Lazy instantiation is a performance enhancement in certain types of scenarios. One example would be a class that has a very expensive user facing UI string.
If you create many of instances of that class but only a very small subset of those instances will be shown in your UI, you waste a lot of CPU resources creating a very expensive UI string that rarely will be used.
I have a class that creates an object lazily and stores it as a weak property. Other classes may request this object, but must obviously keep a strong reference to it to keep the object from being deallocated:
// .h
#interface ObjectManager
#property(nonatomic, weak, readonly) NSObject *theObject;
#end
// .m
#interface ObjectManager ()
#property(nonatomic, weak, readwrite) NSObject *theObject;
#end
#implementation ObjectManager
- (NSObject *)theObject
{
if (!_theObject) {
_theObject = [[NSObject alloc] init];
// Perform further setup of _theObject...
}
return _theObject;
}
#end
When the scheme is Xcode is set to build for Debug, things work just fine - an object can call objectManagerInstance.theObject and get back theObject.
When the scheme is set to build for Release, theObject returns nil:
// Build for Debug:
NSObject *object = objectManagerInstance.theObject;
// object is now pointing to theObject.
// Build for Release:
NSObject *object = objectManagerInstance.theObject;
// object is now `nil`.
My guess is that the compiler is optimising my code by seeing that _theObject is not used further in the accessor method itself, so the weak variable is being set to nil before returning. It seems that I would have to create a strong reference before actually returning the variable, which I can only think to do using a block, but would be messy and I'd rather avoid it!
Is there some kind of keyword I can use with the return type to stop the ivar from being nilled so soon?
Most likely, DEBUG builds cause the object to sit in the autorelease pool long enough to cause it to "work" whereas a RELEASE build causes the optimizer to do a bit more control flow analysis which subsequently eliminates the autorelease chatter.
Frankly, that the compiler isn't spewing a warning in the release build saying that the code can never work is a bug (please file it as you have a great, concise, example)!
You'll need to maintain a strong reference somewhere to the object until whatever needs a strong reference has an opportunity to take a reference.
I'm wondering if something like this might work:
- (NSObject *)theObject
{
NSObject *strongObject;
if (!_theObject) {
strongObject = [[NSObject alloc] init];
_theObject = strongObject;
// Perform further setup of _theObject...
} else {
strongObject = _theObject;
}
return strongObject;
}
I.e. the above would be more akin to a factory method that returns an autoreleased object while also maintaining a weak reference internally. But the optimizer might be too clever by half and break the above, too.
You're being bitten by the optimizer.
Since _theObject is a weak reference, the system is free to get rid of it, and zero out your weak reference, whenever it's not retained. But it's not required to do it right away.
In your lazy instantiator, the newly-created object is never retained. The optimizer sees this, and says "Wow! I can zero this reference at any time! Why don't I do it...right now!" And before you know it, you're returning nil.
What you want to do is assign the lazily-instantiated object to a local variable, for an implicitly strong reference that lasts for the scope of the function. You also want to tell the compiler that you really do want the full scope, using the objc_precise_lifetime annotation.
For details from the standard, see this page.
I need to perform an action in the dealloc method of a category. I've tried swizzling but that doesn't work (nor is it a great idea).
In case anyone asks, the answer is no, I can't use a subclass, this is specifically for a category.
I want to perform an action on delay using [NSTimer scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:] or [self performSelector:withObject:afterDelay:] and cancel it on dealloc.
The first issue is that NSTimer retains the target, which I don't want. [self performSelector:withObject:afterDelay:] doesn't retain, but I need to be able to call [NSObject cancelPreviousPerformRequestsWithTarget:selector:object:] in the dealloc method or we get a crash.
Any suggestions how to do this on a category?
I still think it would be better to subclass your class and not mess with the runtime, but if you are definitely sure you need to do it in a category, I have an option in mind for you. It still messes with the runtime, but is safer than swizzling I think.
Consider writing a helper class, say calling it DeallocHook which can be attached to any NSObject and perform an action when this NSObject gets deallocated. Then you can do something like this:
// Instead of directly messing with your class -dealloc method, attach
// the hook to your instance and do the cleanup in the callback
[DeallocHook attachTo: yourObject
callback: ^{ [NSObject cancelPrevious... /* your code here */ ]; }];
You can implement the DeallocHook using objc_setAssociatedObject:
#interface DeallocHook : NSObject
#property (copy, nonatomic) dispatch_block_t callback;
+ (id) attachTo: (id) target callback: (dispatch_block_t) block;
#end
Implementation would be something like this:
#import "DeallocHook.h"
#import <objc/runtime.h>
// Address of a static global var can be used as a key
static void *kDeallocHookAssociation = &kDeallocHookAssociation;
#implementation DeallocHook
+ (id) attachTo: (id) target callback: (dispatch_block_t) block
{
DeallocHook *hook = [[DeallocHook alloc] initWithCallback: block];
// The trick is that associations are released when your target
// object gets deallocated, so our DeallocHook object will get
// deallocated right after your object
objc_setAssociatedObject(target, kDeallocHookAssociation, hook, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return hook;
}
- (id) initWithCallback: (dispatch_block_t) block
{
self = [super init];
if (self != nil)
{
// Here we just copy the callback for later
self.callback = block;
}
return self;
}
- (void) dealloc
{
// And we place our callback within the -dealloc method
// of your helper class.
if (self.callback != nil)
dispatch_async(dispatch_get_main_queue(), self.callback);
}
#end
See Apple's documentation on Objective-C runtime for more info about the associative references (although I'd say the docs are not very detailed regarding this subject).
I've not tested this thoroughly, but it seemed to work. Just thought I'd give you another direction to look into.
I just stumbled on a solution to this that I haven't seen before, and seems to work...
I have a category that--as one often does--needs some state variables, so I use objc_setAssociatedObject, like this:
Memento *m = [[[Memento alloc] init] autorelease];
objc_setAssociatedObject(self, kMementoTagKey, m, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
And, I needed to know when the instances my category extending were being dealloced. In my case it's because I set observers on self, and have to remove those observers at some point, otherwise I get the NSKVODeallocateBreak leak warnings, which could lead to bad stuff.
Suddenly it dawned on me, since my associated objects were being retained (because of using OBJC_ASSOCIATION_RETAIN_NONATOMIC), they must be being released also, and therefore being dealloced...in fact I had implemented a dealloc method in the simple storage class I had created for storing my state values. And, I postulated: my associated objects must be dealloced before my category's instances are! So, I can have my associated objects notify their owners when they realize they are being dealloced! Since I already had my retained associated objects, I just had to add an owner property (which is not specified as retain!), set the owner, and then call some method on the owner in the associated object's dealloc method.
Here's a modified part of my category's .m file, with the relevant bits:
#import <objc/runtime.h> // So we can use objc_setAssociatedObject, etc.
#import "TargetClass+Category.h"
#interface TargetClass_CategoryMemento : NSObject
{
GLfloat *_coef;
}
#property (nonatomic) GLfloat *coef;
#property (nonatomic, assign) id owner;
#end
#implementation TargetClass_CategoryMemento
-(id)init {
if (self=[super init]) {
_coef = (GLfloat *)malloc(sizeof(GLfloat) * 15);
}
return self;
};
-(void)dealloc {
free(_coef);
if (_owner != nil
&& [_owner respondsToSelector:#selector(associatedObjectReportsDealloc)]) {
[_owner associatedObjectReportsDealloc];
}
[super dealloc];
}
#end
#implementation TargetClass (Category)
static NSString *kMementoTagKey = #"TargetClass+Category_MementoTagKey";
-(TargetClass_CategoryMemento *)TargetClass_CategoryGetMemento
{
TargetClass_CategoryMemento *m = objc_getAssociatedObject(self, kMementoTagKey);
if (m) {
return m;
}
// else
m = [[[TargetClass_CategoryMemento alloc] init] autorelease];
m.owner = self; // so we can let the owner know when we dealloc!
objc_setAssociatedObject(self, kMementoTagKey, m, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return m;
}
-(void) doStuff
{
CCSprite_BlurableMemento *m = [self CCSprite_BlurableGetMemento];
// do stuff you needed a category for, and store state values in m
}
-(void) associatedObjectReportsDealloc
{
NSLog(#"My associated object is being dealloced!");
// do stuff you need to do when your category instances are dealloced!
}
#end
The pattern here I learned somewhere (probably on S.O.) uses a factory method to get or create a memento object. Now it sets the owner on the memento, and the memento's dealloc method calls back to let the owner know it's being dealloced
CAVEATS:
Obviously, you have to have your associated object set with OBJC_ASSOCIATION_RETAIN_NONATOMIC, or it won't be retained and released for you automatically.
This becomes trickier if your memento/state associated object gets dealloced under other circumstances than the owner being dealloced...but you can probably train one object or the other to ignore that event.
The owner property can't be declared as retain, or you'll truly create a strong reference loop and neither object will ever qualify to be dealloced!
I don't know that it's documented that OBJC_ASSOCIATION_RETAIN_NONATOMIC associated objects are necessarily released before the owner is completely dealloced, but it seems to happen that way and almost must be the case, intuitively at least.
I don't know if associatedObjectReportsDealloc will be called before or after the TargetClass's dealloc method--this could be important! If it runs afterwards, if you try to access member objects of the TargetClass you will crash! And my guess is that it's afterwards.
This is a little messy, because you're double-linking your objects, which requires you to be very careful to keep those references straight. But, it doesn't involve swizzling, or other interference with the runtime--this just relies on a certain behavior of the runtime. Seems like a handy solution if you already have an associated object. In some cases it might be worth creating one just to catch your own deallocs!
Your proposed solution unfortunately won't work: because NSTimer retains its target, the target will never run its dealloc until the timer has been invalidated. The target's retain count will always be hovering at 1 or above, waiting for the timer to release it. You have to get to the timer before dealloc. (Pre-ARC, you could override retain and release and destroy the timer, although that's really not a good solution.)
NSThread also has this problem, and the solution is simple: a bit of redesigning separates the controller of the thread from the "model". The object which creates and owns the thread, or timer in this case, should not also be the target of the timer. Then, instead of the retain cycle you currently have (timer owns object which owns timer), you have a nice straight line: controller owns timer which owns target. Outside objects only need to interact with the controller: when it is deallocated, it can shut down the timer without you having to play games with overriding dealloc or other memory management methods.
That's the best way to handle this. In the case that you can't do that for some reason -- you're talking about category overrides, so apparently you don't have the code for the class which is the target of the timer (but you can still probably make a controller even in that case) -- you can use weak references. Unfortunately I don't know any way to make an NSTimer take a weak reference to its target, but GCD will give you a fair approximation via dispatch_after(). Get a weak reference to the target and use that exclusively in the Block you pass. The Block will not retain the object through the weak reference (the way NSTimer would), and the weak reference will of course be nil if the object has been deallocated before the Block runs, so you can safely write whatever message sends you like.
I have a view controller that I want to lazily initialize, and once initialized, use the same copy when possible (I don't use a singleton since I do want to remove it from memory eventually), I use the getter to do so, my code look like this:
#property (retain) UIViewController *myController
...
#synthesize myController = _myController;
...
- (UIViewController *)myController
{
if (!_myController) { // Evaluation
_myController = [[MyViewController alloc] init]; // Object Creation
}
return _myController;
}
This works, but it's not thread safe, and if more than one thread evaluate to true before the object is created, I'll have a memory leak. One solution I've tried is to #synchronized the code, but I'm not sure the correct way to do it.
This appears to work, (lockForMyController is a simple NSString) but it makes this section of code a lot slower:
- (UIViewController *)myController
{
#synchronized(self.lockForMyController){
if (!_myController) {
_myController = [[MyViewController alloc] init];
}
}
return _myController;
}
I was wondering if there is some other way to achieve a lazy initialized, thread safe, property?
This solution works
Note that this solution only works if myController is accessed on a background thread the first time. It will deadlock if called on the main thread.
You want to use gcd. The key is serialize the creation of the object, so that regardless of the threads starting the block, it will always only be created exactly once.
- (UIViewController *)myController
if (_myController == nil) {
dispatch_sync(dispatch_get_main_queue(), ^ { if (_myController == nil) _myController = [[MyViewController alloc] init]; });
}
return _myController;
}
Here, even if multiple threads execute the block, the execution of the block is serialized onto the main thread and only one MyViewController can ever be created.
You won't see a performance hit here unless the object is nil.
Since the property is implicitly atomic, that means that in the setter the value will be autoreleased. This should make it suitable for mingling with your custom getting, since it will autorelease any value changes to _myController.
http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW2
However, you still may get into a race condition where you are setting the value on one thread but accessing it on another. Any time you set the value, you probably want to make sure and do something like this:
dispatch_sync(dispatch_get_main_queue(), ^ { self.myController = {newValueOrNil} });
This will make sure to serialize your setter methods calls without having to reinvent the wheel for atomic setters, which is very hard to get right.
This solution does not work
You want to use gcd.
http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/c/func/dispatch_once
See this post about singletons. I know you don't want a singleton, but this demonstrates how to use the method. You can easily adapt it.
Create singleton using GCD's dispatch_once in Objective C