每个 Home 都有一个 HomeKit 数据库。如下图所示,HomeKit 数据库会安全地和 home 授权的用户的 iOS 设备以及潜在的客人的 iOS 设备进行同步。为了给用户展示当前最新的数据,你的应用需要观察 HomeKit 数据库的变化。
HomKit 使用代理设计模式(delegation design pattern)来通知应用程序 HomeKit 对象的改变。一般来讲,如果你的应用程序调用了一个带有完成处理参数的 HomeKit 方法,并且这个方法被成功调用了,那么相关联的代理消息就会被发送给其他 HomeKit 应用,无论这些应用是安装在同一台 iOS 设备上还是远程 iOS 设备上。这些应用甚至可以运行在客人的 iOS 设备上。如果你的应用发起了数据改变,但是代理消息并没有发送到你的应用,那么添加代码到完成处理方法和相关联的代理方法中来刷新数据和更新视图就成为必须了。如果 home 布局发生了显著变化,那么就重新加载关于这个 home 的所有信息。在完成程序处理的情况下,请在更新应用之前检查那个方法是否成功。Homkit 也会调用代理方法来通知你的应用程序 home 网络状态的改变。
例如,下图演示了使用代理方法的过程:响应用户的操作,你的应用程序调用了 addRoomWithName:completionHandler:方法,并且没有错误发生,完成处理程序应当更新 home 的所有视图。如果成功了,homeKit 将会发送 home:didAddRoom:消息给其他应用中 homes 的代理。因此,你实现的这个 home:didAddRoom:方法也应该更新 home 的所有视图。
应用程序只有在前台运行的时候才能接受代理消息。当你的应用在后台时,HomeKit 数据库的改变并不会成批处理。也就是说,如果你的应用在后台,当其他的应用成功地添加一个 room 到 home 中的时候,你的应用程序并不会接收到 home:didAddRoom: 消息。当你的应用程序到前台运行时,你的应用程序将会接收到 homeManagerDidUpdateHomes:消息,这个消息是表示你的应用程序要重新加载所有的数据。
设置 home manager 的代理并且实现HMHomeManagerDelegate协议,当 primary home 或者 home 集合发生改变时,可以接收代理消息。
所有的应用都需要实现 homeManagerDidUpdateHomes:方法,这个方法在完成最初获取 homes 之后被调用。对新建的 home manager 来说,在这个方法被调用之前,primaryHome 属性的值是 nil,homes 数组是空的数组。当应用程序开始在前台运行时也会调用 homeManagerDidUpdateHomes: 方法,当其在后台运行时数据发生改变。该 homeManagerDidUpdateHomes:方法会重新加载与 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 对象的改变
1.在类接口中添加 home 代理协议。
@interface HomeViewController () @end
2.设置配件代理
home.delegate = self;
3.实现HMHomeDelegate协议
例如:实现 home:didAddAccessory:和 home:didRemoveAccessory: 方法来更新展示配件的视图。用 HMAccessory 类的 room 属性可以获得配件所属的 room。(对配件来说,默认的 room 是 roomForEntireHome 这个方法的返回值。)
Bridge Note:当你为 home 添加桥接口时,桥接口底层的配件会自动被添加到 home 中。你的代理会接收到桥接口后每个配件的 home:didAddAccessory:消息,但是你的代理不会接收到桥接口的 home:didAddAccessory:消息。
配件的状态可以在任何时间发生变化。配件可能不能被获得,可以被移除,或者被关闭。请更新用户界面以反映配件状态的更改,尤其是如果你的 App 允许用户控制配件时。
这以下步骤中,我们假设你已经从 HomeKit 数据库中检索到了配件对象,正如 Getting the Accessories in a Room中描述的那样。
在类接口中添加配件代理协议。
@interface AccessoryViewController ()
@end
设置配件的代理
accessory.delegate = self;
比如,执行 accessoryDidUpdateReachability:方法以启用或者禁用配件控制。
- (void)accessoryDidUpdateReachability:(HMAccessory *)accessory {
if (accessory.reachable == YES) {
// Can communicate with the accessory
} else {
// The accessory is out of range, turned off, etc
}
}
如果你展示了配件的服务状态和特性,那么请执行以下代理方法来相应地更新其视图:
accessory:service:didUpdateValueForCharacteristic:
想了解配件的服务,请参阅Accessing Services and Their Characteristics.