protecting from race condition for primitive types in objective-c - objective-c

In turning on the ThreadSanitizer in Xcode, I think I see there have been some data race conditions regarding some of our primitive types that I'm trying to clean up. Since we cannot use #synchronized for primitive types, is it best to do something like:
// declared somewhere in initialization
myQueue = dispatch_queue_create("com.comp.myqueue", DISPATCH_QUEUE_SERIAL);
// setter example for level that is a primitive type
dispatch_sync(self.myQueue, ^{
_level = someValue;
});
// getter example
- (double) level {
__block double result;
dispatch_sync(self.myQueue, ^{
result = _level
});
return result;
}

That appears correct, although I didn't test it specifically. You can also simply synchronize code blocks on another object within a property getter and setter. _testDoubleLock is a once initialized NSObject property:
NSObject * _testDoubleLock = #"_testDoubleLock";
double _testDouble;
-(double)testDouble {
#synchronized(_testDoubleLock) {
return _testDouble;
}
}
-(void)setTestDouble:(double)testDouble
{
#synchronized(_testDoubleLock) {
_testDouble = testDouble;
}
}

Related

Programmatically access method arguments in Objective-C

Let's say I have the following method:
-(void)methodWithVar1:(NSString*)var1 var2:(NSString*)var2;
Now of course I can access var1 and var2 within methodWithVar1:var2: by using the variable names directly. But what I'd like to do is something like methodArgs[0] and methodArgs[1] to access the variables.
Is there a way to do this? I've looked at runtime.h but can't see anything that helps.
Why do I want to do this?
In certain circumstances, when a method is called, I want to prevent the method executing, but allow it to execute at another moment in time. I'm doing this by creating an NSInvocation object that allows me to 're-call' the method when I would prefer it. However, NSInvocation requires that I call setArgument:atIndex:, which I have to do manually. If the method every changes, then the population of NSInvocation needs to be updated. I want to avoid updating it manually and have a generic way of doing it.
Example
-(void)methodWithVar1:(NSString*)var1 var2:(NSString*)var2{
if (someCheckToSeeIfICannotRun) {
NSMethodSignature * methodSignature =
[self.class instanceMethodSignatureForSelector:_cmd];
KWInvocation * invocation =
[KWInvocation invocationWithMethodSignature:methodSignature];
[invocation.invocation setTarget:self];
[invocation.invocation setSelector:_cmd];
[invocation.invocation setArgument:&var1 atIndex:2];// This and
[invocation.invocation setArgument:&var2 atIndex:3];// this, I would prefer to make generic
[invocation.invocation retainArguments];
//
// Store invocation somewhere so I can call it later...
//
}
else {
// Let the method run as normal
}
}
I think this can help you:
#import <objc/runtime.h>
void logArguments(const id* selfPtr)
{
id obj = *selfPtr;
SEL sel = *(SEL*)(void*)(--selfPtr);
Method m = class_getInstanceMethod([obj class], sel);
for (unsigned int cnt = method_getNumberOfArguments(m) - 2; 0 != cnt; --cnt)
{
NSLog(#"arg: %#", *(--selfPtr));
}
}
You can call logArguments(&self); in any method, but there is one restriction: all arguments should be objective-c objects.

passing in a method in Objective C

In C# you can create a delegate method, assign it to a variable or pass it into a method as if it were a variable. For example:
public delegate int Lookup(String s);
//...
public static int Evaluate(String exp, Lookup variableEvaluator)
{
//...
}
I heard that in C you can create a pointer to any method and then pass that pointer to a method.
Can anyone give me a simple example of doing that in Objective-C? Of course, I can create an object with a singe method and pass that object into a method. But I am curious if there is a way of doing that similar to that of C# or C.
Lots of ways.
One: the good. Use blocks (closures, lambda calculus, however you call it):
typedef void (^MyCallback)();
- (void)callTheCallback:(MyCallback)blockToInvoke
{
blockToInvoke();
}
MyCallback cb = ^{
NSLog(#"I was called! :D");
};
[self callTheCallback:cb];
Two: the bad. Grab a pointer to the method function itself and call that. (Warning: if you use this approach, I'll sue you.)
- (void)callTheCallback:(IMP)funcPtrToCall withObject:(id)obj selector:(SEL)sel
{
funcPtrToCall(obj, sel);
}
- (void)someCallbackMethod
{
NSLog(#"I was called! :D");
}
IMP implemt = [[self class] instanceMethodForSelector:#selector(someCallbackMethod)];
[self callTheCallback:implemt withObject:self selector:#selector(someCallbackMethod)];
Three: the ugly. Use a delegate:
- (void)delegateMethodOfSomeObject:(SomeObject *)obj
{
NSLog(#"I was called! :D");
}
SomeObject *obj = [[SomeObject alloc] init];
obj.delegate = self;
[obj makeThisObjectSomehowCallItsDelegateThatIsCurrentlySelf];
Two quick thoughts come to mind.
The short answer is called "blocks", but it's lower level than is probably recommended for what you need.
The "cleaner" solution (read: higher level) is to pass two params: and object (called "target") and a selector (called "action"). This is a very common pattern in Objective-C, so I'll only demonstrate this one. If you are interested in the blocks idea, check out this doc.
Essentially, the object should be passed as an id, and the selector as a SEL, for which we have the handy #selector() construct:
-(void) doThingWithTarget:(id) targetObj action:(SEL) actionSel {
if([targetObj respondsToSelector:actionSel]) {
[targetObj performSelector:actionSel withObject:self];
}
}
// ...
[thatOtherObject doThingWithTarget:self action:#selector(myMethod:)];
// ... where
-(void) myMethod:(id) sender {
// sender is the calling object, or should be by contract.
}
Objective C uses selectors. http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocSelectors.html

Objective-C - iVar Scoped Method Variables?

I was messing around in Objective-C earlier, and I ran into a quite common situation:
I had a class, which was not a singleton, that needed a variable shared between method calls, like static, but each instance needed it's own variable. However, this variable only needed to be used in one particular method, we'll call it -foo.
What I'd love to do, is have a macro, let's call it ivar, which lets me do the following:
#implementation MyClass
-(foo)
{
ivar int someVal = 10; // default value, ivar scoped variable.
}
-(bar)
{
someVal = 5; // error, outside of `foo`'s scope.
}
#end
How the variable is defined does not matter to me (either a macro like OBJC_IVAR(Type, Name, Default) or ivar someType someName = value), as long as it meets the following requirements:
Has thread safety
Can have variable of same name (but different value) in another method
Type-less (doesn't matter what type the variable is)
Default Value support
Variable can be declared in one line (I shouldn't have to write 15 lines of code just to put a variable in my code)
I am currently working on an Objective-C++ implementation myself, I was just wondering if anyone else had any thoughts (or existing tools) on how to do this.
Obviously, this doesn't have to be done with a true iVar. More likely, this should be done with associated objects at run-time, which also manages deallocation for us.
After a lot of time spent, I believe I have a fully working solution in Objective-C++. Some of the features:
The variables are unique. As long as they have a different scope, their values are independent
Each instance has it's own values
Thread safety (accomplished by associated objects)
Simple variable declaration:
Macro overloading: only specify the information that you need
Possible ways to define an OBJC_IVAR:
OBJC_IVAR(); // creates a warning, does nothing
OBJC_IVAR(Name); // creates an ivar named 'Name' of type 'id'
OBJC_IVAR(Type, Name); // creates an ivar named 'Name' of type 'Type'
OBJC_IVAR(Type, Name, Default); // creates an ivar named 'Name', of type 'Type', and a default value of 'Default' (which is only executed once);
Full Type Support with C++ templates (__weak, __strong, __autoreleasing, volatile, etc. are all supported)
Subclasses do not share variables with their superclasses (so no chance for conflicts, variables really are limited to their scope).
Can be used in singletons without issue
Is fast, takes ~15-30 CPU cycles to look up a variable, and once it's looked up, takes as long as any other variable to set it.
Most of the hard work is done by the pre-processor, which allows for faster code
Just drag-and-drop into an existing Xcode project, doesn't rely on a custom processor
Some minor cons to the implementation:
Objects must have an ownership specifier (limitation with C++ references: Reference to non-const type 'id' with no explicit ownership). Is easily fixed by adding __strong, __weak, or __autoreleasing to the type of the variable
Implementation is hard to read. Because it relies so much on C++ templates and Objective-C working together in harmony, it's difficult to just change 'one thing' and hope for it to work. I have added extensive comments to the implementation, so hopefully that frees some of the burden.
Method swizzling can confuse this majorly. Not the largest of issues, but if you start playing around with method swizzling, don't be surprised if you get unexpected results.
Cannot be used inside a C++ object. Unfortunately, C++ doesn't support runtime attributes, like objective-c does, so we cannot rely upon our variables being cleaned up eventually. For this reason, you cannot use OBJC_IVAR while inside a C++ object. I would be interested in seeing an implementation for that, though.
#line can mess this up drastically, so don't use it.
Version History
1.0: Initial Release
1.1: Updated OBJC_IVAR_NAME to rely only on the preprocessor. As a result, we cannot use __func__.
So, without further ado, here is the code:
OBJC_IVAR.hpp
//
// OBJC_IVAR.h
// TestProj
//
// Created by Richard Ross on 8/17/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//
#ifndef OBJC_IVAR_HPP
#define OBJC_IVAR_HPP
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "NSValue+CppObject.h"
// Argument counting algorithm. Not too complex
#define __NARG(_1, _2, _3, _4, _5, VAL, ...) VAL
#define NARG(...) __NARG(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
// Different implementations based on number of parameters passed in
#define __OBJC_IVAR(N, ...) _OBJC_IVAR_ ## N (__VA_ARGS__)
#define _OBJC_IVAR(N, ...) __OBJC_IVAR(N, __VA_ARGS__)
// Usage: OBJC_IVAR(Type (optional), Name (required), Default (optional))
#define OBJC_IVAR(...) _OBJC_IVAR(NARG(__VA_ARGS__), __VA_ARGS__)
// create a unique name. we use '__COUNTER__' here to support scoping on the same line, for compressed source code
#define __OBJC_IVAR_STRINGIFY_NAME(file, line, name, counter) #file ":" #line " " #name ":" #counter
#define _OBJC_IVAR_NAME(file, line, name, counter) __OBJC_IVAR_STRINGIFY_NAME(file, line, name, counter)
#define OBJC_IVAR_NAME(name) _OBJC_IVAR_NAME(__FILE__, __LINE__, name, __COUNTER__)
// old style creation. advantage: uses __func__ to determine calling function
// #define OBJC_IVAR_NAME(Name) [NSString stringWithFormat:#"%s:%i %s:%s:%i", __FILE__, __LINE__, __func__, #Name, __COUNTER__]
// implemenations for each of the overloads
#define _OBJC_IVAR_0(...) _Pragma("message \"Cannot call OBJC_IVAR with 0 params!\"")
#define _OBJC_IVAR_1(Name) _OBJC_IVAR_2(__strong id, Name)
// first major implemenation. because we do no assignment here, we don't have to check for is_set
#define _OBJC_IVAR_2(Type, Name) Type& Name = (_OBJC_IVAR::IMPL<Type>(self, OBJC_IVAR_NAME(Name)))
// this is where things get fun. we have 'OBJC_IVAR_CUR_NAME', instead of calling OBJC_IVAR_NAME
// multiple times, because we must ensure that COUNTER does not change during the course of the macro
// this is the 'inner bowels' of C, and it's quite hacky. Returns a reference to an associated object
// which is wrapped in a NSValue. Note that we only evaluate 'default' once throught the course of the
// application's cycle, so you can feel free to put intensive loading code there.
static NSString *_OBJC_IVAR_CUR_NAME;
#define _OBJC_IVAR_3(Type, Name, Default) Type& Name = (_OBJC_IVAR::IS_SET(self, (_OBJC_IVAR_CUR_NAME = OBJC_IVAR_NAME(Name))) ? _OBJC_IVAR::IMPL<Type>(self, _OBJC_IVAR_CUR_NAME) : _OBJC_IVAR::IMPL<Type>(self, _OBJC_IVAR_CUR_NAME, Default))
// namespace to wrap al lof our functions
namespace _OBJC_IVAR
{
// internal dictionary of all associated object names, so that we don't run
// into memory management issues. we use a set here, because we should never
// have duplicate associated object names.
static NSMutableSet *_names = [NSMutableSet set];
// wraps a value and a reference to a value. used over std::reference_wrapper,
// as that doesn't actually copy in the value passed. That is required for what
// we are doing, as we cannot be assigning to constants.
template<typename T>
class Wrapper {
private:
// private value wrapped by this object.
T _value;
// private reference wrapped by this object. should always point to _value.
T& _ref;
public:
// default constructor. assumes 'T' has a valid 0-argument constructor
Wrapper() : _value(), _ref(_value) { }
// argument constructor. makes sure that value is initialized properly
Wrapper(T val) : _value(val), _ref(_value) { }
// returns the reference wrapped by this object
operator T& () {
return _ref;
}
T& get() {
return _ref;
}
};
// interns a name. because objc_getAssociatedObject works only by comparing
// pointers (and +stringWithFormat: isn't guaranteed to return the same pointer),
// we have to make sure that we maintain a list of all valid associated object
// names. these are NOT linked to specific objects, which allows us to reuse some
// memory
inline NSString *name_intern(NSString *name)
{
// intern the value. first check if the object has been interned already,
// and if it is, return that interned value
if (id tmpName = [_names member:name])
{
name = tmpName;
}
// if we haven't interned this value before, then add it to the list and return it.
else
{
[_names addObject:name];
}
return name;
}
// check and see if the requested iVar has been set yet. used for default value setting
BOOL IS_SET(id target, NSString *name)
{
// first intern the name
name = name_intern(name);
// check if the object has this property. objc_getAssociatedObject will ALWAYS
// return NULL if the object doesn't exist. Note the bridged cast. This is because
// objc_getAssociatedObject doesn't care what you throw into the second parameter,
// as long as it is a pointer. That gives us the flexibility at a later date, to,
// for example, just pass a pointer to a single byte, and pull out the value that
// way. However, we pass in a NSString pointer, because it makes it easy for us to
// use and to re-use later.
id val = objc_getAssociatedObject(target, (__bridge const void *) name);
return val != nil;
}
// the actual implementation for setting the iVar. luckily this code isn't too hacky,
// but it is a bit confusing.
template<typename T>
Wrapper<T>& IMPL(id target, NSString *name)
{
// first intern the name
name = name_intern(name);
// define a reference. we use pointers & new here, because C++ memory managment is
// weird at best. Most of the time, you should be using RAII, but when dealing with
// templates & objective-c interpolation, it is almost required that you use pointers
// with new.
Wrapper<T> *reference = nullptr;
// check and see if the object already contains this property, if so, return that value
NSValue *result = objc_getAssociatedObject(target, (__bridge const void *) name);
if (result == nil)
{
// at this point, we need to create a new iVar, with the default constructor for the type.
// for objective-c objects this is 'nil', for integers and floating point values this is 0,
// for C++ structs and classes, this calls the default constructor. If one doesn't exist,
// you WILL get a compile error.
reference = new Wrapper<T>();
// we now set up the object that will hold this wrapper. This is an extension on NSValue
// which allows us to store a generic pointer (in this case a C++ object), and run desired
// code on -dealloc (which will be called at the time the parent object is destroyed), in
// this case, free the memory used by our wrapper.
result = [NSValue valueWithCppObject:reference onDealloc:^(void *) {
delete reference;
}];
// finally, set the associated object to the target, and now we are good to go.
// We use OBJC_ASSOCIATION_RETAIN, so that our NSValue is properly freed when done.
objc_setAssociatedObject(target, (__bridge const void *) name, result, OBJC_ASSOCIATION_RETAIN);
}
// from result, we cast it's -cppObjectValue to a Wrapper, to pull out the value.
reference = static_cast<Wrapper<T> *>([result cppObjectValue]);
// finally, return the pointer as a reference, not a pointer
return *reference;
}
// this is pretty much the same as the other IMPL, but it has specific code for default values.
// I will ignore everything that is the same about the two functions, and only focus on the
// differences, which are few, but mandatory.
template<typename T>
Wrapper<T>& IMPL(id target, NSString *name, const T& defVal)
{
name = name_intern(name);
Wrapper<T> *reference = nullptr; // asign to be the default constructor for 'T'
NSValue *result = objc_getAssociatedObject(target, (__bridge const void *) name);
if (result == nil)
{
// this is the only difference. Instead of constructing with the default constructor,
// simply pass in our new default value as a copy.
reference = new Wrapper<T>(defVal);
result = [NSValue valueWithCppObject:reference onDealloc:^(void *) {
delete reference;
}];
objc_setAssociatedObject(target, (__bridge const void *) name, result, OBJC_ASSOCIATION_RETAIN);
}
reference = static_cast<Wrapper<T> *>([result cppObjectValue]);
return *reference;
}
}
#endif // OBJC_IVAR_HPP
NSValue+CppObject.h
//
// NSValue+CppObject.h
// TestProj
//
// Created by Richard Ross on 8/17/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
// Extension on NSValue to add C++ object support. Because of the difficulty
// involved in templates, I took the easy way out and simply passed in a block
// of code to be run at dealloc.
#interface NSValue (CppObject)
// create a new NSValue instance that holds ptr, and calls 'deallocBlock' on destruction.
+(id) valueWithCppObject:(void *) ptr onDealloc:(void (^)(void *)) deallocBlock;
-(id) initWithCppObject:(void *) ptr onDealloc:(void (^)(void *)) deallocBlock;
// get the held pointer of this object. I called it -cppObjectValue, so
// there was no confusion with -pointerValue.
-(void *) cppObjectValue;
#end
NSValue+CppObject.m
//
// NSValue+CppObject.m
// TestProj
//
// Created by Richard Ross on 8/17/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//
#import "NSValue+CppObject.h"
// the concrete NSValue subclass for supporting C++ objects. Pretty straight-forward interface.
#interface ConcreteCppObject : NSValue
{
// the underlying object that is being pointed to
void *_object;
// the block that is called on -dealloc
void (^_deallocBlock)(void *);
}
#end
#implementation ConcreteCppObject
// object initialization
+(id) valueWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
return [[self alloc] initWithCppObject:ptr onDealloc:deallocBlock];
}
-(id) initWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
if (self = [super init])
{
_object = ptr;
_deallocBlock = deallocBlock;
}
return self;
}
// required methods for subclassing NSValue
-(const char *) objCType
{
return #encode(void *);
}
-(void) getValue:(void *)value
{
*((void **) value) = _object;
}
// comparison
-(BOOL) isEqual:(id)compare
{
if (![compare isKindOfClass:[self class]])
return NO;
return [compare cppObjectValue] == [self cppObjectValue];
}
// cleanup
-(void) dealloc
{
// this should manage cleanup for us
_deallocBlock(_object);
}
// value access
-(void *) cppObjectValue
{
return _object;
}
#end
// NSValue additions for creating the concrete instances
#implementation NSValue (CppObject)
// object initialization
+(id) valueWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
return [[ConcreteCppObject alloc] initWithCppObject:ptr onDealloc:deallocBlock];
}
-(id) initWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
return [[self class] valueWithCppObject:ptr onDealloc:deallocBlock];
}
// unless the NSValue IS a ConcreteCppObject, then we shouldn't do anything here
-(void *) cppObjectValue
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
#end
Example Usage:
#import "OBJC_IVAR.hpp"
#interface SomeObject : NSObject
-(void) doSomething;
#end
#implementation SomeObject
-(void) doSomething
{
OBJC_IVAR(__strong id, test, #"Hello World!");
OBJC_IVAR(int, test2, 15);
NSLog(#"%#", test);
NSLog(#"%i", test2 += 7);
// new scope
{
OBJC_IVAR(int, test, 100);
NSLog(#"%i", ++test);
}
[self somethingElse];
}
-(void) somethingElse
{
OBJC_IVAR(int, newVar, 7);
NSLog(#"%i", newVar++);
}
#end
int main()
{
SomeObject *obj = [SomeObject new];
[obj doSomething];
[obj doSomething];
[obj doSomething];
}
I had a class, which was not a singleton, that needed a variable
shared between method calls, like static, but each instance needed
it's own variable.
In that case, the variable is part of the object's state, and it's therefore most appropriate to use an instance variable (or a property). This is exactly what ivars are for, whether they're used in a dozen methods or just one.
I am currently working on an Objective-C++ implementation myself, I
was just wondering if anyone else had any thoughts (or existing tools)
on how to do this.
My advice is to not do it at all. If your goal is to avoid clutter, don't go needlessly trying to add a new storage class to the language.
However, if you're determined to pursue this line, I'd look at using blocks instead of associated objects. Blocks get their own copies of variables that are scoped to the lifetime of the block. For example, you can do this:
- (void)func
{
__block int i = 0;
void (^foo)() = ^{
i++;
NSLog(#"i = %d", i);
};
foo();
foo();
foo();
}
and the output you get is:
i = 1
i = 2
i = 3
Perhaps you can find a clever way to wrap that up in a macro, but it looks to me like a lot of trouble just to avoid declaring an instance variable.

Objective-C blocks usage

I have been looking around online, doing research into how to use blocks. I have also decided to set up a basic example to try and understand the way in which they work.
Essentially what I want to do is have a 'block variable' (no sure if thats the correct term) in which I can store a block of code. I then want to be able to set the code in this block at pointX (methodA or methodB) in my code, then run the block of code at pointY (methodX).
So to be specific, my question is 3-fold
Using the example below is the setup / usage of blocks correct and valid?
In methodX how do I execute the code inside the block (self.completionBlock)?
When creating the block in methodA and methodB will the code be called there and then? If so how can I stop this from happening (all I want to do is set up the code in the block to be called later)?
I may have completely misunderstood how blocks are used, apologies if this is the case, however I'm relatively new to Objective-C and I'm trying to learn.
Here is my code so far:
.h
typedef void (^ CompletionBlock)();
#interface TestClass : NSObject
{
CompletionBlock completionBlock;
NSString *stringOfText;
NSString *otherStringOfText;
}
#property(nonatomic, copy)CompletionBlock completionBlock;
#property(nonatomic, retain)NSString *stringOfText;
#property(nonatomic, retain)NSString *otherStringOfText;
- (void)methodA:(NSString *)myText;
- (void)methodB:(NSString *)myText and:(NSString *)myOtherText;
- (void)methodX;
#end
.m
- (void)methodA:(NSString *)myText;
{
if ([self.stringOfText isEqualToString:#""])
{
// Set the variable to be used by the completion block
self.stringOfText = #"I visited methodA"; // normally make use of myText
// Create the completion block
__block TestClass *blocksafeSelf = self;
self.completionBlock = ^()
{
[blocksafeSelf methodA:blocksafeSelf.stringOfText];
blocksafeSelf.stringOfText = nil;
};
}
else
{
// Do some other stuff with self.stringOfText
}
}
- (void)methodB:(NSString *)myText and:(NSString *)myOtherText;
{
if ([self.stringOfText isEqualToString:#""] || [self.otherStringOfText isEqualToString:#""])
{
// Set the variable to be used by the completion block
self.stringOfText = #"I visited methodB"; // normally make use of myText
self.otherStringOfText = #"I also visited methodB"; // normally make use of myOtherText
// Create the completion block
__block TestClass *blocksafeSelf = self;
self.completionBlock = ^()
{
[blocksafeSelf methodB:blocksafeSelf.stringOfText and:blocksafeSelf.otherStringOfText];
blocksafeSelf.stringOfText = nil;
blocksafeSelf.otherStringOfText = nil;
};
}
else
{
// Do some other stuff with self.stringOfText and self.otherStringOfText
}
}
- (void)methodX
{
// At this point run the block of code in self.completionBlock...how?!
}
In my example either methodA or methodB will be called first. Then some time later (perhaps from a different class) methodX will be called (only ever after methodA or methodB have been called).
It's worth noting that the methods methodA, methodB and methodX are all in a singleton class.
NOTE: This is just a dummy example to try and understand the workings of blocks, I'm fully aware there are other ways to achieve the same result.
Here's the code, just to be clear:
- (void)methodX
{
if(self.completionBlock)
self.completionBlock();
}
I think you want to do self.completionBlock(); in methodX.

Objective-C pass block as parameter

How can I pass a Block to a Function/Method?
I tried - (void)someFunc:(__Block)someBlock with no avail.
ie. What is the type for a Block?
The type of a block varies depending on its arguments and its return type. In the general case, block types are declared the same way function pointer types are, but replacing the * with a ^. One way to pass a block to a method is as follows:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
But as you can see, that's messy. You can instead use a typedef to make block types cleaner:
typedef void (^ IteratorBlock)(id, int);
And then pass that block to a method like so:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
The easiest explanation for this question is follow these templates:
1. Block as a method parameter
Template
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
Example
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
Other use of cases:
2. Block as a Property
Template
#property (nonatomic, copy) returnType (^blockName)(parameters);
Example
#property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
3. Block as a method argument
Template
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
Example
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4. Block as a local variable
Template
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
Example
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5. Block as a typedef
Template
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
Example
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
This might be helpful:
- (void)someFunc:(void(^)(void))someBlock;
You can do like this, passing block as a block parameter:
//creating a block named "completion" that will take no arguments and will return void
void(^completion)() = ^() {
NSLog(#"bbb");
};
//creating a block namd "block" that will take a block as argument and will return void
void(^block)(void(^completion)()) = ^(void(^completion)()) {
NSLog(#"aaa");
completion();
};
//invoking block "block" with block "completion" as argument
block(completion);
One more way to pass block using с functions in example below.
I`ve created functions to perform anything in background and on main queue.
blocks.h file
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
blocks.m file
#import "blocks.h"
void performInBackground(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}
void performOnMainQueue(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_main_queue(), block);
}
Than import blocks.h when necessary and invoke it:
- (void)loadInBackground {
performInBackground(^{
NSLog(#"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
You also can set block as a simple property if it's applicable for you:
#property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
make sure that block property is "copy"!
and of course you can also use typedef:
typedef void (^SimpleBlock)(id);
#property (nonatomic, copy) SimpleBlock someActionHandler;
Also you invoke or call a block in using usual c function syntax
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
More info on blocks here
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxGettingStarted.html#//apple_ref/doc/uid/TP40007502-CH7-SW1
I always tend to forget about blocks syntax. This always comes to my mind when I need to declare a block. I hope it helps someone :)
http://fuckingblocksyntax.com
I wrote a completionBlock for a class which will return the values of dice after they have been shaken:
Define typedef with returnType (.h above #interface declaration)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
Define a #property for the block (.h)
#property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
Define a method with finishBlock (.h)
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
Insert previous defined method in .m file and commit finishBlock to #property defined before
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
To trigger completionBlock pass predefined variableType to it
(Don't forget to check whether the completionBlock exists)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}
Despite the answers given on this thread, I really struggled to write a function which would take a Block as a function - and with a parameter. Eventually, here's the solution I came up with.
I wanted to write a generic function, loadJSONthread, which would take the URL of a JSON Web Service, load some JSON data from this URL on a background thread, then return an NSArray* of results back to the calling function.
Basically, I wanted to keep all the background-thread complexity hidden away in a generic reuseable function.
Here's how I would call this function:
NSString* WebServiceURL = #"http://www.inorthwind.com/Service1.svc/getAllCustomers";
[JSONHelper loadJSONthread:WebServiceURL onLoadedData:^(NSArray *results) {
// Finished loading the JSON data
NSLog(#"Loaded %lu rows.", (unsigned long)results.count);
// Iterate through our array of Company records, and create/update the records in our SQLite database
for (NSDictionary *oneCompany in results)
{
// Do something with this Company record (eg store it in our SQLite database)
}
} ];
...and this is the bit I struggled with: how to declare it, and how to get it to call the Block function once the data was loaded, and pass the Block an NSArray* of records loaded:
+(void)loadJSONthread:(NSString*)urlString onLoadedData:(void (^)(NSArray*))onLoadedData
{
__block NSArray* results = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Call an external function to load the JSON data
NSDictionary * dictionary = [JSONHelper loadJSONDataFromURL:urlString];
results = [dictionary objectForKey:#"Results"];
dispatch_async(dispatch_get_main_queue(), ^{
// This code gets run on the main thread when the JSON has loaded
onLoadedData(results);
});
});
}
This StackOverflow question concerns how to call functions, passing a Block as a parameter, so I've simplified the code above, and not included the loadJSONDataFromURL function.
But, if you are interested, you can find a copy of this JSON loading function on this blog:
http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
Hope this helps some other XCode developers !
(Don't forget to vote up this question and my answer, if it does !)
The full template looks like
- (void) main {
//Call
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}
//Definition
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
//Execute a block
successBlock();
failureBlock([[NSError alloc]init]);
}
- (void) successMethod {
}
- (void) failureMethod:(NSError*) error {
}