2017-08-11 50 views
7

我正在学习如何使用志愿。我创建了两个类,Truck和Driver,如下所示。如何使用KVO传递值?

Truck类有一个文本框和一个按钮,文本应该包含当前的卡车速度,当按下按钮时,prepareForSegue应该被调用,它包含下面的代码。

Driver类包含应该充满低速载货一个文本框。 Truck类中的卡车速度将通过KVO传递给Driver类中的文本字段,如代码所示。

我遇到的问题或者我想要做的是,当用户在Truck类中输入卡车的速度并按下按钮时,我想要显示在Driver类中的文本字段中输入的卡车速度通过志愿

我按照以下发布的代码得到的结果是,在驱动程序类的空文本字段

请让我知道为什么在驱动程序类文本字段为空。和我应该怎么通过志愿

Truck.m

#import "TruckViewController.h" 
#import "DriverViewController.h" 
#import "ServerViewController.h" 

@interface TruckViewController() 

@property (strong, nonatomic) IBOutlet UITextField *textFieldCurrenSpeed; 
@property (strong, nonatomic) IBOutlet UIButton *buttonBroadcast; 
@property (strong, nonatomic) IBOutlet UIButton 
*buttonToDriverViewController; 
@property (strong, nonatomic) IBOutlet UIButton 
*buttonToServerViewController; 
@property (strong, nonatomic) TruckViewController *truck; 
@property (strong, nonatomic) DriverViewController *driver; 
@property (strong, nonatomic) ServerViewController *server; 

@end 


@implementation TruckViewController 


- (void)viewDidLoad { 
[super viewDidLoad]; 
// Do any additional setup after loading the view. 
} 


- (void)didReceiveMemoryWarning { 
[super didReceiveMemoryWarning]; 
// Dispose of any resources that can be recreated. 
} 


-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
self.truck = [[TruckViewController alloc] init]; 
self.driver = [[DriverViewController alloc] init]; 
self.server = [[ServerViewController alloc] init]; 

if ([segue.identifier isEqualToString:@"segueToDriver"]) { 

    [self.truck addObserver:self.driver 
      forKeyPath:@"currentSpeedOfTheTruck" 
       options:NSKeyValueObservingOptionNew 
       context:NULL]; 

    self.truck.currentSpeedOfTheTruck = [self.textFieldCurrenSpeed 
text]; 
    NSLog(@"prepareForSegue: %@", self.truck.currentSpeedOfTheTruck); 
} 

if ([segue.identifier isEqualToString:@"segueToServer"]) { 

    [self.truck addObserver:self.server 
      forKeyPath:@"currentSpeedOfTheTruck" 
       options:NSKeyValueObservingOptionNew 
       context:NULL]; 

    self.truck.currentSpeedOfTheTruck = [self.textFieldCurrenSpeed 
text]; 
    NSLog(@"text entered: %@", self.truck.currentSpeedOfTheTruck); 

} 

} 

- (void)dealloc 
{ 
[self.truck removeObserver:self.driver 
forKeyPath:@"currentSpeedOfTheTruck"]; 
[self.truck removeObserver:self.server  
forKeyPath:@"currentSpeedOfTheTruck"]; 
} 

Driver.m

#import "DriverViewController.h" 

    @interface DriverViewController() 
    @property (strong, nonatomic) IBOutlet UITextField 
    *textFieldCurrentSpeed; 

@end 


