第五部分:观察HomeKit数据库的变化
最后更新于:2022-04-01 02:09:55
每个Home都有一个HomeKit数据库。如下图所示,HomeKit数据库会安全地和home授权的用户的iOS设备以及潜在的客人的iOS设备进行同步。为了给用户展示当前最新的数据,你的应用需要观察HomeKit数据库的变化。
![101.png](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-08_55c5769871ad7.png "1427273342915914.png")
**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的所有视图。
![102.png](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-08_55c57699ed235.png "1427273431510346.png")
应用程序只有在前台运行的时候才能接受代理消息。当你的应用在后台时,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).