第四部分:创建Homes和添加Accessories

最后更新于:2022-04-01 02:09:53

HomeKit对象被保存在一个可以共享的HomeKit数据库里,它可以通过HomeKit框架被多个应英程序访问。所有HomeKit调用的方法都是异步写入的,并且这些方法都包含一个完成处理后的参数。如果这个方法处理成功了,你的应用将会在完成处理函数里更新本地对象。应用程序启动时,HomeKit对象发生改变的并不能收到代理回调?法,只能接受处理完成后的回调函数。 想要观察其他应用程序启动时HomeKit对象的变化,请参阅:[Observing HomeKit Database Changes](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/RespondingtoHomeKitDatabaseChanges/RespondingtoHomeKitDatabaseChanges.html#//apple_ref/doc/uid/TP40015050-CH5-SW2)。查阅异步消息完成处理后传过来的错误码的信息,请参阅:[HomeKit Constants Reference](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HomeKit_Constants/index.html#//apple_ref/doc/uid/TP40014524). **对象命名规则** HomeKit对象的名字,例如home、room和zone对象都可以被Siri识别,这一点已经在文档中指出。以下几点是HomeKit对象的命名规则: * 对象名字在其命名空间内必须是唯一的。 * 属于用户所有的home名字都在一个命名空间内。 * 一个home对象及其所包含的对象在另一个命名空间内。 * 名字只能包含数字、字母、空格以及省略号字符。 * 名字必须以数字或者字母字符开始。 * 在名字比较的时候,空格或者省略号是忽略的(例如home1和home 1 同一个名字)。 * 名字没有大小写之分。 想了用户可以使用哪些语言与Siri进行交互,请参阅[HomeKit User Interface Guidelines](https://developer.apple.com/homekit/ui-guidelines/)文档中的"Siri Integration" **创建Homes** 在[HMHomeManager](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManager_Class/index.html#//apple_ref/occ/cl/HMHomeManager)类中使用[addHomeWithName:completionHandler: ](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHomeManager_Class/index.html#//apple_ref/occ/instm/HMHomeManager/addHomeWithName:completionHandler:)异步方法可以添加一个home。作为参数传到那个方法中的home的名字,必须是唯一独特的,并且是Siri可以识别的home名字。 ~~~ [self.homeManager addHomeWithName:@"My Home" completionHandler:^(HMHome *home, NSError *error) { if (error != nil) { // Failed to add a home } else { // Successfully added a home } }]; ~~~ 在else语句中,写入代码以更新你应的程序的视图。为了获取home manager对象,请参阅[Getting the Home Manager Object](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/FindingandAddingAccessories/FindingandAddingAccessories.html#//apple_ref/doc/uid/TP40015050-CH3-SW2). **在Home中增加一个Room** 使用[addRoomWithName:completionHandler: ](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/addRoomWithName:completionHandler:)异步方法可以在一个home中添加一个room对象。作为参数传到那个方法中的room的名字,必须是唯一独特的,并且是Siri可识别的room名字。 ~~~ NSString *roomName = @"Living Room"; [home addRoomWithName:roomName completionHandler:^(HMRoom *room, NSError *error) { if (error != nil) { // Failed to add a room to a home } else { // Successfully added a room to a home } }]; ~~~ 在else语句中,写入代码更新应用程序的视图。 **发现配件** Accessories封装了物理配件的状态,因此它不能被用户创建。想要允许用户给家添加新的配件,我们可以使[HMAccessoryBrowser对象](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowser_Class/index.html#//apple_ref/occ/cl/HMAccessoryBrowser)找到一个与home没有关联的配件。[HMAccessoryBrower](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowser_Class/index.html#//apple_ref/occ/cl/HMAccessoryBrowser)对象在后台搜寻配件,当它找到配件的时候,使用委托来通知你的应用程序。只有在[startSearchingForNewAccessories](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowser_Class/index.html#//apple_ref/occ/instm/HMAccessoryBrowser/startSearchingForNewAccessories)方法调用之后或者[stopSearchingForNewAccessories](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowser_Class/index.html#//apple_ref/occ/instm/HMAccessoryBrowser/stopSearchingForNewAccessories)方法调用之前,[HMAccessoryBrowserDelegate](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowserDelegate_Protocol/index.html#//apple_ref/occ/intf/HMAccessoryBrowserDelegate)消息才被发送给代理对象。 **发现home中的配件** 1\. 在你的类接口中添加配件浏览器委托协议,并且添加一个配件浏览器属性。代码如下: ~~~ @interface EditHomeViewController () @property HMAccessoryBrowser *accessoryBrowser; @end ~~~ 用你自己的类名代替EditHomeViewController 2\. 创建配件浏览器对象,并设置它的代理 ~~~ self.accessoryBrowser = [[HMAccessoryBrowser alloc] init]; self.accessoryBrowser.delegate = self; ~~~ 3\. 开始搜寻配件 ~~~ [self.accessoryBrowser startSearchingForNewAccessories]; ~~~ 4\. 将找到的配件添加到你的收藏里 ~~~ - (void)accessoryBrowser:(HMAccessoryBrowser *)browser didFindNewAccessory:(HMAccessory *)accessory { // Update the UI per the new accessory; for example, reload a picker view. [self.accessoryPicker reloadAllComponents]; } ~~~ 用你自己的代码实现上面的[accessoryBrowser:didFindNewAccessory:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowserDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMAccessoryBrowserDelegate/accessoryBrowser:didFindNewAccessory:)方法。 当然也可以实现[accessoryBrowser:didRemoveNewAccessory:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessoryBrowserDelegate_Protocol/index.html#//apple_ref/occ/intfm/HMAccessoryBrowserDelegate/accessoryBrowser:didRemoveNewAccessory:) 这个方法来移除配件,这个配件对你的视图或者收藏来说不再是新的。 5\. 停止搜寻配件 如果一个视图控制器正在开始搜寻配件,那么可以通过重写[viewWillDisappear:](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIViewController_Class/index.html#//apple_ref/occ/instm/UIViewController/viewWillDisappear:)方法来停止搜寻配件。代码如下: ~~~ - (void)viewWillDisappear:(BOOL)animated { [self.accessoryBrowser stopSearchingForNewAccessories]; } ~~~ 注意: 在WiFi网络环境下,为了安全地获取新的并且能够被HomeKit发现的无线配件,请参阅[External Accessory Framework Reference](https://developer.apple.com/library/ios/documentation/ExternalAccessory/Reference/ExternalAccessoryFrameworkReference/index.html#//apple_ref/doc/uid/TP40008235). **为Home和room添加配件(Accessory)** 配件归属于home,并且它可以被随意添加到home中的任意一个room中。使用[addAccessory:completionHandler:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/addAccessory:completionHandler:)这个异步方法可以在home中添加配件。这个配件的名字作为一个参数传递到上述异步方法中,并且这个名字在配件所属的home中必须是唯一的。使用[assignAccessory:toRoom:completionHandler:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/assignAccessory:toRoom:completionHandler:) 这个异步方法可以给home中 的room添加配件。配件默认的room是[roomForEntireHome](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/roomForEntireHome)这个方法返回值room。下面的代码演示了如何给home和room添加配件: ~~~ // Add an accesory to a home and a room // 1. Get the home and room objects for the completion handlers. __block HMHome *home = self.home; __block HMRoom *room = roomInHome; // 2. Add the accessory to the home [home addAccessory:accessory completionHandler:^(NSError *error) { if (error) { // Failed to add accessory to home } else { if (accessory.room != room) { // 3. If successfully, add the accessory to the room [home assignAccessory:accessory toRoom:room completionHandler:^(NSError *error) { if (error) { // Failed to add accessory to room } }]; } } }]; ~~~ 配件可提供一项或者多项服务,这些服务的特性是由制造商定义。想了解配件的服务和特性目的,请参阅 [Accessing Services and Characteristics](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/AccessingServicesandTheirCharacteristics/AccessingServicesandTheirCharacteristics.html#//apple_ref/doc/uid/TP40015050-CH6-SW1). **更改配件名称** 使用[updateName:completionHandler:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMAccessory_Class/index.html#//apple_ref/occ/instm/HMAccessory/updateName:completionHandler:) 异步方法可以改变配件的名称,代码如下: ~~~ [accessory updateName:@"Kid's Night Light" completionHandler:^(NSError *error) { if (error) { // Failed to change the name } else { // Successfully changed the name } }]; ~~~ **为Homes和Room添加Bridge(桥接口)** 桥接口是配件中的一个特殊对象,它允许你和其他配件交流,但是不允许你直接和HomeKit交流。例如一个桥接口可以是控制多个灯的枢纽,它使用的是自己的通信协议,而不是HomeKit配件通信协议。想要给home添加多个桥接口 ,你可以按照[Adding Accessories to Homes and Rooms](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/WritingtotheHomeKitDatabase/WritingtotheHomeKitDatabase.html#//apple_ref/doc/uid/TP40015050-CH4-SW5)中所描述的步骤,添加任何类型的配件到home中。当你给home添加一个桥接口时,在桥接口底层的配件也会被添加到home中。正如[Observing HomeKit Database Changes](https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/RespondingtoHomeKitDatabaseChanges/RespondingtoHomeKitDatabaseChanges.html#//apple_ref/doc/uid/TP40015050-CH5-SW2)中所描述的那样,每次更改通知设计模,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:)代理消息。在home中,要把桥接口后的配件和任何类型的配件看成一样的--例如,把它们加入配件列表的配置表中。相反的是,当你给room增添一个桥接口时,这个桥接口底层的配件并不会自动地添加到room中,原因是桥接口和它的的配件可以位于到不同的room中。 **创建分区** 分区 ([HMZone](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMZone_Class/index.html#//apple_ref/occ/cl/HMZone)) 是任意可选的房间(rooms)分组;例如楼上、楼下或者卧室。房间可以被添加到一个或者多个区域。 ![zones_2x.png](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2015-08-08_55c57697d3f1f.png "1427271797247122.png") 可使用[addZoneWithName:completionHandler: ](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMHome_Class/index.html#//apple_ref/occ/instm/HMHome/addZoneWithName:completionHandler:)异步方法创建分区。所创建的作为参数传递到这个方法中分区的名称,在home中必须是唯一的,并且应该能被Siri识别。代码如下: ~~~ __block HMHome *home = self.home; NSString *zoneName = @"Upstairs"; [home addZoneWithName:zoneName completionHandler:^(HMZone *zone, NSError *error) { if (error) { // Failed to create zone } else { // Successfully created zone, now add the rooms } }]; ~~~ 可使用[addRoom:completionHandler:](https://developer.apple.com/library/ios/documentation/HomeKit/Reference/HMZone_Class/index.html#//apple_ref/occ/instm/HMZone/addRoom:completionHandler:)异步方法给分区添加一个room,代码如下: ~~~ __block HMRoom *room = roomInHome; [zone addRoom:room completionHandler:^(NSError *error) { if (error) { // Failed to add room to zone } else { // Successfully added room to zone } }]; ~~~
';