malloc + Automatic Reference Counting? - objective-c

If I use malloc along with Automatic Reference Counting, do I still have to manually free the memory?
int a[100];
int *b = malloc(sizeof(int) * 100);
free(b);

Yes, you have to code the call to free yourself. However, your pointer may participate in the reference counting system indirectly if you put it in an instance of a reference-counted object:
#interface MyObj : NSObject {
int *buf;
}
#end
#implementation MyObj
-(id)init {
self = [super init];
if (self) {
buf = malloc(100*sizeof(int));
}
}
-(void)dealloc {
free(buf);
}
#end
There is no way around writing that call to free - one way or the other, you have to have it in your code.

Yes. ARC only applies to Objective-C instances, and does not apply to malloc() and free().

Some 'NoCopy' variants of NSData can be paired with a call to malloc which will free you from having to free anything.
NSMutableData can be used as somewhat higher-overhead version of calloc which provides the convenience and safety of ARC.

In dealloc add an if not nil and assign to nil for safe. Dont want to free nil, malloc might be used outside of init etc.
#interface MyObj : NSObject {
int *buf;
}
#end
#implementation MyObj
-(id)init {
self = [super init];
if (self) {
buf = malloc(100*sizeof(int));
}
}
-(void)dealloc {
if(buf != null) {
free(buf);
buf = null;
}
}
#end

Related

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

Is this how properties are declared behind the scenes? [duplicate]

How exactly getter and setter methods body looks like after they have been automatically synthesized ?
From official documentation I found so far only recommended implementation techniques, however no word about which of them used by compiler during synthesizing process: http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539-SW5
Some techniques recommends implementations containing autorelease message, which is not quite secure for multithreaded programming. I'm just wonder if auto-generated code follows to some of the proposed implementations.
For example:
.h
#interface AClass: NSObject{}
#property (nonatomic, retain) AnotherClass *aProp;
#end
.m
#implementation AClass
#synthesize aProp
-(id) init {
if ((self = [super init])) {
self.aProp = [[AnotherClass alloc] init]; // setter invocation
}
return self;
}
-(AnotherClass *) aMethod {
return self.aProp; // getter invocation
}
#end
What are equivalent accessors code snippets for aProp generated by compiler ?
-(AnotherClass *) aProp {
// getter body
}
-(void) setAProp: (AnotherClass *) {
// setter body
}
When declaring a property as nonatomic, you'll get the following:
// .h
#property (nonatomic, retain) id ivar;
// .m
- (id)ivar {
return ivar;
}
- (void)setIvar:(id)newValue {
if (ivar != newValue) { // this check is mandatory
[ivar release];
ivar = [newValue retain];
}
}
Note the check ivar != newValue. If it was absent, ivar could be dealloc'ed after release, and the following retain would cause a memory access error.
When you declare your property with copy, the code will look almost the same, with retain replaced by copy.
For assign, it is even simpler:
- (void)setIvar:(id)newValue {
ivar = newValue;
}
Now, when you declare your property as atomic (this one is the default), things get slightly more complicated. A snippet similar to the one below was posted by one of Apple's engineers on the development forums:
- (id)ivar {
#synchronized (self) {
return [[self->ivar retain] autorelease];
}
}
- (void)setIvar:(id)newValue {
#synchronized (self) {
if (newValue != self->ivar) {
[self->ivar release];
self->ivar = newValue;
[self->ivar retain];
}
}
}
Note the #synchronized block in both methods and additional retain-autorelease in the getter. Both those things ensure that you will either get the previous value (retained and autoreleased) or a new one in the case the value is changed by some thread while you are trying to read it.
It depends on the attributes you set, for instance with a RETAIN attribute...
- (void)setAProp:(AnotherClass *)value {
[aProp release];
aProp = value;
[aProp retain];
}
For ASSIGN attribute....
- (void)setAProp:(AnotherClass *)value {
aProp = value;
}
For COPY attribute (used with NSString)...
- (void)setAProp:(AnotherClass *)value {
aProp = [value copy];
}

