Calling getter for dispatch_queue_t property causes crash - objective-c

I have a private serial queue declared as a property and I am running into a very strange situation.
If I dispatch_async the property, it will crash (EXC_BAD_ACCESS (code=EXC_i386_GPFLT)). After some debugging, I found out that it's because the getter is called. If getter is not called, the crash won't happen. Also, it always crashes the second time self.queue is called. See second example below.
It's as though the first synthesized getter call has somehow caused the ivar to be over-released.
This is targeting iOS 9 and above so I am not checking OS_OBJECT_USE_OBJC.
Example 1) This doesn't work:
#interface Test ()
#property (nonatomic, strong) dispatch_queue_t initQueue;
#end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)onCompletion:(void (^)())completion {
// Crashes here - EXC_BAD_ACCESS (code=EXC_i386_GPFLT)
// the second time self.queue is accessed - either by subsequent call into
// this method, or by adding NSLog(#"%#", self.queue) before this line.
dispatch_async(self.initQueue, ^{
...
});
}
Example 2) This also doesn't work:
#interface Test ()
#property (nonatomic, strong) dispatch_queue_t initQueue;
#end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)onCompletion:(void (^)())completion {
NSLog(#"%#", self.initQueue);
// Crashes below - EXC_BAD_INSTRUCTION (code=EXC_i386_INVOP, subcode=0x0)
NSLog(#"%#", self.initQueue);
}
Example 3) It works if I stay away from using the getter:
#interface Test ()
#property (nonatomic, strong) dispatch_queue_t initQueue;
#end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (void)onCompletion:(void (^)())completion {
// Works fine
dispatch_async(_initQueue, ^{
...
});
}
Example 4) It also works if I supply the getter:
#interface Test ()
#property (nonatomic, strong) dispatch_queue_t initQueue;
#end
- (instancetype)init {
self = [super init];
if (self) {
_initQueue = dispatch_queue_create("com.test.initQueue", DISPATCH_QUEUE_SERIAL);
}
return self;
}
- (dispatch_queue_t)initQueue {
return _initQueue;
}
- (void)onCompletion:(void (^)())completion {
// Works fine
dispatch_async(self.initQueue, ^{
...
});
}
Example 5) It will also work if I use ivar for queue instead of property or self.initQueue is assigned the main queue instead.
What's the reason for this behavior?
Other open source library is using property for dispatch_queue_t along with the getter and they have no issue at all. Example: https://github.com/rs/SDWebImage/blob/7e0964f8d90dcd80d535c52dd9f6d5fa7432052b/SDWebImage/SDImageCache.m#L57

Per your comments you originally named the property initQueue, this in turn created a method called initQueue which fell afoul of the ARC Method family rules. Those rules indicate that ARC will automatically annotate any method beginning with new or init as NS_RETURNS_RETAINED.
Methods in the init family implicitly consume their self parameter and return a retained object. Neither of these properties can be altered through attributes.
This in turn means that callers of the method are supposed to be safe to assume that they are taking ownership of the returned value and do not need to increment the retain value. As a result when you attempted to use the property ARC did not increase the reference count as was expected but ARC still left a release call at the end of the method. This resulted in your property value being released prior to when your class was dealloced.
It is possible to override this behavior using attributes in some cases. However I would suggest just being aware of method families, as they can have a nice performance impact on your application particularly for factory methods.
Other pitfalls to be aware of:
Methods in the alloc, copy, mutableCopy, and new families — that is, methods in all the currently-defined families except init — implicitly return a retained object as if they were annotated with the ns_returns_retained attribute. This can be overridden by annotating the method with either of the ns_returns_autoreleased or ns_returns_not_retained attributes.
A side note on this as well:
It is undefined behavior for a program to cause two or more calls to init methods on the same object, except that each init method invocation may perform at most one delegate init call.
Sadly the compiler doesn't seem to warn about that one.

Related

Method is expected to return an instance of its class type

