什麼是 視圖控制器B中的最正確的方式來訪問 NSMutableArray的,是由一個充滿?
我會做一些簡單的事情,只有返回到決定,如果它導致問題。簡單的東西可能是暴露在控制器A的公共接口陣列併發送通知有關陣列更新,以便B可看:
@interface A
@property(readonly) NSArray *foos;
@implementation
- (void) updateFoos {
NSString *const key = @"foos";
[self willChangeValueForKey:key];
[foos doSomething];
[self didChangeValueForKey:key];
}
@interface B
@implementation
- (void) afterSettingA {
[a addObserver:self forKeyPath:@"foos" options:0 context:NULL];
}
- (void) observeValueForKeyPath: (NSString*) keyPath ofObject: (id) object
change: (NSDictionary*) change context: (void*) context
{
NSAssert([keyPath isEqualToString:@"foos"], @"Somethind fishy going on.");
// update what depends on foos
}
另一種簡單的解決辦法是將數組變成一個完整的模型類,你會連接到A和B.(該連接將有控制器以外的地方進行,以避免過多的耦合。您可以使用Interface Builder,這將連線的對象在一起或其他任何符合一個「工廠」類)。
@interface Foo
@property(readonly) NSArray* items;
@implementation
- (void) updateItems {
// send KVO notifications just as above
}
@interface A
@property(retain) Foo *fooModel;
@interface B
@property(retain) Foo *fooModel;
@interface Factory
@implementation
- (void) wireObjects {
A *a = [[A alloc] init];
B *b = [[B alloc] init];
Foo *fooModel = [[Foo alloc] init];
[a setFooModel:fooModel];
[b setFooModel:fooModel];
// Of course the A and B would be member variables of this
// class or you would return a root of the constructed object
// graph from this method, otherwise it would not make sense.
}
在第一解決方案B控制器必須具有指向A的指針,以便它可以訂閱KVO通知。控制器之間的這種連接最好在其他地方維護,比如在代碼中。 B不應該創建一個A的實例。(這樣你會在A和B之間引入一個緊密的耦合。不是非常可測試的等等)如果你已經在Interface Builder中實例化了這些控制器,這是給B指針的理想地方A.(只需在B中爲A創建一個IBOutlet
)
第二種解決方案與單獨的模型類是「更乾淨」的MVC,不需要控制器相互瞭解 - 它們都取決於模型類。您也可以實例化模型並將其鏈接到Interface Builder中的控制器。順便說一句:如果B想要觀察A的某些屬性的變化,則必須在已經設置了A的鏈接之後訂閱。一個簡單但很輕微的錯誤方法是在B的viewDidLoad
方法中訂閱。它很方便,但如果在此之後到A的鏈接被更改,通知不會相應地改變。訂閱的更難但正確的方式是在A的設置者 - 當有人設置新的A時,您取消通知訂閱舊A並訂閱新A。
@zoul:您的解決方案非常有趣,我一直想使用KVO。只是一個簡單的問題:您的解決方案涉及@interface B包含對@interface A的引用?(我在創建應用程序時將B鏈接到A的一個指針)。如果是這樣,那麼分配這個指針的最好方法是什麼?我使用Interface Builder實例化A和B. – Goles 2010-02-15 10:08:45
我已經更新了答案。如果不夠清楚,請不要猶豫,再次提問。 – zoul 2010-02-15 10:30:33
你的答案是我在這個網頁上獲得的最好的答案之一。非常感謝你。順便說一句,有一個小的錯字,你可以在這一行修復:NSAssert([keyPath isEqualToString:@「foos」],@「Somethind fishy going on。」); //這是固定行(缺少']')。再次感謝! – Goles 2010-02-15 10:44:02