NSArray of weak references (__unsafe_unretained) to objects under ARC

I need to store weak references to objects in an NSArray, in order to prevent retain cycles. I'm not sure of the proper syntax to use. Is this the correct way?
Foo* foo1 = [[Foo alloc] init];
Foo* foo2 = [[Foo alloc] init];
__unsafe_unretained Foo* weakFoo1 = foo1;
__unsafe_unretained Foo* weakFoo2 = foo2;
NSArray* someArray = [NSArray arrayWithObjects:weakFoo1, weakFoo2, nil];
Note that I need to support iOS 4.x, thus the __unsafe_unretained instead of __weak.
EDIT (2015-02-18):
For those wanting to use true __weak pointers (not __unsafe_unretained), please check out this question instead: Collections of zeroing weak references under ARC
As Jason said, you can't make NSArray store weak references. The easiest way to implement Emile's suggestion of wrapping an object inside another object that stores a weak reference to it is the following:
NSValue *value = [NSValue valueWithNonretainedObject:myObj];
[array addObject:value];
Another option: a category that makes NSMutableArray optionally store weak references.
Note that these are "unsafe unretained" references, not self-zeroing weak references. If the array is still around after the objects are deallocated, you'll have a bunch of junk pointers.
The solutions to use a NSValue helper or to create a collection (array, set, dict) object and disable its Retain/Release callbacks are both not 100% failsafe solutions with regard to using ARC.
As various comments to these suggestions point out, such object references will not work like true weak refs:
A "proper" weak property, as supported by ARC, has two behaviors:
Doesn't hold a strong ref to the target object. That means that if the object has no strong references pointing to it, the object will be deallocated.
If the ref'd object is deallocated, the weak reference will become nil.
Now, while the above solutions will comply with behavior #1, they do not exhibit #2.
To get behavior #2 as well, you have to declare your own helper class. It has just one weak property for holding your reference. You then add this helper object to the collection.
Oh, and one more thing: iOS6 and OSX 10.8 supposedly offer a better solution:
[NSHashTable weakObjectsHashTable]
[NSPointerArray weakObjectsPointerArray]
[NSPointerArray pointerArrayWithOptions:]
These should give you containers that hold weak references (but note matt's comments below).
An example (updated 2 Feb 2022)
#import <Foundation/Foundation.h>
static BOOL didDealloc = NO;
#interface TestClass : NSObject
#end
#implementation TestClass
-(void)dealloc {
didDealloc = YES;
}
#end
int main(int argc, const char * argv[]) {
NSPointerArray *pa = [NSPointerArray weakObjectsPointerArray];
#autoreleasepool {
TestClass *obj = TestClass.new;
[pa addPointer:(__bridge void * _Nullable)(obj)]; // stores obj as a weak ref
assert([pa pointerAtIndex:0] != nil);
assert(!didDealloc);
} // at this point the TestClass obj will be deallocated
assert(didDealloc);
assert([pa pointerAtIndex:0] == nil); // verify that the weak ref is null now
return 0;
}
If you run this you'll find that after adding the TestClass object to the pointer array pa, then releasing that object again, the pointer (which is internally a weak object ref) is now set to null as desired.
However, note that calling [pa compact] at the end will not remove the nil pointer as I'd have expected.
I am new to objective-C, after 20 years of writing c++.
In my view, objective-C is excellent at loosely-coupled messaging, but horrible for data management.
Imagine how happy I was to discover that xcode 4.3 supports objective-c++!
So now I rename all my .m files to .mm (compiles as objective-c++) and use c++ standard containers for data management.
Thus the "array of weak pointers" problem becomes a std::vector of __weak object pointers:
#include <vector>
#interface Thing : NSObject
#end
// declare my vector
std::vector<__weak Thing*> myThings;
// store a weak reference in it
Thing* t = [Thing new];
myThings.push_back(t);
// ... some time later ...
for(auto weak : myThings) {
Thing* strong = weak; // safely lock the weak pointer
if (strong) {
// use the locked pointer
}
}
Which is equivalent to the c++ idiom:
std::vector< std::weak_ptr<CppThing> > myCppThings;
std::shared_ptr<CppThing> p = std::make_shared<CppThing>();
myCppThings.push_back(p);
// ... some time later ...
for(auto weak : myCppThings) {
auto strong = weak.lock(); // safety is enforced in c++, you can't dereference a weak_ptr
if (strong) {
// use the locked pointer
}
}
Proof of concept (in the light of Tommy's concerns about vector reallocation):
main.mm:
#include <vector>
#import <Foundation/Foundation.h>
#interface Thing : NSObject
#end
#implementation Thing
#end
extern void foo(Thing*);
int main()
{
// declare my vector
std::vector<__weak Thing*> myThings;
// store a weak reference in it while causing reallocations
Thing* t = [[Thing alloc]init];
for (int i = 0 ; i < 100000 ; ++i) {
myThings.push_back(t);
}
// ... some time later ...
foo(myThings[5000]);
t = nullptr;
foo(myThings[5000]);
}
void foo(Thing*p)
{
NSLog(#"%#", [p className]);
}
example log output:
2016-09-21 18:11:13.150 foo2[42745:5048189] Thing
2016-09-21 18:11:13.152 foo2[42745:5048189] (null)
If you do not require a specific order you could use NSMapTable with special key/value options
NSPointerFunctionsWeakMemory
Uses weak read and write barriers appropriate for ARC or GC. Using NSPointerFunctionsWeakMemory object references will turn to NULL on last release.
I believe the best solution for this is to use NSHashTable or NSMapTable. the Key or/and the Value can be weak. You can read more about it here: http://nshipster.com/nshashtable-and-nsmaptable/
To add weak self reference to NSMutableArray, create a custom class with a weak property as given below.
NSMutableArray *array = [NSMutableArray new];
Step 1: create a custom class
#interface DelegateRef : NSObject
#property(nonatomic, weak)id delegateWeakReference;
#end
Step 2: create a method to add self as weak reference to NSMutableArray. But here we add the DelegateRef object
-(void)addWeakRef:(id)ref
{
DelegateRef *delRef = [DelegateRef new];
[delRef setDelegateWeakReference:ref]
[array addObject:delRef];
}
Step 3: later on, if the property delegateWeakReference == nil, the object can be removed from the array
The property will be nil, and the references will be deallocated at proper time independent of this array references
The simplest solution:
NSMutableArray *array = (__bridge_transfer NSMutableArray *)CFArrayCreateMutable(nil, 0, nil);
NSMutableDictionary *dictionary = (__bridge_transfer NSMutableDictionary *)CFDictionaryCreateMutable(nil, 0, nil, nil);
NSMutableSet *set = (__bridge_transfer NSMutableSet *)CFSetCreateMutable(nil, 0, nil);
Note: And this works on iOS 4.x too.
No, that's not correct. Those aren't actually weak references. You can't really store weak references in an array right now. You need to have a mutable array and remove the references when you're done with them or remove the whole array when you're done with it, or roll your own data structure that supports it.
Hopefully this is something that they'll address in the near future (a weak version of NSArray).
I've just faced with same problem and found that my before-ARC solution works after converting with ARC as designed.
// function allocates mutable set which doesn't retain references.
NSMutableSet* AllocNotRetainedMutableSet() {
CFMutableSetRef setRef = NULL;
CFSetCallBacks notRetainedCallbacks = kCFTypeSetCallBacks;
notRetainedCallbacks.retain = NULL;
notRetainedCallbacks.release = NULL;
setRef = CFSetCreateMutable(kCFAllocatorDefault,
0,
&notRetainedCallbacks);
return (__bridge NSMutableSet *)setRef;
}
// test object for debug deallocation
#interface TestObj : NSObject
#end
#implementation TestObj
- (id)init {
self = [super init];
NSLog(#"%# constructed", self);
return self;
}
- (void)dealloc {
NSLog(#"%# deallocated", self);
}
#end
#interface MainViewController () {
NSMutableSet *weakedSet;
NSMutableSet *usualSet;
}
#end
#implementation MainViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
weakedSet = AllocNotRetainedMutableSet();
usualSet = [NSMutableSet new];
}
return self;
}
- (IBAction)addObject:(id)sender {
TestObj *obj = [TestObj new];
[weakedSet addObject:obj]; // store unsafe unretained ref
[usualSet addObject:obj]; // store strong ref
NSLog(#"%# addet to set", obj);
obj = nil;
if ([usualSet count] == 3) {
[usualSet removeAllObjects]; // deallocate all objects and get old fashioned crash, as it was required.
[weakedSet enumerateObjectsUsingBlock:^(TestObj *invalidObj, BOOL *stop) {
NSLog(#"%# must crash here", invalidObj);
}];
}
}
#end
Output:
2013-06-30 00:59:10.266 not_retained_collection_test[28997:907]
constructed 2013-06-30 00:59:10.267
not_retained_collection_test[28997:907] addet to
set 2013-06-30 00:59:10.581 not_retained_collection_test[28997:907]
constructed 2013-06-30 00:59:10.582
not_retained_collection_test[28997:907] addet to
set 2013-06-30 00:59:10.881 not_retained_collection_test[28997:907]
constructed 2013-06-30 00:59:10.882
not_retained_collection_test[28997:907] addet to
set 2013-06-30 00:59:10.883 not_retained_collection_test[28997:907]
deallocated 2013-06-30 00:59:10.883
not_retained_collection_test[28997:907]
deallocated 2013-06-30 00:59:10.884
not_retained_collection_test[28997:907]
deallocated 2013-06-30 00:59:10.885
not_retained_collection_test[28997:907] * -[TestObj
respondsToSelector:]: message sent to deallocated instance 0x1f03c8c0
Checked with iOS versions 4.3, 5.1, 6.2.
Hope it will be useful to somebody.
If you need zeroing weak references, see this answer for code you can use for a wrapper class.
Other answers to that question suggest a block-based wrapper, and ways to automatically remove zeroed elements from the collection.
If you use a lot this comportment it's indicated to your own NSMutableArray class (subclass of NSMutableArray) which doesn't increase the retain count.
You should have something like this:
-(void)addObject:(NSObject *)object {
[self.collection addObject:[NSValue valueWithNonretainedObject:object]];
}
-(NSObject*) getObject:(NSUInteger)index {
NSValue *value = [self.collection objectAtIndex:index];
if (value.nonretainedObjectValue != nil) {
return value.nonretainedObjectValue;
}
//it's nice to clean the array if the referenced object was deallocated
[self.collection removeObjectAtIndex:index];
return nil;
}
I think an elegant solution is what Mr. Erik Ralston propose on his Github repository
https://gist.github.com/eralston/8010285
this are the essential steps:
create a category for NSArray and NSMutableArray
in the implementation create a convenience class with a weak property. Your category will assign the objects to this weak property.
.h
#import <Foundation/Foundation.h>
#interface NSArray(WeakArray)
- (__weak id)weakObjectForIndex:(NSUInteger)index;
-(id<NSFastEnumeration>)weakObjectsEnumerator;
#end
#interface NSMutableArray (FRSWeakArray)
-(void)addWeakObject:(id)object;
-(void)removeWeakObject:(id)object;
-(void)cleanWeakObjects;
#end
.m
#import "NSArray+WeakArray.h"
#interface WAArrayWeakPointer : NSObject
#property (nonatomic, weak) NSObject *object;
#end
#implementation WAArrayWeakPointer
#end
#implementation NSArray (WeakArray)
-(__weak id)weakObjectForIndex:(NSUInteger)index
{
WAArrayWeakPointer *ptr = [self objectAtIndex:index];
return ptr.object;
}
-(WAArrayWeakPointer *)weakPointerForObject:(id)object
{
for (WAArrayWeakPointer *ptr in self) {
if(ptr) {
if(ptr.object == object) {
return ptr;
}
}
}
return nil;
}
-(id<NSFastEnumeration>)weakObjectsEnumerator
{
NSMutableArray *enumerator = [[NSMutableArray alloc] init];
for (WAArrayWeakPointer *ptr in self) {
if(ptr && ptr.object) {
[enumerator addObject:ptr.object];
}
}
return enumerator;
}
#end
#implementation NSMutableArray (FRSWeakArray)
-(void)addWeakObject:(id)object
{
if(!object)
return;
WAArrayWeakPointer *ptr = [[WAArrayWeakPointer alloc] init];
ptr.object = object;
[self addObject:ptr];
[self cleanWeakObjects];
}
-(void)removeWeakObject:(id)object
{
if(!object)
return;
WAArrayWeakPointer *ptr = [self weakPointerForObject:object];
if(ptr) {
[self removeObject:ptr];
[self cleanWeakObjects];
}
}
-(void)cleanWeakObjects
{
NSMutableArray *toBeRemoved = [[NSMutableArray alloc] init];
for (WAArrayWeakPointer *ptr in self) {
if(ptr && !ptr.object) {
[toBeRemoved addObject:ptr];
}
}
for(WAArrayWeakPointer *ptr in toBeRemoved) {
[self removeObject:ptr];
}
}
#end

What equivalent code is synthesized for a declared property?

How exactly getter and setter methods body looks like after they have been automatically synthesized ?
From official documentation I found so far only recommended implementation techniques, however no word about which of them used by compiler during synthesizing process: http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAccessorMethods.html#//apple_ref/doc/uid/TP40003539-SW5
Some techniques recommends implementations containing autorelease message, which is not quite secure for multithreaded programming. I'm just wonder if auto-generated code follows to some of the proposed implementations.
For example:
.h
#interface AClass: NSObject{}
#property (nonatomic, retain) AnotherClass *aProp;
#end
.m
#implementation AClass
#synthesize aProp
-(id) init {
if ((self = [super init])) {
self.aProp = [[AnotherClass alloc] init]; // setter invocation
}
return self;
}
-(AnotherClass *) aMethod {
return self.aProp; // getter invocation
}
#end
What are equivalent accessors code snippets for aProp generated by compiler ?
-(AnotherClass *) aProp {
// getter body
}
-(void) setAProp: (AnotherClass *) {
// setter body
}
When declaring a property as nonatomic, you'll get the following:
// .h
#property (nonatomic, retain) id ivar;
// .m
- (id)ivar {
return ivar;
}
- (void)setIvar:(id)newValue {
if (ivar != newValue) { // this check is mandatory
[ivar release];
ivar = [newValue retain];
}
}
Note the check ivar != newValue. If it was absent, ivar could be dealloc'ed after release, and the following retain would cause a memory access error.
When you declare your property with copy, the code will look almost the same, with retain replaced by copy.
For assign, it is even simpler:
- (void)setIvar:(id)newValue {
ivar = newValue;
}
Now, when you declare your property as atomic (this one is the default), things get slightly more complicated. A snippet similar to the one below was posted by one of Apple's engineers on the development forums:
- (id)ivar {
#synchronized (self) {
return [[self->ivar retain] autorelease];
}
}
- (void)setIvar:(id)newValue {
#synchronized (self) {
if (newValue != self->ivar) {
[self->ivar release];
self->ivar = newValue;
[self->ivar retain];
}
}
}
Note the #synchronized block in both methods and additional retain-autorelease in the getter. Both those things ensure that you will either get the previous value (retained and autoreleased) or a new one in the case the value is changed by some thread while you are trying to read it.
It depends on the attributes you set, for instance with a RETAIN attribute...
- (void)setAProp:(AnotherClass *)value {
[aProp release];
aProp = value;
[aProp retain];
}
For ASSIGN attribute....
- (void)setAProp:(AnotherClass *)value {
aProp = value;
}
For COPY attribute (used with NSString)...
- (void)setAProp:(AnotherClass *)value {
aProp = [value copy];
}

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.