2

我正在开发一个基于 HomeKit API 的演示 iOS 应用程序。

我已经为特定家庭(H1)创建了场景(动作集)AS1,并带有一些服务(S1 S2 ...),以便一次执行多个动作。我可以毫无问题地创建多个场景,但我在更新任何创建的场景时遇到问题

我的申请流程

  • 显示添加的主页(ListView)
  • 单击任何主页,出现详细屏幕,但选项很少(附件 A1 ,房间 A2 ,场景 A3 ......)
  • 点击 A1 添加配件(可以从这里更改添加配件的服务特性)
  • A3 有一个添加场景(Action-Set)的列表以及一个将新场景(Action-Set)添加到当前主页的按钮
  • 用户可以单击任何添加的场景(动作集)来更新其动作并命名两者

问题:一旦我从附件 A1 选项更改了服务的特性,添加到场景动作的特性就会更新为相同的值。

我的假设:我认为每个创建的场景(动作集)分别维护自己的特征值,如果用户从附件 A1(从其他地方)修改任何服务的特征,那么它不应该影响添加到已保存场景的动作的值(前提条件 - 用户在创建场景的操作中选择了该附件)

我将动作集(场景)更新为的方法,

  • 一旦用户单击任何添加的 Action-Set 服务列表,用户可以单击任何服务以更新其特性
  • 访问当前 Action-Set 的 Action
  • 每个动作的访问特征(HMCharacteristicWriteAction) 访问特征的服务
  • 创建 CustomServices 实例(以跟踪一些其他信息,例如用户将该服务包含到当前操作集中等)并将其添加到数据源并避免重复
  • 一旦用户完成值更改并单击更新操作按钮
  • 启动更新过程

更新场景(动作集)

1.检查用户是否更改了Action-set的名称,

  • 然后首先更新动作集的名称,一旦成功块执行,删除所有过去添加的动作(如果存在)。
  • 向更新的场景添加新动作。

2.如果场景(动作集)名称与旧名称相同,

  • 如果存在,则删除所有以前的操作。
  • 向更新的场景添加新动作。

这是用于填充服务列表视图的代码片段(准备数据源)

func prepareDataSource(){

var actionsArray = NSArray(array: 
self.currentScene!.actions.allObjects)

    for (var index = 0 ; index<actionsArray.count; index++ ){

        var sWritttenAction:HMCharacteristicWriteAction? = actionsArray[index] as? HMCharacteristicWriteAction

        if let sActionCharacteristic = sWritttenAction!.characteristic{

            var accessoryService = sActionCharacteristic.service as HMService

            if(!isServiceAlraedyAdded(accessoryService.name)){
                var sceneService = DMIAccessoryService.initWithService(accessoryService)
                sceneService.isSelected = true
                //Add Services
                self.services.append(sceneService)
                self.addedServices.append(sceneService)
                println("its a diffrent service")
            }
            else
            {
                println("Already has the same service")
            }
        }
    }
}

我已经多次阅读 HomeKit 文档,但没有发现与此问题相关的任何内容。

据我了解动作集的概念,它应该单独维护特征值,以便我们以后可以更改它的动作值。

自最近几天以来我一直面临这个问题(因为几天前在这里发布了同样的问题)现在我确定这是苹果主页 API 中的一个错误,因为一旦我尝试重新执行相同的操作集(前置条件:用户从A1选项中更改服务特征的值。它执行成功并更新所有与创建的场景(ActionSet)具有相同特征的附件。

请任何发现更新场景(ActionSet)类似问题的人帮助我。如果我的方法是错误的,请随时指出我。

4

1 回答 1

1

可以使用HMActionSet对象创建场景,
它只公开 3 个 api,即 updateName()、addAction()、removeAction()

如果用户想要更改场景的名称,可以使用 updateName。它不应该调用任何其他 api(removeAction 或 addAction)

Add Action
addAction() 用于通过使用 Accessory 的 HMCharacteristic 来改变任何使用场景的 Accessory 的行为。该特性必须支持可以检查的WriteAction 。

[characteristic.properties containsObject:HMCharacteristicPropertyWritable]

如何加载特征
特征可以在表格视图中显示或可以创建自定义视图。并且该特征的值可以设置为显示视图。

如果当前特征已经添加到 actionset,我们需要从 actionset 对象的 actions 属性中获取值。

- (void) readValueForCharacteristic:(HMCharacteristic *)characteristic completion:(void (^)(id, NSError *))completion {
for (HMCharacteristicWriteAction *action in self.actionSet.actions) {
    if ([characteristic isEqual:action.characteristic]) {
        completion([self getTargetValueForCharacteristic:characteristic],nil);
        return;
    }
}
[characteristic readValueWithCompletionHandler:^(NSError *error) {
    dispatch_async(dispatch_get_main_queue(), ^{
        completion(characteristic.value, error);
    });
}];

}

-(id) getTargetValueForCharacteristic:(HMCharacteristic *)characteristic {
id value;
for (HMCharacteristicWriteAction *action in self.actionSet.actions) {
    if ([action.characteristic isEqual:characteristic]) {
        value = action.targetValue;
    }
}
return value;
}

现在,可以在向场景添加特征或更新特征时同时设置此值。当它检查动作是否添加到 Scene ?然后它将从 actionSet 中获取值。否则它将读取该特性的当前值。

保存场景 添加场景或更新场景时相同。只需要添加一个条件。

/** Create property */
@property (nonatomic) dispatch_group_t sceneGroup;
@property (nonatomic) NSError *error;

/** Initialize */
self.sceneGroup = dispatch_group_create();

- (void)saveActionSetWithName:(NSString *)name
            completionHandler:(void (^)(NSError *error))completion {
    if (self.actionSet) {
        [self saveScene:self.actionSet];
        [self updateNameIfRequire:name];
    } else {
        [self createScene:name];
    }
    dispatch_group_notify(self.sceneGroup, dispatch_get_main_queue(), ^{
        completion(self.error);
        self.error = nil;
    });
}

如果场景已经创建,则在 saveScene: 方法中将可写操作添加到操作集中。还要检查场景名称是否已更改,如果需要,只需使用 updateName: 方法更改名称。

如果未创建场景,则使用 HMHome 类的方法 addActionSetWithName: 创建场景,通过使用 home 对象,在其完成块上调用saveScene方法,并在其中向创建的场景添加可写动作。

您可以参考苹果的HMatalog示例项目。
如果您创建模型自定义类来管理 Actionset,那就太好了。
问我是否有任何疑问。

于 2015-05-19T06:10:26.183 回答