KVO 方法 observeValueForKeyPath 通知我有关更改,但我不能在 viewDidLoad 中使用它
KVO Method observeValueForKeyPath notifys me about the change, but I can't use it in viewDidLoad
这两天我都在工作,我不知道我做错了什么。
首先,我不知道 KVO 是否是将点击行信息的值从一个视图控制器传递到另一个视图控制器的最佳方式。
我有主视图,只有 2 个按钮。单击其中一个按钮,我打开 MasterTableViewController,其中我有 NSTableView,其中包含来自核心数据的一些记录(仅一列)。
单击 NSTableView 后,我将打开 DetailViewController,其中只有一个标签。
我正在尝试使用 NSTableView 中单击的行的值来更改标签值。
虽然我可以在 DetailViewController 中打印点击行的值,但我无法更改标签值。我假设通知是在调用 viewDidLoad 之前发出的。
我有以下代码:
在我的 MasterTableViewController.h 文件中:
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
@interface MasterTableViewController : NSViewController
@property (nonatomic,strong) NSManagedObjectContext *mObjContext;
@property (weak) IBOutlet NSTableView *websitesTableView;
- (IBAction)tableViewDoubleClick:(id)sender;
@property (nonatomic,strong) NSString *cellValue;
@end
在我的 MasterTableViewController.m 文件中:
#import "MasterTableViewController.h"
#import "DetailViewController.h"
@interface MasterTableViewController ()
@end
@implementation MasterTableViewController
-(void)awakeFromNib {
[_websitesTableView setTarget:self];
[_websitesTableView setDoubleAction:@selector(tableViewDoubleClick:)];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Get the object managed context
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
self.mObjContext = appDelegate.managedObjectContext;
}
- (IBAction)tableViewDoubleClick:(id)sender {
NSInteger rowNumber = [_websitesTableView clickedRow];
NSTableColumn *column = [_websitesTableView tableColumnWithIdentifier:@"websiteUrl"];
NSCell *cell = [column dataCellForRow:rowNumber];
_cellValue = [cell stringValue];
MasterTableViewController *mtvc = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
DetailViewController *dvc = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
[mtvc addObserver:dvc
forKeyPath:@"cellValue"
options:NSKeyValueObservingOptionNew
context:NULL];
[mtvc setCellValue:_cellValue];
[mtvc removeObserver:dvc forKeyPath:@"cellValue"];
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
[appDelegate changeViewController:2];
}
@end
DetailViewController.h 的代码是:
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
@interface DetailViewController : NSViewController
@property (nonatomic, weak) AppDelegate *appDelegate;
@property (weak) IBOutlet NSTextField *detailLabel;
@property (nonatomic,strong) NSString *transferedLabelValue;
@property (nonatomic,strong) NSString *cellValue;
@end
DetailViewController.m 的代码是:
#import "DetailViewController.h"
#import "MasterTableViewController.h"
@interface DetailViewController ()
@end
@implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
// if I uncomment this line, program crashes, because the value of the _transferedLabelValue is null here.
//[_detailLabel setStringValue:_transferedLabelValue];
}
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqualToString:@"cellValue"]) {
_transferedLabelValue = [change objectForKey:NSKeyValueChangeNewKey];
// Here I get the value of the clicked cell, it is printed in the console. However if I try to change the label value here, doesn't work, since seems that label does not exist yet at this point....
NSLog(@"Value in the observerValueForKeyPath is:%@",_transferedLabelValue);
}
}
@end
来自 AppDelegate.h 的代码:
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (weak) IBOutlet NSView *mainAppView;
@property (nonatomic,strong) NSViewController *mainAppViewController;
- (IBAction)showMasterViewButtonHasBeenClicked:(id)sender;
- (IBAction)showDetailViewButtonHasBeenClicked:(id)sender;
- (void)changeViewController:(NSInteger)tag;
@end
此处仅引用AppDelegatge.m中的相关代码,样板代码省略
#import "AppDelegate.h"
#import "MasterTableViewController.h"
#import "DetailViewController.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
- (IBAction)saveAction:(id)sender;
@end
@implementation AppDelegate
- (IBAction)showMasterViewButtonHasBeenClicked:(id)sender {
NSInteger tag = [sender tag];
[self changeViewController:tag];
}
- (IBAction)showDetailViewButtonHasBeenClicked:(id)sender {
NSInteger tag = [sender tag];
[self changeViewController:tag];
}
- (void)changeViewController:(NSInteger)tag {
[[_mainAppViewController view]removeFromSuperview];
switch (tag) {
case 1:
self.mainAppViewController = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
[_mainAppView addSubview:[_mainAppViewController view]];
[[_mainAppViewController view] setFrame:[_mainAppView bounds]];
[[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
break;
case 2:
self.mainAppViewController = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
[_mainAppView addSubview:[_mainAppViewController view]];
[[_mainAppViewController view] setFrame:[_mainAppView bounds]];
[[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
break;
}
}
同样,如果 KVO 和通知不是最好的方式,请让我知道我应该如何 "inform" 另一个视图哪一行被点击,哪个是他的值。
此致,约翰
我设法用 KVO 解决了我的问题...我的问题是我在 MasterTableViewController 中创建了视图控制器的新实例...我所做的是在 appDelegatge.h 像这样:
@property MasterTableViewController *mtvc;
@property DetailViewController *dvc;
然后在 appDelegate.m 中:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
_mtvc = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
_dvc = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
}
代码中的其余更改只是将 MasterTableViewController 和 DetailViewController 替换为 _mtvc 和 _dvc...
但是...有人警告我说此解决方案容易出错,并且该警告是正确的。有时我会得到错误的值,而不是点击的值。一旦点击 4-5 次,我就会得到错误的值。让我感到困惑的是,我使该功能可以在双击时使用,但它也可以在单击时使用...但我猜这些是针对其他问题的。
这两天我都在工作,我不知道我做错了什么。
首先,我不知道 KVO 是否是将点击行信息的值从一个视图控制器传递到另一个视图控制器的最佳方式。
我有主视图,只有 2 个按钮。单击其中一个按钮,我打开 MasterTableViewController,其中我有 NSTableView,其中包含来自核心数据的一些记录(仅一列)。
单击 NSTableView 后,我将打开 DetailViewController,其中只有一个标签。
我正在尝试使用 NSTableView 中单击的行的值来更改标签值。
虽然我可以在 DetailViewController 中打印点击行的值,但我无法更改标签值。我假设通知是在调用 viewDidLoad 之前发出的。
我有以下代码:
在我的 MasterTableViewController.h 文件中:
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
@interface MasterTableViewController : NSViewController
@property (nonatomic,strong) NSManagedObjectContext *mObjContext;
@property (weak) IBOutlet NSTableView *websitesTableView;
- (IBAction)tableViewDoubleClick:(id)sender;
@property (nonatomic,strong) NSString *cellValue;
@end
在我的 MasterTableViewController.m 文件中:
#import "MasterTableViewController.h"
#import "DetailViewController.h"
@interface MasterTableViewController ()
@end
@implementation MasterTableViewController
-(void)awakeFromNib {
[_websitesTableView setTarget:self];
[_websitesTableView setDoubleAction:@selector(tableViewDoubleClick:)];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Get the object managed context
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
self.mObjContext = appDelegate.managedObjectContext;
}
- (IBAction)tableViewDoubleClick:(id)sender {
NSInteger rowNumber = [_websitesTableView clickedRow];
NSTableColumn *column = [_websitesTableView tableColumnWithIdentifier:@"websiteUrl"];
NSCell *cell = [column dataCellForRow:rowNumber];
_cellValue = [cell stringValue];
MasterTableViewController *mtvc = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
DetailViewController *dvc = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
[mtvc addObserver:dvc
forKeyPath:@"cellValue"
options:NSKeyValueObservingOptionNew
context:NULL];
[mtvc setCellValue:_cellValue];
[mtvc removeObserver:dvc forKeyPath:@"cellValue"];
AppDelegate *appDelegate = (AppDelegate*)[[NSApplication sharedApplication] delegate];
[appDelegate changeViewController:2];
}
@end
DetailViewController.h 的代码是:
#import <Cocoa/Cocoa.h>
#import "AppDelegate.h"
@interface DetailViewController : NSViewController
@property (nonatomic, weak) AppDelegate *appDelegate;
@property (weak) IBOutlet NSTextField *detailLabel;
@property (nonatomic,strong) NSString *transferedLabelValue;
@property (nonatomic,strong) NSString *cellValue;
@end
DetailViewController.m 的代码是:
#import "DetailViewController.h"
#import "MasterTableViewController.h"
@interface DetailViewController ()
@end
@implementation DetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
// if I uncomment this line, program crashes, because the value of the _transferedLabelValue is null here.
//[_detailLabel setStringValue:_transferedLabelValue];
}
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void *)context {
if ([keyPath isEqualToString:@"cellValue"]) {
_transferedLabelValue = [change objectForKey:NSKeyValueChangeNewKey];
// Here I get the value of the clicked cell, it is printed in the console. However if I try to change the label value here, doesn't work, since seems that label does not exist yet at this point....
NSLog(@"Value in the observerValueForKeyPath is:%@",_transferedLabelValue);
}
}
@end
来自 AppDelegate.h 的代码:
#import <Cocoa/Cocoa.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (weak) IBOutlet NSView *mainAppView;
@property (nonatomic,strong) NSViewController *mainAppViewController;
- (IBAction)showMasterViewButtonHasBeenClicked:(id)sender;
- (IBAction)showDetailViewButtonHasBeenClicked:(id)sender;
- (void)changeViewController:(NSInteger)tag;
@end
此处仅引用AppDelegatge.m中的相关代码,样板代码省略
#import "AppDelegate.h"
#import "MasterTableViewController.h"
#import "DetailViewController.h"
@interface AppDelegate ()
@property (weak) IBOutlet NSWindow *window;
- (IBAction)saveAction:(id)sender;
@end
@implementation AppDelegate
- (IBAction)showMasterViewButtonHasBeenClicked:(id)sender {
NSInteger tag = [sender tag];
[self changeViewController:tag];
}
- (IBAction)showDetailViewButtonHasBeenClicked:(id)sender {
NSInteger tag = [sender tag];
[self changeViewController:tag];
}
- (void)changeViewController:(NSInteger)tag {
[[_mainAppViewController view]removeFromSuperview];
switch (tag) {
case 1:
self.mainAppViewController = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
[_mainAppView addSubview:[_mainAppViewController view]];
[[_mainAppViewController view] setFrame:[_mainAppView bounds]];
[[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
break;
case 2:
self.mainAppViewController = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
[_mainAppView addSubview:[_mainAppViewController view]];
[[_mainAppViewController view] setFrame:[_mainAppView bounds]];
[[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
break;
}
}
同样,如果 KVO 和通知不是最好的方式,请让我知道我应该如何 "inform" 另一个视图哪一行被点击,哪个是他的值。
此致,约翰
我设法用 KVO 解决了我的问题...我的问题是我在 MasterTableViewController 中创建了视图控制器的新实例...我所做的是在 appDelegatge.h 像这样:
@property MasterTableViewController *mtvc;
@property DetailViewController *dvc;
然后在 appDelegate.m 中:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
_mtvc = [[MasterTableViewController alloc]initWithNibName:@"MasterTableViewController" bundle:nil];
_dvc = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];
}
代码中的其余更改只是将 MasterTableViewController 和 DetailViewController 替换为 _mtvc 和 _dvc...
但是...有人警告我说此解决方案容易出错,并且该警告是正确的。有时我会得到错误的值,而不是点击的值。一旦点击 4-5 次,我就会得到错误的值。让我感到困惑的是,我使该功能可以在双击时使用,但它也可以在单击时使用...但我猜这些是针对其他问题的。