Javascript promises in objective-c - objective-c

In javascript, there is this concept of promises where you can pass a function as a parameter to another function. For example:
doSomething(doSomethingElse());
I have written a block based code in Objective-C. Example usage of the code is as follows:
[MyObject doSomethingWithSuccessHandler:^()
{
[My object doSomethingMoreWithSuccessHandler:^()
{
[myObject saveTheResults];
}
failureHandler:^(MYError *myError)
{
[MyObject logError:myError];
}];
}
failureHandler:^(MYError *myError)
{
[MyObject logError:myError];
}];
Instead of the way that my block based code is used as shown in the above snippet, I would like it to be used in the following way (like javascript promises):
[MyObject doSomethingAndOnSuccess:[myObject doSomethingMoreAndOnSuccess:[myObject saveTheResults] onFailure:[myObject logError] ] onFailure:[myObject logError] ];
Is this possible? It's just for the sake of readability of the code as you can see that in the first case there is a lot of pyramid code that I would like to avoid.

Take a look at Bolts by Facebook and Parse.
These will give you what you are looking for.
https://developers.facebook.com/blog/post/2014/01/30/let-s-bolt/
You can get it as a Cocoapod too to install it easily.

What you're passing still needs to be blocks rather than method calls but the typedef suggestion from the link in comments can make things clearer.
E.g.:
typedef void (^FailureBlock)(NSError *);
typedef void (^SuccessBlock)();
- (void)startsHere
{
FailureBlock f = ^(NSError *myError){
[self logError:myError];
};
SuccessBlock s2 = ^(){
[self saveTheResults];
};
SuccessBlock s1 = ^(){
[self doSomethingMoreWithSuccessHandler:s2
failureHandler:f];
};
[self doSomethingWithSuccessHandler:s1
failureHandler:f];
}

Related

Generate an Obj-C Method

