What are alternatives to “delegates” for passing d

2020-02-23 04:28发布

问题:

Are there alternatives to "delegates" to pass back data from one controller to another?

Just seems like a lot of work implementing a delegate just to pass back the result from a child controller, back to the parent controller. Is there not another method? Are "blocks" one answer, and if so some example code would be great.

回答1:

You could use many ways:

  1. Calling a method of the super controller, needs casting maybe
  2. Notifications
  3. Simple Key-Value-Observing
  4. Core Data

Example for for 1.

interface of your MainViewController: add a public method for the data to be passed

- (void)newDataArrivedWithString:(NSString *)aString;

MainViewController showing ChildController

- (void)showChildController
{
    ChildController *childController = [[ChildController alloc] init];
    childController.mainViewController = self;

    [self presentModalViewController:childController animated:YES];

    [childController release];
}

Child Controller header / interface: add a property for the mainViewController

@class MainViewController;

@interface ChildController : UIViewController {
    MainViewController *mainViewController;   
}

@property (nonatomic, retain) MainViewController *mainViewController;

Child Controller passing data to the MainViewController

- (void)passDataToMainViewController
{
    NSString * someDataToPass = @"foo!";
    [self.mainViewController newDataArrivedWithString:someDataToPass];
}


回答2:

Delegates aren't a lot of work, aren't a lot of code, and are commonly the most appropriate solution. In my opinion they're neither difficult nor messy.

Five lines of code in the child's interface. Before @interface:

@protocol MyUsefulDelegate <NSObject>
- (void)infoReturned:(id)objectReturned;
@end

Inside @interface:

id <MyUsefulDelegate> muDelegate;

After @inteface's @end:

@property (assign) id <MyUsefulDelegate> muDelegate;

One line of code in the child's implementation:

[[self muDelegate] infoReturned:yourReturnObject];

One addition to an existing line of code in the parent's interface:

@interface YourParentViewController : UIViewController <MyUsefulDelegate>

Three lines of code in the parent's implementation. Somewhere before you call the child:

[childVC setMuDelegate:self];

Anywhere in the implementation:

- (void)infoReturned:(id)objectReturned {
    // Do something with the returned value here
}

A total of nine lines of code, one of which is merely an addition to an existing line of code and one of which is a closing curly brace.

It's not as simple as a returning a value from a local method, say, but once you're used to the pattern it's super straightforward, and it has the power of allowing you do do all kinds of more complex stuff.



回答3:

KVO or notifications are the way to go in many cases, but delegation gives a very good foundation to build upon. If you plan on extending the relationship between the view controllers in the future, consider using delegation.

Blocks are not really relevant to the above, but in short - it is a technique introduced with iOS 4, where you pass around blocks of code as variables/ parameters. It is very powerful and has many uses. For example, here is how you enumerate objects in an array using a block:

[someArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop){
    NSLog(@"obj descriptions is - %@", [obj description]); 
}]; 

The part from the ^ until the } is a block. Note that I've passed it in as parameter. Now, this block of code will be executed for every object in the array (i.e. output will be the description of each object).

Blocks are also very efficient performance-wise, and are used heavily in many new frameworks.

Apple's blocks beginners guide is quite good.



回答4:

Check out NSNotificationCenter — NSNotificationCenter Class Reference



回答5:

Folks pay a lot of attention the the V and the C in MVC, but often forget the M. If you've got a data model, you can pass it from one controller to the next. When one controller makes changes to the data stored in the model, all the other controllers that share the same model will automatically get the changes.



回答6:

You might find using a singleton is practical. Just use it as a central storage for all your shared data.

Then throw in saving the state of your application too;)