質問

I'm trying to use a delegate to pass a value from one VC to another. I think I'm am misunderstanding the way it is supposed to work.

In my main ViewController.h I have this:

@protocol defaultLocationChoice <NSObject>

- (NSString *) locChoice;

@end

In both my PreferencesViewController.h and ChooseServerViewController.h I have defaultLocationChoice declared in the @interface section and the property assinged like so:

@property (nonatomic, assign) id <defaultLocationChoice> locationDelegate;

Both are synthesized also.

When the user segues from PreferencesViewController to ChooseServerViewController the prepare for segue code is:

- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if ([segue.identifier isEqualToString:@"toServerChoice"]) {
        ChooseServerViewController *viewController = (ChooseServerViewController *)segue.destinationViewController;
        viewController.locationDelegate = self;

    }

}

When a cell choice is made in ChooseServerViewController I call:

[self locChoice];

Which is:

- (NSString *) locChoice {
    NSLog(@"Cell Vale Loc choice %@",cellValue);
    return cellValue;
}

The NSLog verifies the correct value is returned.

Now, as I think I understand it, the value of LocChoice in the delegate is now the value returned, no?

When the user goes back (NavController) the PreferencesViewController has:

-(void) viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];
    defaultLocation = [locationDelegate locChoice];
    [self.tableView reloadData];  
}

I was expecting the value of defaultLocation to now equal the value passed to locChoice. However when the table reloads the cell in question is still blank, implying what I exepct to happen isn't happening.

Any ideas?

役に立ちましたか?

解決

If I followed your code properly, you do not need to adopt the mentioned protocol in your ChooseServerViewController, only PreferencesViewController.

The reasoning is you want to send data back to the previous view controller. Try:

@protocol defaultLocationChoice <NSObject>
    - (void) locChoice:(NSString*)choice;
@end

Have your PreferencesViewController implement that method so it receives the selection. You will have to store that in an appropriate instance variable.

// in PreferencesViewController.m
-(void)locChoice:(NSString*)choice {
    self.choice = choice;  // this just my example
}

When the choice is made (in ChooseServerViewController) to send the choice back, call:

// this is in 'ChooseServerViewController.m' some where appropriate
[self.delegate locChoice:cellValue];

Your implementation is simply doing nothing with cell value (not even storing it, just logging it). When you return to PreferencesViewController, you will now have the selected value and that view controller can what it wants with it.

Protocols are somewhat analgous to interfaces in Java or C#, but more flexible.

UPDATE:

The declaration for ChooseServerViewController should look like:

#import "FileWithProtocolDecalration.h"
@interface ChooseServerViewController
.
.
.
@property ( nonatomic,assign) id<defaultLocationChoice> delegate;
.
.
.
@end

他のヒント

I think you do have some misunderstanding there

protocol and delegates are something that is passed around. in other words somebody need to be receiver and somebody need to be the sender. in your case.
update your protocol to this

@protocol defaultLocationChoice <NSObject>

- (void)locChoice:(NSString *)updateString;  // the method from delegate and implementer must be exact

@end  

and set implement the protocol to ViewController as a receiver

@interface VCReceiver : UIViewController <defaultLocationChoice>

then later in VCReceiver

- (void)viewDidLoad {  
    ChooseServerViewController *vcSender = [[ChooseServerViewController alloc] init];
    [vcSender setLocationDelegate:self]; // this is like saying. i have implemented method from protocol in this file (self)
}
- (void)locChoice:(NSString *)updateString {
    // update the VCReceiver here
    // or access vcSender value 
    // or use the updateString value
}

then in ChooseServerViewController locChoice: method (the one from your example) replace with this one and call [self updateChoice] instead:

- (void)updateChoice {
    if ([self.locationDelegate respondsToSelector:@selector(locChoice:)]) {
         [self.locationDelegate locChoice:aStringToUpdate]; // this will call VCReceiver locChoice
   }

it does not have to return anything because it is actually calling the VCReceiver method to tell it that ChooseServerViewController got the value ready to be read.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top