Blocks with no return value - ios

Is there a proper way to write a block with no return value in Objective-C? All the examples that I have seen are all with return values. Can someone also please explain the difference between a completion block & a regular block? I know the ^ means that it is a block but doesn't the + before (void) mean it is a block as well?

Here is what a method header would look like if it has a parameter of a block:
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
So a block with no return type and no parameters would look something like this:
- (void)someMethodThatTakesABlock:(void (^)(void))blockName;
A regular block is just a set (or group) of code. A completion block is a block that will be executed when the method is completed. A completion block is a regular block, it just is specific to being called at the end of a method.
The ^ signifies a block. The + before a method is a class method.
Other ways to use blocks
As a local variable
returnType (^blockName)(parameterTypes) = ^returnType(parameters) {...};
As a property
#property (nonatomic, copy) returnType (^blockName)(parameterTypes);
As a method parameter
- (void)someMethodThatTakesABlock:(returnType (^)(parameterTypes))blockName;
As an argument to a method call
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
As a typedef
typedef returnType (^TypeName)(parameterTypes);
TypeName blockName = ^returnType(parameters) {...};
You would just replace returnType with void.

Here is a demo:
1、no return values and no parameter:
- (void)viewDidLoad {
[super viewDidLoad];
//block
void(^myBlock)(void) = ^(void) {
NSLog(#"This is a block without parameter and returned value");
};
myBlock();
2、no return values and have parameter:
-(void)blockWithParameterButNoReturnData
{
void(^myBlock)(int) = ^(int num) {
NSLog(#"%d",num*100);
};
myBlock(4);
}
3、have retrun values and have parameter:
-(void)blockWithParameterAndReturnValue
{
int (^myBlock)(int) = ^(int num) {
return num * 100;
};
int result = myBlock(2);
NSLog(#"This is a block with parameter and return value :%d",result);
}
PS:for more infomation,see this website:http://www.cnblogs.com/zhanggui/p/4656440.html

Related

Unable to access a block which is passed as arguments in this method

In the following example, I have no idea on how to access the block which I passed as parameter in the method. I should have used typedef, but only if I broke the code, I could get the below scenario. So didn't use typedef
#interface ViewController ()
- (void(^)(void)) anotherMethodWithReturnTypeAnd: ( void ( ^ )( int ))argumentsBlock;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
void (^twoBlock)(void) = [ self anotherMethodWithReturnTypeAnd:^(int n) {
NSLog(#"%d, block without typedef",n);
}];
twoBlock();
}
- (void(^)(void)) anotherMethodWithReturnTypeAnd: ( void ( ^ )( int n) )argumentsBlock{
void (^blockToPassAsReturnType)(void) = ^{
NSLog(#"Passing this block as return type");
};
return blockToPassAsReturnType;
}
OUTPUT:
2017-09-05 00:23:08.148 DeleteThisBlockProject[657:22195] Passing this block as return type
So how should I use and pass value for the block which I passed as parameter, [ self anotherMethodWithReturnTypeAnd:^(int n) {
NSLog(#"%d, block without typedef",n);
}];
You didn't call method
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
void (^twoBlock)(void) = [ self anotherMethodWithReturnTypeAnd:^(int n) {
// this will never execute because you didn't call it you just implemented it
NSLog(#"%d, block without typedef",n);
}];
twoBlock();
}
- (void(^)(void)) anotherMethodWithReturnTypeAnd: ( void ( ^ )( int n) )argumentsBlock{
void (^blockToPassAsReturnType)(void) = ^{
NSLog(#"Passing this block as return type");
};
// you should call method which you did provide to this function
argumentsBlock(yourInt)
return blockToPassAsReturnType;
}

How to make function which takes block as parameter and one boolean and in body if boolean is true executes that block?

How do you make a function which takes block as parameter and one boolean and in body; and if the boolean is true executes that block ?
The Block has no returning value ( void ) and does not take any parameter.
In c++ I would do this with function pointers but I am new to objective c and don't know how to perform conditional execution of blocks.
Declare your method as
-(void)myBlock:(void (^)(void))block withCondition:(BOOL)condition{
if(condition){
block();
}
}
Call it as:
[self myBlock:^(void) {
NSLog(#"Hii block excuted");
} withCondition:YES];
For more detail you can find it in HERE
Objective-C Method:
- (void)executeBlock:(void (^)(void))block onCondition:(BOOL)condition
{
if (condition)
{
block();
}
}
C function:
void executeBlock(void (^block)(void), BOOL condition)
{
if (condition)
{
block();
}
}

What is the correct syntax

I want to define a block similar to NSArray enumerateObjects:usingBlock
my block is as follows
typedef void (^MyBlock)(BOOL *);
and i want to invoke it in some method, so that the method would give me the BOOL value to stop
how do I continue from here ?
EDIT:
I want to do the following
BOOL replaceSomething;
[self someMethod:MyBlock(&replaceSomething)] <== this syntax is not correct
if(replaceSomething){
do something
}
-(void)someMethod:^void(BOOL *stop){
*stop = YES;
}
Here's a handy and an easy to remember site when dealing with blocks:
http://fuckingblocksyntax.com
What you're looking for exactly is the last part (using typedef):
typedef void (^ MyBlock)(id, BOOL);
MyBlock myBlock = ^(id myId, BOOL myBool) {...};
P.S. Note that BOOL is not an object, but a primitive type.

Return the result of the outer method from the block in Objective-C

I have a method that creates a block inside. Is it possible to return the result of the method from this block? Something like:
- (id)myFunction {
//some code here
BlockType myBlock = ^{
//some other code here
return someObject; //is it possible to return something for myFunction?
};
[someOtherObject methodWithBlock: myBlock];
}
Blocks can have a return type. Here's an example.
First you define a block type (optional, but convenient)
typedef NSString * (^BlockType)(NSString *name);
^^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^^^^^^
return type type name parameters
Then you can instantiate a block like follows
BlockType aBlock = ^ NSString * (NSString *name){
return [#"Hello " stringByAppendingString:name];
};
And use it
NSString *salutation = aBlock(#"Nikita");
NSLog(#"%#", salutation); // => Hello Nikita

Expect Argument Type to be integer but getting id instead

I'm using the forwardInvocation: feature of objective-c and I need to know what type of argument the method received. In my example I'm passing it an int but getArgumentTypeAtIndex: tells me it's an id instead. Here's a simple example:
#interface Do : NSObject
+ (void) stuff:(int)x;
#end
#implementation Do
+ (NSMethodSignature *) methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature)
signature = [self methodSignatureForSelector:#selector(forwardInvocation:)];
return signature;
}
+ (void)forwardInvocation:(NSInvocation *)i
{
const char* argType = [i.methodSignature getArgumentTypeAtIndex:2];
NSLog(#"%s == %s", argType, #encode(id)); // # == #
NSLog(#"%s == %s", argType, #encode(int)); // # == i
}
#end
Here's how I call it:
[Do stuff:123];
Any idea why I'm not getting id instead of int as the type?
The problem is that you don't have actually have a stuff: method on the class so methodSignatureForSelector: will return nil - it looks like you discovered that and so implemented your own version, but that fails on the super call and so ends up returning the signature of forwardInvocation: - which is not what you want!
To get around this you either need to direct the methodSignatureForSelector: to a class which has the selector, or use a protocol - if a class implements a protocol then it will return the signature for any methods in that protocol even if the methods are not actually implemented by that class.
Here is your sample using a protocol:
#protocol DoProtocol
#optional
+ (void) stuff:(int)x;
#end
#interface Do : NSObject<DoProtocol>
#end
#implementation Do
+ (void)forwardInvocation:(NSInvocation *)i
{
const char* argType = [i.methodSignature getArgumentTypeAtIndex:2];
NSLog(#"%s == %s", argType, #encode(id)); // # == #
NSLog(#"%s == %s", argType, #encode(int)); // # == i
}
#end
The #optional avoids any compiler warnings for unimplemented methods. The default implementation of methodSignatureForSelector: (from NSObject) will return a valid signature obtained from the protocol, and so forwardInvocation: will be called.
As long as you can get it past the compiler, whatever you pass as an argument will be interpreted as such at runtime - you could declare that a function takes an NSNumber, but it you pass a UITableView to it, it's class will still be a UITableView.

Resources