2

I have two viewcontrollers, ViewControllerA and ViewControllerB respectively.

On ViewcontrollerB there are tableview cells. On click of tableview cells I want to send the data selected on ViewControllerB to label on ViewControllerA.

I know it can be achieved through many ways but how can this be achieved through blocks.Kindly suggest.

Thanks in advance!

ViewController B

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *viewArr = [self.array objectAtIndex:indexPath.row];

    NSLog(@"the value obtained on cell is %@",viewArr);
    ViewController *vc=[[ViewController alloc]init];
    vc.aSimpleBlock(viewArr);   
}
TestShroff
  • 87
  • 9

5 Answers5

3

In your ViewController A

1) Declare a typedef for block say typedef void (^simpleBlock)(NSString*);

2) Create a block variable like

@property(nonatomic,strong)simpleBlock  aSimpleBlock;

3) Define this block in viewDidAppear / viewDidLoad

aSimpleBlock = ^(NSString* str){
        NSLog(@"Str is the string passed on tableView Cell Click..!!");
    };

In your ViewController B Where you have tableView

1) In -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

just call your block as

your_VC_A_Object.aSimpleBlock("Your_Label_String_here");
Vishal Sonawane
  • 2,637
  • 2
  • 16
  • 21
  • It gives EXC_BAD_ACCESS exception when following line is executed : your_VC_A_Object.aSimpleBlock("Your_Label_String_here"); – TestShroff Feb 22 '17 at 07:19
  • @TestShroff You are creating new object there. No need to create new object, just pass the object reference from where you are navigating to VC B. When you create new instance , it will create new block variable so you will not be able to reference the same block. – Vishal Sonawane Feb 22 '17 at 07:28
  • @TestShroff Welcome .. and if this solves your problem, mark it as correct answer so that the other members can find it useful. Happy coding..!! – Vishal Sonawane Feb 22 '17 at 07:34
  • "just pass the object reference from where you are navigating to VC B."explain this a little more please. – TestShroff Feb 22 '17 at 09:16
  • Say you are navigating from VC1 to VC2. Then create VC1 variable in VC2 (but don't initialize it with alloc init). Now when you are going to push VC2, do like this: VC2_object.VC1_Variable_you_created = self. – Vishal Sonawane Feb 22 '17 at 09:24
  • You could also just define a regular method in A and call it from B. What advantage do you get from using a block instead? – Brett Donald Feb 22 '17 at 22:07
  • @BrettDonald Yes we can do this with simple method also. But I think I have answered 'I know it can be achieved through many ways but how can this be achieved through blocks.Kindly suggest.' this. Second thing, the advantage of blocks is blocks are faster than delegates also using blocks we can have the inline execution which makes code more readable. – Vishal Sonawane Feb 23 '17 at 04:54
  • Have a look at this :http://stackoverflow.com/questions/12176961/what-is-the-purpose-of-using-blocks – Vishal Sonawane Feb 23 '17 at 04:59
  • So, @TestShroff, did you try it? What do you think of the result? Do you prefer the delegate code or the block code? Why? – Brett Donald Feb 23 '17 at 05:12
  • @Brett Donald yes,i have implemeted it .I know it can be achieved through other ways also...but just to understand blocks i wanted to implement using blocks. – TestShroff Feb 23 '17 at 05:20
1

You can define a block in viewControllerB and set it ViewController A, when select a cell, you can call this block and pass the value to it, something like:
In viewControllerB

// ViewControllerB.h
@interface ViewControllerB : UITableViewController

@property (nonatomic, copy) void (^didSelectCellBlock)(id obj);
@end

// ViewControllerB.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        NSString *str = [self.dataArray objectAtIndex:indexPath.row];
        if (self.didSelectCellBlock) {
            self.didSelectCellBlock(str);
        }
        ...
    }
}

And In ViewController A

 ViewControllerB *controllerB = [[ViewControllerB alloc] init];
 __weak __typeof(self) weakSelf = self;
 controllerB.didSelectCellBlock = ^(id obj) {
     weakSelf.label.text = (NSString *)obj;
 };
1

step-1

initially add parent class of VC-B to VC-A

@interface ViewControllerA : ViewControllerB

Step-2

create the one common method in interface on ViewControllerB

@interface ViewControllerB : UIViewController

-(void)shareContent:(NSString*)currentText;

step-3

on that ViewControllerB implementation file

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
 {
     __weak typeof(self) weakSelf = self;

      dispatch_async(dispatch_get_main_queue(), ^ {

         [weakSelf shareContent: [_items objectAtIndex:indexPath.row]];

    });


}

Step-4

on your ViewControllerA implementation file

 -(void)shareContent:(NSString*)currentText
 {

   NSLog(@"Local details:%@", currentText);
 }

Choice -2

for alternate Way , you can get the sample from here or example

Community
  • 1
  • 1
Anbu.Karthik
  • 82,064
  • 23
  • 174
  • 143
0

I don't know if that's sensible or even possible.

To pass data directly between view controllers, I often use delegates. I would add a delegate property to B and have it define a delegate protocol. I would have A implement that protocol and have B invoke those protocol methods to pass the data. And, of course, set B's delegate to A.

Brett Donald
  • 6,745
  • 4
  • 23
  • 51
  • Yes it's possible and even feasible as blocks are faster than delegates also using blocks we can have the inline execution which makes code more readable. But it is also true that you can't replace delegates everywhere with blocks, sometimes delegates are essential rather than blocks. – Vishal Sonawane Feb 22 '17 at 06:50
0

Well in that case you'd have to provide a block from ViewControllerA so the other one (ViewControllerB) can handle it (as a property), retain it and call when you select the table row.

But the benefit over the delegation? Not much in fact, delegation is way more a standard pattern to use in this case.

Michi
  • 1,464
  • 12
  • 15
  • In fact delegation is better because (a) it's the standard pattern, and (b) it avoids A and B being dependent on each other. Using delegation keeps B independent. – Brett Donald Feb 22 '17 at 22:03
  • @michi and Brett Donald I think you guys should have a look at this :http://stackoverflow.com/questions/12176961/what-is-the-purpose-of-using-blocks – Vishal Sonawane Feb 23 '17 at 04:59
  • Blocks are certainly valuable in many situations. I just don't think they're the right choice in THIS situation. – Brett Donald Feb 23 '17 at 05:05