Is it possible to generate an Obj-C method? - For example:
- (void)doSomething:(BOOL)isLater
{
if (isLater == FALSE)
{
NSLog(#"Not Later");
} else {
NSLog(#"Is Later");
}
}
I'm specifically talking about generating the logic, I have some code that can create a class and add an existing method, but I'd like to know If I can generate the logic for the method itself and add it to a method?
static NSString *Description(id self, SEL _cmd)
{
return #"My Description Method";
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
Class mySubclass = objc_allocateClassPair([NSObject class], "MySubclass", 0);
// grab NSObject's description signature so we can borrow it
Method description = class_getInstanceMethod([NSObject class],
#selector(description));
const char *types = method_getTypeEncoding(description);
// now add
class_addMethod(mySubclass, #selector(description), (IMP)Description, types);
objc_registerClassPair(mySubclass);
id myInstance = [[mySubclass alloc] init];
NSLog(#"%#", myInstance);
}
If we are splitting hair:
Yes, technically, you can.
But it won't be easy at all.
Objective-C can be parsed by libclang (the C++ library which the clang compiler is based on) and then JIT-compiled and run using LLVM.
This way, you can embed clang and LLVM into your program, generate some Objective-C source text dynamically, parse it into an abstract syntax tree (or generate that AST directly, without writing and parsing any Objective-C), and compiling it. If you write a method that does this, then you can essentially run arbitrary Objective-C code dynamically from within your application.

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 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 {
}

Dynamic method creation in Objective-C

In the book The Pragmatic Programmer, the authors suggest that all method inputs should be validated. This allows problems with a method to be caught early and their sources traced easily.
In my Mac application, I accomplished this by creating an Assert class. This class has several class methods. These methods determine if some precondition is met, and if it is not, then an exception is thrown. A typical assertion might looks something like this:
-(void) setWidth: (int) theWidth {
[Assert integer: width isGreaterThanInteger: 0];
width = theWidth;
}
This works really well, and significantly reduced the amount of time I've spend bug hunting. However, I've noticed lately some of the assertion methods are very useful as predicates. For example, my integer:isGreaterThanInteger:andLessThanInteger: and my stringIsNotEmpty: methods are equally useful. To this end, I created a second class Predicate, which I filled with several of my more useful predicate methods. So I took the logic from the assert methods, and moved it into Predicate, and then rewrote my Assert methods like the following:
if ![Predicate predicateMethod]
throw exception
This has turned into a maintenance nightmare. If I change the name of a method name in Predicate, I must also change it in Assert to stay consistent. If I update the documentation of an Assert method, then I must do the same to a Predicate method.
Ideally, I would like the reconstruct the Assert class so that when any method is called on it, it intercepts the selector. The Predicate class can then be checked to see if it responds to the selector, and if it does, the method is called on Predicatewith the same arguments that were passed into the Assert method. If the Predicate method returns false, then an exception is thrown.
Is there a way to do this in Objective-C?
Thanks.
You could use -forwardingTargetForSelector: to simply forward the method to another object, but if you want advanced behavior (like checking the return value to see if it's false), you may need to use -forwardInvocation:. (However, note that the documentation says this is "much more expensive" than the former option.)
If you're using pure Objective-C, you should see the "Forwarding" discussion here. It basically describes how to do exactly what you want, including example code.
If you're using Cocoa then you might have to use forwardInvocation: instead.
I ended up overriding resolveClassMethod:. While overriding forwardInvocation might have worked (I would have had to figure out some way to override it for the class object), resolveClassMethod: seems like it's the easier and more efficient method. Here's what my final implementation ended up looking like:
#import "Assert.h"
#import "Predicate.h"
#include <objc/objc-runtime.h>
void handlePredicateSelector(id self, SEL _cmd, ...);
#implementation Assert
+(void) failWithMessage: (NSString *) message
{
NSLog(#"%#", message);
[NSException raise:#"ASSERTION FAILURE" format:message];
}
+(void) fail
{
[Assert failWithMessage:#"An unconditional failure has been detected."];
}
+(BOOL) resolveClassMethod: (SEL) selector
{
if ([(id) [Predicate class] respondsToSelector:selector])
{
/*
The meta class fix was taken from here: http://iphonedevelopment.blogspot.com/2008/08/dynamically-adding-class-objects.html
*/
//get the method properties from the Predicate class
Class predicateMetaClass = objc_getMetaClass([[Predicate className] UTF8String]);
Method predicateMethod = class_getClassMethod(predicateMetaClass, selector);
const char *encoding = method_getTypeEncoding(predicateMethod);
Class selfMetaClass = objc_getMetaClass([[self className] UTF8String]);
class_addMethod(selfMetaClass, selector, (IMP) handlePredicateSelector, "B#:?");
return YES;
}
return [super resolveClassMethod:selector];
}
#end
void handlePredicateSelector(id self, SEL _cmd, ...)
{
//get the number of arguments minus the self and _cmd arguments
NSMethodSignature *predicateMethodSignature = [(id) [Predicate class] methodSignatureForSelector:_cmd];
NSUInteger numberOfArguments = [predicateMethodSignature numberOfArguments] - 2;
NSInvocation *predicateInvocation = [NSInvocation invocationWithMethodSignature:predicateMethodSignature];
[predicateInvocation setTarget:[Predicate class]];
[predicateInvocation setSelector:_cmd];
va_list ap;
va_start(ap, _cmd);
for (int i = 0; i < numberOfArguments; i++)
{
void *arg = va_arg(ap, void *);
[predicateInvocation setArgument:&arg atIndex:i+2];
}
va_end(ap);
BOOL returnValue;
[predicateInvocation invoke];
[predicateInvocation getReturnValue:&returnValue];
//determine if the assertion is true
if (!returnValue)
{
[Assert failWithMessage:[NSString stringWithFormat: #"The following assertion failed: %#", NSStringFromSelector(_cmd)]];
}
}
The only thing I couldn't really figure out was how to get the type encoding from the method signature. It didn't seem to affect the output of the methods, but I would like to fix it if I can.

In Objective C what is the equivalent of passing a function pointer in C?

#implementation ThisObject
-(void)start {
SomeOtherObject *someOtherObject = [SomeOtherObject alloc];
[someOtherObject doSomethingAndCallThisFunctionWhenUrDone:myCallBackFunction :self];
}
-(void)myCallBackFunction {
// :)
}
Basically, how can I make this work?
There are four ways to make a callback:
Function Pointer You can do a function pointer if you really want, but it's not recommended. It's done the same way you would do it in C. The problem is you can't use a function pointer to an Objective-C method. It looks something like this:
void callback(/* Some args */) {
// Some callback.
}
- (void)doSomethingAndCallThisFunctionWhenDone:(void(*)(/* Some args */))func {
// Do something.
if (func)
func(/* Some args */);
}
- (void)start {
[self doSomethingAndCallThisFunctionWhenDone:&callback];
}
Selectors You can use -performSelector:. It looks like this:
- (void)doSomethingAndCallTarget:(id)target withSelector:(SEL)sel {
// Do something.
[target performSelector:sel];
}
- (void)start {
SomeOtherObject * someOtherObject = [[SomeOtherObject alloc] init];
[self doSomethingAndCallTarget:someOtherObject withSelector:#selector(MyCallback)];
}
Delegates Use a delegate. This is similar to UITableViewDelegate/UITableViewDataSource. See the Apple docs here. You might do it like this:
- (void)doSomethingDelegate:(id<MyCallbackObject>)delegate {
[delegate retain];
// Do something.
[delegate performMyCallback]; // -performMyCallback must be declared in the MyCallbackObject protocol and implemented by SomeOtherObject.
[delegate release];
}
- (void)start {
id<MyCallbackObject> someOtherObject = [[SomeOtherObject alloc] init];
[self doSomethingDelegate:someOtherObject];
[someOtherObject release];
}
Blocks The preferred way for callbacks is to use blocks. They are only available for iOS 4.0+ or Mac OS X 10.6+. It looks something like this:
- (void)doSomethingAndCallThisBlockWhenDone:(void(^)(/* Some args */))block {
[block copy];
// Do something.
if (block)
block(/* Some args */);
[block release];
}
- (void)start {
[self doSomethingAndCallThisBlockWhenDone:^void(/* Some args */){ // Return type and arguments may be omitted if you don't have any.
// Your callback
}];
}
As you can see with the block, it's easier to read and your callback is inline with your code. This is especially nice so you don't have to hunt it down. There are many more benefits of blocks, but I couldn't possibly cover them all here.
One last thing, if you use a block, you will want to use a typedef so you don't have to type obscure block types like void(^)(/* Some args */) all the time. The typedef could look like this:
typdef void(^MyCallback)(/* Some args */);
Then, you can declare your method like this:
- (void)doSomethingAndCallThisBlockWhenDone:(MyCallback)block;
Update:
I have shown more detail of how to implement the different techniques (see above).
Are you talking about this?
-(void)callSomePassedSelector:(SEL)callbackSelector {
[someObjectThatRespondesToThisSelector performSelector:callbackSelector];
}
I assume you want to store it and call it later, but this should give you all the needed information about how to pass and call it. There are other methods to invoke the selector, see more here
im a bit confused about what you talking about but is this it?
[self performSelector:#selector(myCallFunction)];