I have an NSTimer which is called from a class method to control an NSProgressBar. It works seemingly fine on the surface, although I get a warning as I'm using the NSTimer where I'm assuming the compiler wants the class name.
When I put the class name MyProgressBar in place of NSTimer the warning seems to go away. The reality of the matter is that all hell is breaking loose behind the scenes and the memory allocations start spiking up and up.
The question is, how should this really be done?
.h
#interface MyProgressBar : NSProgressIndicator {
double progressOffset;
NSTimer* animated;
}
#property (readwrite, retain) NSTimer* animated;
#property (readwrite) double progressOffset;
.m
- (void)setDoubleValue:(double)value {
[super setDoubleValue:value];
if (![self isDisplayedWhenStopped] && value == [self maxValue]) {
[self stopAnimation:self];
}
}
- (NSTimer*)animated { // This is the line with the warning
return animated; // using MyProgressBar ends up creating a memory leak
}
- (void)setAnimated :(NSTimer *)value {
if (animated != value) {
[animated invalidate];
animated = value;
}
}
- (id)initWithFrame :(NSRect)frameRect {
self = [super initWithFrame:frameRect];
if (self) {
self.progressOffset = 0;
self.animated = nil;
}
return self;
}
warning:
Method is expected to return an instance of its class type 'MyProgressBar', but is declared to return 'NSTimer *'
Overridden method returns an instance of its class type
-> complete github project here that displays the warning.
The getter should be called animated, not animate.
Also you should use underscore in all your instance variables (the default pattern) and drop the getter/setter as the compiler will provider better implementations (i.e. that setAnimated doesn't look right, if I recollect the use of manual reference counting). The getter should be returning an autoreleased object.

How to allocate memory for an array in class in objective-C?

I am very much new to objective-c and I'm struggling with this problem for a while! Here is my class prototype:
#interface YoCatchModel : NSObject
/**
Name of the Yo user. Currently this is local
*/
#property (nonatomic, strong) NSString* username;
/**
History of the messages sent with Yo
*/
#property (nonatomic, strong, readonly) NSMutableArray* historyArray;
/*
implement init method
*/
+ (instancetype) initmethod;
I should allocate memory for my history mutable array in this method which is read only.
I want to make another init method that takes a username string parameter. This new initWithUsername method should call init within its definition.
And here is implementation which I am trying to implement an init method using instancetype as the return type. But I am not really sure how to
Allocate memory for the array.
Call another init method for the user name.
#implementation YoCatchModel
+ (instancetype)initmethod {
return [[[self class] alloc] init];
}
I appreciate if anyone can give me some hint how to do this. So far I have read these pages to get to here:
http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming#Declaring.2C_Initializing_and_Releasing_a_Class_Instance
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/DefiningClasses/DefiningClasses.html#//apple_ref/doc/uid/TP40011210-CH3-SW7
https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html#//apple_ref/doc/uid/TP40014150-CH1-SW11
The initWithUsername method becomes the designated initializer of your class and would look something like:
- (instancetype)initWithUsername:(NSString *)username
{
self = [super init];
if (self) {
_username = [username copy];
_historyArray = [NSMutableArray new];
}
return self;
}
You should make the default init method use the designated initializer:
- (instancetype)init
{
return [self initWithUsername:nil];
}
and note that this code works on the property backing instance variables, which start with _, rather than using self. (which won't work with a readonly property anyway), and this is to avoid possible KVO side-effects of the property setter methods.

Objective-C, ARC: Is it correct to use __weak arguments?

Here's a little example of using weak arguments:
#interface MYTestObject : NSObject
#end
#implementation MYTestObject {
void(^_block)(void);
}
- (void)dealloc {
NSLog(#"DEALLOC!");
}
- (id)init {
if (self = [super init]) {
[self doSomethingWithObject:self];
}
return self;
}
- (void)doSomethingWithObject:(id __weak /* <- weak argument! */)obj {
_block = ^{
NSLog(#"%p", obj);
};
}
#end
And it works: -dealloc is called!
Also, if you remove __weak you'll get a retain-cycle and it's absolutely correct.
Wonder, if that's just a side-effect and it's completely unsafe to use weak arguments? Or is it a specified behavior and I'm just a bad google-user?
Two observations:
I'd be inclined to make a local __weak reference within doSomethingWithObject, rather than make it a __weak argument as illustrated in Avoid Strong Reference Cycles when Capturing self.
I don't think that it is, as you asked, "completely unsafe to use weak arguments." But if nothing else, it's the more common pattern to have a local __weak variable and strikes me as more appropriate as an implementation detail of doSomethingWithObject rather than part of the method's public interface.
I'd also make block a property with the copy memory qualifier. As the docs say
You should specify copy as the property attribute, because a block needs to be copied to keep track of its captured state outside of the original scope. This isn’t something you need to worry about when using Automatic Reference Counting, as it will happen automatically, but it's best practice for the property attribute to show the resultant behavior.
Thus:
#interface MYTestObject : NSObject
#property (nonatomic, copy) void(^block)(void);
#end
#implementation MYTestObject
- (void)dealloc {
NSLog(#"DEALLOC!");
}
- (id)init {
if (self = [super init]) {
[self doSomethingWithObject:self];
}
return self;
}
- (void)doSomethingWithObject:(MYTestObject *)obj {
typeof(obj) __weak weakObj = obj;
self.block = ^{
NSLog(#"%p", weakObj);
};
}
#end

What are the rules that affect __weak variables in a block with regard to GCC_OPTIMIZATION_LEVEL?

In the code below, when I run it with the GCC_OPTIMIZATION_LEVEL set to None, execution works as I expect and it prints the following to the console:
My Obj - SomeObj
However, when I set the GCC_OPTIMIZATION_LEVEL to Fastest, Smallest in the Xcode target configuration (as one typically does for Release builds) I end up with the following printed to the console:
My obj - (null)
The object appears to be getting released when I store it into the __weak id myObj variable in [Foo doSomething]. If I remove the __weak flag from the myObj variable the code runs as expected when the GCC_OPTIMIZATION_LEVEL is set to Fastest, Smallest.
I built this example based on a similar pattern I had in another project and added the __weak flag because I was encountering a retain cycle. The retain cycle warning went away, but when I built for Release, I found that myObj would be nil by the time it got to the spot where I am logging it in this example.
What rules am I violating by setting the __weak flag?
#import "FFAppDelegate.h"
///////////////////////////////////////////////////////
#interface SomeObject : NSObject
#end
#implementation SomeObject
- (NSString *)description; {
return #"SomeObject";
}
#end
///////////////////////////////////////////////////////
#interface Factory : NSObject
#end
#implementation Factory
- (id)generateObj {
id myObj = nil;
if (!myObj) {
SomeObject *anObj = [[SomeObject alloc] init];
myObj = anObj;
}
return myObj;
}
#end
///////////////////////////////////////////////////////
#interface Bar : NSObject
- (id)barObj;
#end
#implementation Bar
{
Factory *factory;
}
- (id)init {
self = [super init];
if (self) {
factory = [[Factory alloc] init];
}
return self;
}
- (id)barObj {
id anObj = [factory generateObj];
return anObj;
}
#end
///////////////////////////////////////////////////////
#interface Foo : NSObject
#property (strong) Bar *aBar;
- (void)doSomething;
#end
#implementation Foo
- (id)init {
self = [super init];
if (self) {
_aBar = [[Bar alloc] init];
}
return self;
}
- (void)doSomething {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
__weak id myObj = [self.aBar barObj];
NSLog(#"My Obj - %#", myObj);
});
}
#end
///////////////////////////////////////////////////////
#implementation FFAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Foo *f = [[Foo alloc] init];
[f doSomething];
}
#end
What rules am I violating by setting the __weak flag?
In your example, there is no strong reference to the instance returned from [self.aBar barObj]. Therefore, you cannot assume the instance will be alive by the time you read the myObj variable.
In the unoptimized build, the returned instance has been added to an autorelease pool and is therefore still alive when you print myObj. You can verify this by setting a breakpoint in -[SomeObject dealloc].
In the optimized build, ARC has avoided the autorelease pool and the returned instance is therefore deallocated immediately.
See section 3.2.3 in the Clang ARC documentation for more info. Specifically:
When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary. In the worst case, this may involve an autorelease, but callers must not assume that the value is actually in the autorelease pool.
When using __weak to avoid a retain cycle, you must ensure that there is a strong reference somewhere else to keep the object alive.
Maybe you should use Apple's default compiler LLVM and not GCC.
Edit: Also your "factory" method looks wrong. For example, the object is always nil in that if. Take a tour: http://developer.apple.com/library/ios/#documentation/general/conceptual/CocoaEncyclopedia/ClassFactoryMethods/ClassFactoryMethods.html

How to simplify callback logic with a Block?

Let's say I need to communicate with a class that provides a protocol and calls delegate methods when an operation is complete, as so:
#protocol SomeObjectDelegate
#required
- (void)stuffDone:(id)anObject;
- (void)stuffFailed;
#end
#interface SomeObject : NSObject
{
}
#end
Now, I've decided that while I could make another class implement the stuffDone: delegate method, I've decided that I'd rather encapsulate the process into a block which is written somewhere close to where SomeObject is instantiated, called, etc. How might I do this? Or in other words, if you look at this famous article on blocks (in the Replace Callbacks section); how might I write a method in SomeObject that accepts a completionHandler: of sorts?
It sounds like you wish to communicate with an existing class which is designed to take a delegate object. There are a number of approaches, including:
using a category to add block-based variants of the appropriate methods;
use a derived class to add the block-based variants; and
write a class which implements the protocol and calls your blocks.
Here is one way to do (3). First let's assume your SomeObject is:
#protocol SomeObjectDelegate
#required
- (void)stuffDone:(id)anObject;
- (void)stuffFailed;
#end
#interface SomeObject : NSObject
{
}
+ (void) testCallback:(id<SomeObjectDelegate>)delegate;
#end
#implementation SomeObject
+ (void) testCallback:(id<SomeObjectDelegate>)delegate
{
[delegate stuffDone:[NSNumber numberWithInt:42]];
[delegate stuffFailed];
}
#end
so we have some way to test - you will have a real SomeObject.
Now define a class which implements the protocol and calls your supplied blocks:
#import "SomeObject.h"
typedef void (^StuffDoneBlock)(id anObject);
typedef void (^StuffFailedBlock)();
#interface SomeObjectBlockDelegate : NSObject<SomeObjectDelegate>
{
StuffDoneBlock stuffDoneCallback;
StuffFailedBlock stuffFailedCallback;
}
- (id) initWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail;
- (void)dealloc;
+ (SomeObjectBlockDelegate *) someObjectBlockDelegateWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail;
// protocol
- (void)stuffDone:(id)anObject;
- (void)stuffFailed;
#end
This class saves the blocks you pass in and calls them in response to the protocol callbacks. The implementation is straightforward:
#implementation SomeObjectBlockDelegate
- (id) initWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail
{
if (self = [super init])
{
// copy blocks onto heap
stuffDoneCallback = Block_copy(done);
stuffFailedCallback = Block_copy(fail);
}
return self;
}
- (void)dealloc
{
Block_release(stuffDoneCallback);
Block_release(stuffFailedCallback);
[super dealloc];
}
+ (SomeObjectBlockDelegate *) someObjectBlockDelegateWithOnDone:(StuffDoneBlock)done andOnFail:(StuffFailedBlock)fail
{
return (SomeObjectBlockDelegate *)[[[SomeObjectBlockDelegate alloc] initWithOnDone:done andOnFail:fail] autorelease];
}
// protocol
- (void)stuffDone:(id)anObject
{
stuffDoneCallback(anObject);
}
- (void)stuffFailed
{
stuffFailedCallback();
}
#end
The only thing you need to remember is to Block_copy() the blocks when initializing and to Block_release() them later - this is because blocks are stack allocated and your object may outlive its creating stack frame; Block_copy() creates a copy in the heap.
Now you can all a delegate-based method passing it blocks:
[SomeObject testCallback:[SomeObjectBlockDelegate
someObjectBlockDelegateWithOnDone:^(id anObject) { NSLog(#"Done: %#", anObject); }
andOnFail:^{ NSLog(#"Failed"); }
]
];
You can use this technique to wrap blocks for any protocol.
ARC Addendum
In response to the comment: to make this ARC compatible just remove the calls to Block_copy() leaving direct assignments:
stuffDoneCallback = done;
stuffFailedCallback = fail;
and remove the dealloc method. You can also change Blockcopy to copy, i.e. stuffDoneCallback = [done copy];, and this is what you might assume is needed from reading the ARC documentation. However it is not as the assignment is to a strong variable which causes ARC to retain the assigned value - and retaining a stack block copies it to the heap. Therefore the ARC code generated produces the same results with or without the copy.
You could do something like this:
typedef void (^AZCallback)(NSError *);
AZCallback callback = ^(NSError *error) {
if (error == nil) {
NSLog(#"succeeded!");
} else {
NSLog(#"failed: %#", error);
}
};
SomeObject *o = [[SomeObject alloc] init];
[o setCallback:callback]; // you *MUST* -copy the block
[o doStuff];
...etc;
Then inside SomeObject, you could do:
if ([self hadError]) {
callback([self error]);
} else {
callback(nil);
}
The below link explains how the call backs using delegates could be easily replaced with blocks.
The examples includes UITableview,UIAlertview and ModalViewController.
click me
Hope this helps.