-(void) observeValueForKeyPath:(NSString *)keyPath 
        ofObject:(id)object 
        change:(NSDictionary<NSKeyValueChangeKey,id> 
*)change 
        context:(void *)context { 

if ([keyPath isEqualToString:@"currentSpeedOfTheTruck"]) { 
    NSLog(@"DriverViewController->currentSpeedOfTheTruck: %@", 
      [object valueForKey:keyPath]); 

    NSLog(@"DriverViewController->currentSpeedOfTheTruck: %@", 
      [change objectForKey:NSKeyValueChangeNewKey]); 

    self.receivedCurrentSpeed = [change 
objectForKey:NSKeyValueChangeNewKey]; 
    [self.textFieldCurrentSpeed setText:self.receivedCurrentSpeed]; 

} 
} 



    - (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 

    NSLog(@"DriverViewController->viewDidLoad"); 

    [self.textFieldCurrentSpeed setText:self.receivedCurrentSpeed]; 
    } 

    - (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

日志输出通过低速载货的值从卡车类驱动程序类

2017-08-13 19:53:55.293 KVC-1[91529:2346883] DriverViewController- 
>currentSpeedOfTheTruck: 45 

2017-08-13 19:53:55.294 KVC-1[91529:2346883] DriverViewController- 
>currentSpeedOfTheTruck: 45 
2017-08-13 19:53:55.294 KVC-1[91529:2346883] prepareForSegue: 45 
+0

日志的输出是什么? –

+0

@AminNegm-Awad请看日志输出张贴 – user2121

回答

1

在两个错误:

  1. truck添加观察者driver,但然后立即删除它,所以在driver你不能收到currentSpeedOfTheTruck通知价值变动。当您不需要观察员值更改时将其删除,但必须在driver dealloc之前删除。
  2. 当您收到currentSpeedOfTheTruck的通知时,您只设置了receivedCurrentSpeed的值,而不是self.textFieldCurrentSpeed.text,因此self.textFieldCurrentSpeedtext为空。 移动[self.textFieldCurrentSpeed setText:receivedCurrentSpeed]到FUNC observeValueForKeyPath:或覆盖receivedCurrentSpeedsetter

Truck.m

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {  
    if ([segue.identifier isEqualToString:@"segueToServer"]) { 
     if ([segue.destinationViewController isKindOfClass:[DriverViewController class]]) { 
      ((DriverViewController *)segue.destinationViewController).sourceViewController = self; 

      [self addObserver:segue.destinationViewController forKeyPath:@"currentSpeedOfTheTruck" options:NSKeyValueObservingOptionNew context:nil]; 
     } 
    } 
} 

驱动。^ h

@property (nonatomic, weak) TrunkViewController *sourceViewController; 

Driver.m

- (void)dealloc { 
    [self.sourceViewController removeObserver:self forKeyPath:@"currentSpeedOfTheTruck"]; 
} 

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { 
    if ([keyPath isEqualToString:@"currentSpeedOfTheTruck"]) { 
     id newValue = [change objectForKey:NSKeyValueChangeNewKey]; 
     if ([newValue isKindOfClass:NSString.class]) { 
      self.receivedCurrentSpeed = newValue 
      [self.textFieldCurrentSpeed setText:self.receivedCurrentSpeed]; 
     } 
    } else { 
     [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; 
    } 
} 
+0

我放置了[self.textFieldCurrentSpeed setText:self.receivedCurrentSpeed];里面observevalueforkey但没有任何改变。我也尝试删除观察者一些地方,但我不能,因为我必须在全局声明TrcuckViewController类的实例,我不知道该怎么做。请你帮我 – user2121

+0

@ user2121对不起我没有注意到你的评论,我已经更新了答案,希望对你有所帮助。 –

4

问题是与代码

self.truck = [[TruckViewController alloc] init]; 
self.driver = [[DriverViewController alloc] init]; 
self.server = [[ServerViewController alloc] init]; 

这些线路由于您创建另一个对象,而不是一个被用于SEGUE准备之前,您应该创建使用segue.destinationController转移值

将上面的代码行更改为

self.truck = (TruckViewController *) segue.destinationViewController; 

相应于所有视图控制器。

+0

但我想通过使用KVO作为状态din的值。问题 – user2121

+1

KVO是观察者模式,您没有使用KVO传递值,您正在使用它接收值更改。理解这很重要。答案是正确的。你已经创建了一个TruckViewController的新实例,但它不会显示在UI上,这就是为什么你的textField是空的。在这个答案中尝试解决方案。 –