我有两个视图,我的第一个视图是class1.m,第二个视图是class2.m。当在第一个视图中的工具栏上按下按钮时,我的第二个视图被初始化为弹出窗口。我在第二个视图中有一个数组,如果按下任何行,则添加对象。我正在尝试在我的第一个视图中设置一个KVO,这样我就可以在第一个视图中从第二个视图访问allSelectedFocus数组,但它不起作用。我意识到我没有调用removeObserver,但我不知道在哪里调用它,没有它在使用之前移除观察者。如果有人知道有任何更好的方法可以做到这一点,我愿意接受建议,但是如果有人可以让它发挥作用,那真的很棒。
// class2.m
#import "class2.h"
#import "class1.h"
@implementation class2
@synthesize selectedFocus = _selectedFocus;
@synthesize focusArray = _focusArray;
@synthesize allSelectedFocus = _allSelectedFocus;
- (void)viewDidLoad
{
_focusArray = [[NSArray alloc]initWithObjects:@"Balance",@"Bevægelse",@"Elementskift",@"Vejrtrækning",@"Alle",nil];
[super viewDidLoad];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return _focusArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSString *cellValue = [_focusArray objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
_selectedFocus = [[_focusArray objectAtIndex:indexPath.row] stringByAppendingString:@","];
if(![[self mutableAllSelectedFocus] containsObject:_selectedFocus])
{
//add object to array, if it's not already there
[[self mutableAllSelectedFocus] addObject:_selectedFocus];
}
else
{
//remove object from array, if it's already there
[[self mutableAllSelectedFocus] removeObject:_selectedFocus];
}
}
-(NSMutableArray *)allSelectedFocus
{
if(_allSelectedFocus == nil)
{
_allSelectedFocus = [[NSMutableArray alloc]init];
}
return _allSelectedFocus;
}
-(NSMutableArray *)mutableAllSelectedFocus
{
return [self mutableArrayValueForKey:@"allSelectedFocus"];
}
@end
// class1.m
#import "class1.h"
#import "class2.h"
@implementation class1
- (void)viewDidLoad
{
[super viewDidLoad];
if(_focusTag == nil)
{
_focusTag = [[class2 alloc]init];
}
[_focusTag addObserver:self forKeyPath:@"selectedFocus" options:NSKeyValueObservingOptionNew context:NULL];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"allSelectedFocus"])
{
NSLog(@"%@", [object valueForKeyPath:keyPath]);
}
}
答案 0 :(得分:4)
我怀疑这是NSArray objects are not observable或更广泛违反KVC compliance这一事实的函数。无论如何,只为NSArray对象实现manual change notification,你应该没问题。我刚刚测试了对NSArray对象的更改(添加对象)并且没有发生自动通知,但是当我添加手动通知时,它工作正常。 (但奇怪的是,NSKeyValueObservingOptionOld没有按预期工作,显示新值而不是旧值。)仅供参考,这是一个更新方法的示例,它使用手动通知向我的对象NSMutableArray添加内容:
- (void)addToMyArray:(id)obj
{
[self willChangeValueForKey:@"myArray"];
[_myArray addObject:obj];
[self didChangeValueForKey:@"myArray"];
}
<强>更新强>
顺便说一下,如果你需要NSKeyValueObservingOptionOld,你可以这样做:
- (void)addToMyArray:(id)obj
{
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:_myArray];
[tempArray addObject:obj];
[self setMyArray:tempArray];
}
这样,你不需要手动通知,你可以检索旧值和新值,但它似乎也是对内存的低效使用,所以有利有弊。
答案 1 :(得分:1)
只是提醒一下,在任何时候你都没有使用访问器方法来设置/获取你的属性。这意味着KVO将无法运作。我相信KVO依赖于通过访问器获取/设置属性。
我不确定您要使用该应用程序完成的任务,但我将一些可能有用的代码放在一起。我在代码中进行了评论,所以我不会在这个答案中解释它。
我会像你一样从class2开始:
#import <UIKit/UIKit.h>
@interface Class2ViewController : UITableViewController
@property (nonatomic, strong) NSArray *focusArray;
@property (nonatomic, strong) NSMutableArray *allSelectedFocus;
// This is a readonly property that will return a mutable array of the allSelectedFocus property
// This gives you the ability to have automatic KVO if you add/remove using this property
// You won't have to wrap your calls to will/didChangeValueForKey:
@property (nonatomic, readonly, strong) NSMutableArray *mutableAllSelectedFocus;
@end
#import "Class2ViewController.h"
#import "Class1ViewController.h"
@implementation Class2ViewController
@synthesize focusArray = _focusArray;
@synthesize allSelectedFocus = _allSelectedFocus;
- (void)viewDidLoad
{
[super viewDidLoad];
// This is what you have
// FYI you are accessing the iVar directly, not sure if that matters in your app or not
_focusArray = [[NSArray alloc] initWithObjects:@"Balance",@"Bevægelse",@"Elementskift",@"Vejrtrækning",@"Alle",nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Grab the string of interest from the _focusArray --> this is direct access again which I imagine is fine
NSString *selectedFocus = [[_focusArray objectAtIndex:indexPath.row] stringByAppendingString:@","];
// Use the new mutableAllSelectedFocus property to check if the array doesn't contain the string of interest
if (![[self mutableAllSelectedFocus] containsObject:selectedFocus]) {
// If it doesn't contain it, add it using the mutableAllSelectedFocus property
[[self mutableAllSelectedFocus] addObject:selectedFocus];
}
}
// This is getter that lazily instantiates your _allSelectedFocus array
- (NSMutableArray *)allSelectedFocus
{
// Check to see if the backing iVar is nil
if (_allSelectedFocus == nil) {
// If it is, create an empty mutable array
_allSelectedFocus = [[NSMutableArray alloc] init];
}
// return the array
return _allSelectedFocus;
}
// This is our new property
- (NSMutableArray *)mutableAllSelectedFocus
{
// mutableArrayValueForKey: returns a mutable array for the given key (property)
// Allows us better KVO and efficiency with changing properties
return [self mutableArrayValueForKey:@"allSelectedFocus"];
}
现在上课1:
#import "Class1ViewController.h"
#import "Class2ViewController.h"
@implementation Class1ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// If you are using ARC, this instance will be deallocated after -viewDidLoad
// You will want to store this in an instance variable if you need to keep it around
Class2ViewController *class2ViewController = [[Class2ViewController alloc] init];
[class2ViewController addObserver:self
forKeyPath:@"allSelectedFocus"
options:NSKeyValueObservingOptionNew
context:NULL];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([keyPath isEqualToString:@"allSelectedFocus"]) {
NSLog(@"%@", [object valueForKeyPath:keyPath]);
}
}
我不确定代码中的这一更改是否会对您的应用程序有所帮助。我会做的两件事是,如果你还没有阅读键值编码和键值观察指南,请阅读这个post关于多对关系和属性。
如果我出错了,请发表评论。
祝你好运。