1

2つのビューがあります。最初のビューはclass1.mで、2番目のビューはclass2.mです。2番目のビューは、最初のビューのツールバーでボタンが押されたときにポップオーバーとして初期化されます。2番目のビューに配列があり、行のいずれかが押された場合にオブジェクトが追加されます。最初のビューでKVOを設定して、最初のビューの2番目のビューから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]);
}
}
4

2 に答える 2

4

これは、 NSArray オブジェクトが監視できないという事実の機能か、またはKVC コンプライアンスのより広範な違反のいずれかであると思われます。とにかく、 NSArray オブジェクトの手動変更通知を実装するだけで問題ありません。NSArray オブジェクトへの変更 (オブジェクトの追加) をテストしたところ、自動通知は行われませんでしたが、手動通知を追加すると正常に機能しました。(ただし、不思議なことに、NSKeyValueObservingOptionOld は期待どおりに機能せず、古い値ではなく新しい値を表示します。) 参考までに、手動通知を使用してオブジェクト NSMutableArray に何かを追加する update メソッドの例を次に示します。

- (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];
}

こうすれば、手動で通知する必要がなく、古い値と新しい値の両方を取得できますが、メモリの使用効率が悪いようにも見えるため、賛否両論があります。

于 2012-04-22T03:11:00.090 に答える
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]);
    }
}

このコードの変更があなたのアプリケーションに役立つかどうかはわかりません。対多関係とプロパティに関するこの投稿を読んでいない場合は、Key-Value Coding と Key-Value Observing Guides を読むことをお勧めします。

何か間違っている場合は、コメントを残してください。

幸運を。

于 2012-04-22T06:31:04.057 に答える