Passing back data from view2 back to view1

Discussion in 'iOS Programming' started by larswik, Dec 9, 2012.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    This weekend I set out to understand how to pass data back from ViewController2 to ViewController1 when I exit VC2. I found a good explanation on line with helper code but I am not understanding a few things even though it works.

    So in VC1.h I import the header of VC2. I created in the xib a UIlabel and a UIbutton. The user presses the button and it pushes VC2 on the stack, easy
    Code:
    #import <UIKit/UIKit.h>
    #import "SecondVC.h"
    
    @interface ViewController : UIViewController [COLOR="Red"]<MyUsefulDelegate>[/COLOR]{
        IBOutlet UILabel *displayLable;
    }
    -(IBAction)pressButton:(id)sender;
    @end
    
    VC1.m
    Code:
    #import "ViewController.h"
    
    @implementation ViewController
    
    - (void)viewDidLoad
    //...Boilerplate code removed.
    
    -(IBAction)pressButton:(id)sender{
        SecondVC *svc = [[SecondVC alloc] init];
       [COLOR="Red"] [svc setMuDelegate:self];[/COLOR]
        [self.navigationController pushViewController:svc animated:YES];
    }
    
    - (void)infoReturned:(id)objectReturned {
        NSArray *tempArray = [NSArray arrayWithArray:objectReturned];
        displayLable.text = [tempArray objectAtIndex:0];
    }
    
    @end
    
    In VC2 I just have a textField, that is it. The user enters some string and presses the back button on the NavController (NavController set up in the AppDelete).
    Code:
    #import <UIKit/UIKit.h>
    
    [COLOR="Red"]@protocol MyUsefulDelegate <NSObject>
    - (void)infoReturned:(id)objectReturned;
    @end
    [/COLOR]
    @interface SecondVC : UIViewController{
        [COLOR="Red"]id <MyUsefulDelegate> muDelegate;[/COLOR]
        IBOutlet UITextField *textField;
    }
    @property (assign) id <MyUsefulDelegate> muDelegate;
    
    @end
    
    in the VC2.m I simply get the string in the textField and add it to an array and it is sent back to VC1 and displayed in the UILabel.

    Code:
    #import "SecondVC.h"
    
    @implementation SecondVC
    //...Boilerplate code removed.
    -(void)viewWillDisappear:(BOOL)animated{
        NSArray *myArray =[[NSMutableArray alloc] initWithObjects:textField.text, nil];
     [COLOR="Red"]   [[self muDelegate] infoReturned:myArray];[/COLOR]
    }
    
    @end
    
    It all works but a few things I don't get why?

    Q1. When VC2 is instantiated a @protocol is defined with 1 Method. In the @interface, in the ivar section, dose that then creating an object called muDelegate of type MyUsefulDelegate which is the protocol? I don't understand the 'id' part of that line? I know id is a generic object type and used in Methods, like in the Protocols method they use id. But it seems to be setting a return type in the ivar section where you declare your global instance variable, I don't get that?

    Q2. When the button is pressed, in VC1.m the VC2 object is instantiated. Since I declared an muDelegate object in the ivar section I gain access to that and then set it to 'self'. This has me totally confused, self? I could see this [svc setMuDelegate.delegate:self]; There you are telling the delegate to be 'self', or in charge of it's self.

    The @property section I get, it is creating the setters and getters to access this Method.

    Q3. After I get my string from the textField and add it to myArray there is the line of code
    Code:
    [[self muDelegate] infoReturned:myArray];
    
    When I normally do something to my objects, like add to myArray(if it was a mutableArray) I would write something like [array addObject:someObject]; But if I try and write code like this,
    Code:
    [muDelegate infoReturned:myArray];
    
    The code won't work. Why must I refer to that object with 'self' first? I don't refer to myArray that way [[self myArray] addObject: someObject];?

    Q4. That new @protocol what was created, that is now destroyed when I exit out of VC2 is gone, no longer accessible? Every time I instantiate a new VC2 a new @protocol is created. I am pretty sure that is right.
     
  2. MattInOz macrumors 68030

    MattInOz

    Joined:
    Jan 19, 2006
    Location:
    Sydney
    #2
  3. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #3
    I got the breakdown on http://stackoverflow.com for it. I did search and I do get what is happening with the majority of it. The code works in my test project just fine, but I wanted to understand it so I can replicated it in the future easily. I did Google last night but didn't quite get it still. The 2 lines of code that are throwing me off are these

    Code:
    id <MyUsefulDelegate> muDelegate;
    [[self muDelegate] infoReturned:myArray];
    
    The first looks like it is making a 'pointer' variable to the @protocol that was created. But there is no '*' (pointer)? The id that proceeds that from what I understand is a generic object type. It makes scenes if the code looked like this...
    Code:
    <MyUsefulDelegate> *muDelegate;
    
    There I could at least see a pointer to that new object, space in memory, that the Delegate is located. I have not been able to find anything that describable that? The only time I see things like that are when I work with Structs, CGSize size =. But this is not a Struct?

    As for the second line of code I posted, I do get that now. The encapsulation [self muDelegate] was throwing me off. When I deal with NavControllers I write [self.navigationController ....push:....]; When I wrote it like this [self.muDelegate method:argument]; I understood it. But the first on I don't get still.

    Sorry, just trying to get it. Spent all night last night researching it.

    Thanks!
     
  4. iphonedude2008 macrumors 65816

    iphonedude2008

    Joined:
    Nov 7, 2009
    Location:
    Irvine, CA
    #4
    When you do something like UILabel *label, you are making a pointer to a type of UILabel. When you do cgsize size, you are creating a new variable, not a pointer. So when doing id <MyUsefulDelegate> muDelegate, you are creating a variable which can take on any pointer type. It is not a pointer to an id, or a protocol because there would be no data to take on.

    Also, when you do uilabel *label, memory is not allocated nor is an object created. It just says, "this pointer, label, points to a uilabel and can do what a uilabel (or subclasses of uilabel) can do" when you do Uilabel *label = [[uilabel alloc]init], you allocate and create that classes variables and then initialize it and allow it to change an send methods. Then, you assign that to the pointer.

    EDIT: when you do id <myusefuldelegate> mudelegate, you say that this a pointer to any object that conforms to the protocol myusefuldelegate. You can not assign any object to that value, only ones that implement the required methods of that protocol.
     
  5. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #5
    I see that. It still looks odd to me but I will just have to deal with that. I understand the type is id, But when I declare a int I would say int num; So when I see' id <myusefuldelegate> ' I would see 'type varName;'. But here I am seeing 'type varName somethingElse'.

    Like you say it is not s Struct ether. Everything works and I can return the data but it just bugs me that I can't wrap my head around that yet.

    I'm sure it will sync in someday.

    Thanks!
     
  6. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    Think of it as: type <protocolName> variableName
     

Share This Page