每個Home都有一個HomeKit數據庫。如下圖所示,HomeKit數據庫會安全地和home授權的用戶的iOS設備以及潛在的客人的iOS設備進行同步。為了給用戶展示當前最新的數據,你的應用需要觀察HomeKit數據庫的變化。

**HomeKit代理方法**
HomKit使用代理設計模式([delegation design pattern](https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Delegation.html#//apple_ref/doc/uid/TP40008195-CH14-SW2))來通知應用程序HomeKit對象的改變。一般來講,如果你的應用程序調用了一個帶有完成處理參數的HomeKit方法,并且這個方法被成功調用了,那么相關聯的代理消息就會被發送給其他HomeKit應用,無論這些應用是安裝在同一臺iOS設備上還是遠程iOS設備上。這些應用甚至可以運行在客人的iOS設備上。如果你的應用發起了數據改變,但是代理消息并沒有發送到你的應用,那么添加代碼到完成處理方法和相關聯的代理方法中來刷新數據和更新視圖就成為必須了。如果home布局發生了顯著變化,那么就重新加載關于這個home的所有信息。在完成程序處理的情況下,請在更新應用之前檢查那個方法是否成功。Homkit也會調用代理方法來通知你的應用程序home網絡狀態的改變。
例如,下圖演示了使用代理方法的過程:響應用戶的操作,你的應用程序調用了[addRoomWithName:completionHandler:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/addRoomWithName:completionHandler:)方法,并且沒有錯誤發生,完成處理程序應當更新home的所有視圖。如果成功了,homeKit將會發送[home:didAddRoom:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didAddRoom:)消息給其他應用中homes的代理。因此,你實現的這個[home:didAddRoom:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didAddRoom:)方法也應該更新home的所有視圖。

應用程序只有在前臺運行的時候才能接受代理消息。當你的應用在后臺時,HomeKit數據庫的改變并不會成批處理。也就是說,如果你的應用在后臺,當其他的應用成功地添加一個room到home中的時候,你的應用程序并不會接收到[home:didAddRoom:?](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didAddRoom:)消息。當你的應用程序到前臺運行時,你的應用程序將會接收到[homeManagerDidUpdateHomes:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManagerDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeManagerDelegate/homeManagerDidUpdateHomes:)消息,這個消息是表示你的應用程序要重新加載所有的數據。
**觀察Homes集合的改變**
設置home manager的代理并且實現[HMHomeManagerDelegate](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManagerDelegate_Protocol/index.html#//apple_ref/occ/intf/HMHomeManagerDelegate)協議,當primary home或者home集合發生改變時,可以接收代理消息。
所有的應用都需要實現[homeManagerDidUpdateHomes:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManagerDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeManagerDelegate/homeManagerDidUpdateHomes:)方法,這個方法在完成最初獲取homes之后被調用。對新建的home manager來說,在這個方法被調用之前,[primaryHome](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManager_Class/index.html#//apple_ref/occ/instp/HMHomeManager/primaryHome)屬性的值是nil,[homes](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManager_Class/index.html#//apple_ref/occ/instp/HMHomeManager/homes)數組是空的數組。當應用程序開始在前臺運行時也會調用?[homeManagerDidUpdateHomes:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManagerDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeManagerDelegate/homeManagerDidUpdateHomes:)?方法,當其在后臺運行時數據發生改變。該[homeManagerDidUpdateHomes:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManagerDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeManagerDelegate/homeManagerDidUpdateHomes:)方法會重新加載與homes相關聯的所有數據。
**觀察homes的變化**
1.在你的類接口中添加HMHomeManagerDelegate代理和homeManager屬性。代碼如下:
~~~
@interface AppDelegate () @property (strong, nonatomic) HMHomeManager *homeManager;
@end
~~~
2.創建home manager對象并設置其代理
~~~
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.homeManager = [[HMHomeManager alloc] init];
self.homeManager.delegate = self;
return YES;
}
~~~
3\. 實現homes發生改變時調用的代理方法。例如:如果多個視圖控制器展示了homes相關信息,你可以發布一個更改通知去更新所有視圖。
~~~
- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager {
// Send a notification to the other objects
[[NSNotificationCenter defaultCenter]
postNotificationName:@"UpdateHomesNotification"
object:self];
}
- (void)homeManagerDidUpdatePrimaryHome:(HMHomeManager
*)manager {
// Send a notification to the other objects
[[NSNotificationCenter defaultCenter]
postNotificationName:@"UpdatePrimaryHomeNotification"
object:self];
}
~~~
視圖控制器注冊更改通知并且執行適當的操作。
~~~
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updateHomes:)
name:@"UpdateHomesNotification"
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(updatePrimaryHome:)
name:@"UpdatePrimaryHomeNotification" object:nil];
~~~
**觀察個別home的變化**
展示home信息的視圖控制器應該成為home對象的代理,并且當home發生改變時更新視圖控制器的視圖。
觀察特定home對象的改變
1.在類接口中添加home代理協議。
~~~
@interface HomeViewController () @end
~~~
2.設置配件代理
~~~
home.delegate = self;
~~~
3.實現[HMHomeDelegate](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intf/HMHomeDelegate)協議
例如:實現[home:didAddAccessory:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didAddAccessory:)和[home:didRemoveAccessory:?](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didRemoveAccessory:)方法來更新展示配件的視圖。用[HMAccessory](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessory_Class/index.html#//apple_ref/occ/cl/HMAccessory)類的[room](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessory_Class/index.html#//apple_ref/occ/instp/HMAccessory/room)屬性可以獲得配件所屬的room。(對配件來說,默認的room是[roomForEntireHome](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/roomForEntireHome)這個方法的返回值。)
Bridge Note:當你為home添加橋接口時,橋接口底層的配件會自動被添加到home中。你的代理會接收到橋接口后每個配件的?[home:didAddAccessory:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didAddAccessory:)消息,但是你的代理不會接收到橋接口的[home:didAddAccessory:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMHomeDelegate/home:didAddAccessory:)消息。
**觀察配件的變化**
配件的狀態可以在任何時間發生變化。配件可能不能被獲得,可以被移除,或者被關閉。請更新用戶界面以反映配件狀態的更改,尤其是如果你的app允許用戶控制配件時。
這以下步驟中,我們假設你已經從HomeKit數據庫中檢索到了配件對象,正如[Getting the Accessories in a Room](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/FindingandAddingAccessories/FindingandAddingAccessories.html#//apple_ref/doc/uid/TP40015050-CH3-SW5)中描述的那樣。
觀察個別配件的變化
1. 在類接口中添加配件代理協議。
~~~
@interface AccessoryViewController ()
@end
~~~
2. 設置配件的代理
~~~
accessory.delegate = self;
~~~
3. 實現?[HMAccessoryDelegate?](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryDelegate_Protocol/index.html#//apple_ref/occ/intf/HMAccessoryDelegate)協議
比如,執行[accessoryDidUpdateReachability:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMAccessoryDelegate/accessoryDidUpdateReachability:)方法以啟用或者禁用配件控制。
~~~
- (void)accessoryDidUpdateReachability:(HMAccessory *)accessory {
if (accessory.reachable == YES) {
// Can communicate with the accessory
} else {
// The accessory is out of range, turned off, etc
}
}
~~~
如果你展示了配件的服務狀態和特性,那么請執行以下代理方法來相應地更新其視圖:
[accessoryDidUpdateServices](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMAccessoryDelegate/accessoryDidUpdateServices:):
[accessory:service:didUpdateValueForCharacteristic:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMAccessoryDelegate/accessory:service:didUpdateValueForCharacteristic:)
想了解配件的服務,請參閱[Accessing Services and Their Characteristics](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/AccessingServicesandTheirCharacteristics/AccessingServicesandTheirCharacteristics.html#//apple_ref/doc/uid/TP40015050-CH6-SW1).