views:

44

answers:

1

How can I create my own methods which take a block as an argument and which I can call later?

I have tried following things.

#import <UIKit/UIKit.h>
typedef void (^viewCreator)(void);

@interface blocks2ViewController : UIViewController
{
}
-(void)createButtonUsingBlocks:(viewCreator *)block;

@end


- (void)viewDidLoad {
  [super viewDidLoad];
  [self createButtonUsingBlocks:^(NSString * name) {
        UIButton *dummyButton = [[UIButton alloc]initWithFrame:CGRectMake(50, 50, 200, 100)];
        dummyButton.backgroundColor = [UIColor greenColor];
        [self.view addSubview:dummyButton];
  }];
}

-(void)createButtonUsingBlocks:(viewCreator *)block
{
    //    Do something
    NSLog(@"inside creator");
}

I have also tried to pass the block variable to my custom method but without any success. Why it is so and what is the right way to do this?


Update

This is file is.h:

 #import <UIKit/UIKit.h>

typedef void (^viewCreator)(void);

@interface blocks2ViewController : UIViewController
{

}
- (void)createButtonUsingBlocks:(viewCreator)block;
@end

And this is the .m file:

#import "blocks2ViewController.h"

@implementation blocks2ViewController
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
        [self createButtonUsingBlocks:^(NSString * name) {
        UIButton *dummyButton = [[UIButton alloc]initWithFrame:CGRectMake(50, 50, 200, 100)];
        dummyButton.backgroundColor = [UIColor greenColor];
        [self.view addSubview:dummyButton];
        [dummyButton release];
    }];
}

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

// ...

-(void)createButtonUsingBlocks:(viewCreator)block
{
//    viewCreator;
    NSLog(@"inside creator");
}
@end
+4  A: 

First the typedef is off if you want to let your blocks take a string parameter:

typedef void (^viewCreator)(NSString*);

Secondly the type for blocks is:

ReturnType (^)(ParameterTypes...)

and not

ReturnType (^*)(ParameterTypes...)

Thus there is no need to add pointers to the viewCreator type:

- (void)createButtonUsingBlocks:(viewCreator)block;

Third you actually have to call the block if you are not doing that yet:

-(void)createButtonUsingBlocks:(viewCreator *)block {
    block(@"button name");
    // ...

Fourth and last, the UIButton is over-retained - you should release or autorelease it:

UIButton *dummyButton = [[UIButton alloc] initWithFrame:...];
// ...    
[self.view addSubview:dummyButton];
[dummyButton release];

Throwing all that together:

#import <UIKit/UIKit.h>
typedef void (^viewCreator)(NSString*);

@interface blocks2ViewController : UIViewController {}
-(void)createButtonUsingBlocks:(viewCreator)block;      
@end

@implementation blocks2ViewController
- (void)viewDidLoad {
    [super viewDidLoad];  
    [self createButtonUsingBlocks:^(NSString *name) {
        UIButton *dummyButton = 
            [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 200, 100)];
        dummyButton.backgroundColor = [UIColor greenColor];
        [self.view addSubview:dummyButton];
        [dummyButton release];
    }];
}

-(void)createButtonUsingBlocks:(viewCreator)block {
    block(@"my button name");
}
@end
Georg Fritzsche
No it's still not working for me.....
Ajay Pandey
@Ajay: See the edit, are you actually calling the block somewhere?
Georg Fritzsche
Awesome answer. One additional note; if your goal is to store the block and call it later, you need to `copy` the block. Blocks start out on the stack and very bad things will happen if to call a block that wasn't copied after the declaring stack frame has been destroyed.
bbum
OK now that i have commented typedef statement and since i am using block as inline function(i am actualy calling createButtonUsingBlocks:,which in turn takes that block as an argument)So i need not to copy ot,right?But still there seems some error...It will be nice if you can just post few lines in which a custom method takes block as argument and use it later on.This will make a more clearer picture..
Ajay Pandey
@Ajay: What is some error? And what do you mean with later on? Just passing a block to a method and calling it in there? With the code structured as in your question, if you call the block in `-createButtonUsingBlocks:` there is no problem. By the way, Mike Ash had a good post on [block basics](http://www.mikeash.com/pyblog/friday-qa-2009-08-14-practical-blocks.html).
Georg Fritzsche
ot's a very smaal code and it gives error in those lines where i have declared the -createButtonUsingBlocks: and where i have defined -createButtonUsingBlocks: I am sure it's syntectical error,that's why i wanted you to send few lines sothat i knowwhere i am wrong..Error reads expected ')' before 'viewCreator'
Ajay Pandey
y .h file looks looks this
Ajay Pandey
#import <UIKit/UIKit.h>@interface blocks2ViewController : UIViewController { }- (void)createButtonUsingBlocks:(viewCreator)block;@endsorry for any silly mistake..
Ajay Pandey
@Ajay: You are now missing the `typedef void (^viewCreator)(NSString*);` before your interface declaration.
Georg Fritzsche
but you said it's off when my block takes any parameter
Ajay Pandey
specifically if the argumnt happens to be NSString
Ajay Pandey
@Ajay: With it being off i meant the `typedef` was wrong and has to be changed, not to remove it. See the edit.
Georg Fritzsche
and after writing typedef there is an error in my viewDidLoad saying error: incompatible block pointer types initializing 'void (^)(struct NSString *)', expected 'viewCreator' My viewDidLoad looks like this
Ajay Pandey
- (void)viewDidLoad { [super viewDidLoad]; [self createButtonUsingBlocks:^(NSString * name) { UIButton *dummyButton = [[UIButton alloc]initWithFrame:CGRectMake(50, 50, 200, 100)]; dummyButton.backgroundColor = [UIColor greenColor]; [self.view addSubview:dummyButton]; [dummyButton release]; } ];}
Ajay Pandey
@Ajay: Compare your version with what i added above. If that doesn't help add your current code to the question or into PasteBin or similar.
Georg Fritzsche
OK I am pasting my code again to question
Ajay Pandey
sorry george,it's now working but i could not know the reson.Why it's not working when i am declaring it in .h file...Should i take it as a way to use methods taking block or what?
Ajay Pandey
Thanks a lot george.It wasthe best way i could have learnt how to create our custom methods using blocks.Thanks for everything.
Ajay Pandey