Reputation: 1774
I beginner in iOs programming. I have some problem. I have MasterViewController, code below
#import "MasterViewController.h"
#import "DetailViewController.h"
@interface MasterViewController () {
}
@property (strong, nonatomic) NSString *str;
@end
@implementation MasterViewController
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.str = @"1234";
}
and I send property "str" to DetailViewController.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSString *object = self.str;
[[segue destinationViewController] setDetailItem:object];
}
}
after, I change str
#import "DetailViewController.h"
@interface DetailViewController ()
@end
@implementation DetailViewController
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.detailItem = @"1233";
}
after, I come back to MasterViewController but str don't change. Why?
Upvotes: 0
Views: 65
Reputation: 12015
The problem is that you're just changing which object the detailItem
property refers to in DetailViewController
, rather than changing the value of the object itself. When you set self.detailItem
in the viewDidLoad
method, the str
property MasterViewController
will continue to point to the original string:
Before:
MasterViewController.str -> 1234 <- DetailViewController.detailItem
Then you do self.detailItem = 1233
. It doesn't change the value of the strings themselves, but just makes detailItem point to a new string. Looking at the graph below, it moves the arrow pointing from DetailViewController rather than changing the content of "1234" itself:
MasterViewController.str -> 1234
1233 <- DetailViewController.detailItem
What you want to do here is use the delegate pattern to properly notify the MasterViewController of changes in the detail controller and give it access to the new value.
DetailViewController.h:
// declare the delegate protocol
@class DetailViewController;
@protocol DetailViewControllerDelegate <NSObject>
-(void)detailViewControllerChangedDetailItem:(DetailViewController *)detailController;
@end
@interface DetailViewController
// add a property for the delegate
@property (nonatomic, copy) NSString *detailItem;
@property (nonatomic, weak) id <DetailViewControllerDelegate> delegate;
@end
DetailViewController.m:
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// notify the delegate whenever the detailItem changes
[self.delegate detailViewControllerChangedDetailItem:self];
}
}
MasterViewController.m:
// mark this as implementing the delegate protocol
@interface MasterViewController () <DetailViewControllerDelegate> {
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:@"showDetail"]) {
NSString *object = self.str;
// wire up the delegate connection
[[segue destinationViewController] setDelegate:self];
// now whenever detailItem changes in the DetailViewController,
// it will notify its delegate (the master VC)
[[segue destinationViewController] setDetailItem:object];
}
}
// implement the delegate method
-(void)detailViewControllerChangedDetailItem:(DetailViewController *)detailController
{
// now you can get a copy of the new detailItem value
// and do whatever you want with it.
self.str = detailController.detailItem;
}
Upvotes: 1