Xcode 8.3.3 中的 iOS Swift Researchkit 谓词问题

Posted

技术标签:

【中文标题】Xcode 8.3.3 中的 iOS Swift Researchkit 谓词问题【英文标题】:iOS Swift Researchkit Predicate issue in Xcode 8.3.3 【发布时间】:2018-03-19 23:52:05 【问题描述】:

我正在工作基于 Researchkit 的应用程序,我正在根据 Xcode 8.3.3 中单选问题的选定选项导航到问题。不幸的是,应用程序在设置导航规则时动态崩溃。在 Xcode 8.2.1 早期,我没有问题并且工作顺利。请让我知道我的代码出了什么问题,以下是崩溃日志:

无法将“(谓词:__ObjC.NSPredicate,destinationStepIdentifier:Swift.String)”(0x15fe50570)类型的值转换为“(resultPredicate:__ObjC.NSPredicate,destinationStepIdentifier:Swift.String)”(0x15fe60530)。 2017-10-10 07:37:57.530808 Turbo[7440:2981376] 无法将类型“(谓词:__ObjC.NSPredicate,destinationStepIdentifier:Swift.String)”(0x15fe50570)的值转换为“(resultPredicate:__ObjC.NSPredicate,destinationStepIdentifier : Swift.String)' (0x15fe60530)。

           //Question0
    let textChoiceOneText = NSLocalizedString("Choice 1", comment: "")
    let textChoiceTwoText = NSLocalizedString("Choice 2", comment: "")
    let textChoiceThreeText = NSLocalizedString("Choice 3", comment: "")

    // The text to display can be separate from the value coded for each choice:
    let textChoices = [
        ORKTextChoice(text: textChoiceOneText, value: "choice_1" as NSCoding & NSCopying & NSObjectProtocol),
        ORKTextChoice(text: textChoiceTwoText, value: "choice_2" as NSCoding & NSCopying & NSObjectProtocol),
        ORKTextChoice(text: textChoiceThreeText, value: "choice_3" as NSCoding & NSCopying & NSObjectProtocol)
    ]
    let answerFormat = ORKAnswerFormat.choiceAnswerFormat(with: .singleChoice, textChoices: textChoices)
    let questionStepzero = ORKQuestionStep(identifier: String(describing:"singlechoice0"), title: "titel", answer: answerFormat)

    //question1
    let question1 = ORKQuestionStep(identifier: "question1")
    question1.answerFormat = ORKBooleanAnswerFormat()
    //question2
    let question2 = ORKQuestionStep(identifier: "question2")
    question2.answerFormat = ORKBooleanAnswerFormat()

    //Question6
    let question6 = ORKQuestionStep(identifier: "question6")
    question6.answerFormat = ORKBooleanAnswerFormat()


    //Question 7
    let defaultDate = Date()
    let minDate = Date()
    let maxDate = Date()
    let nameQuestionStepTitle = "title message"
    let dateAnswer = ORKDateAnswerFormat(style:ORKDateAnswerStyle.date, defaultDate: defaultDate, minimumDate: minDate, maximumDate: maxDate, calendar: nil)
    let dataPickerQuestionStep7 = ORKQuestionStep(identifier: "datequestion7", title:nameQuestionStepTitle, answer: dateAnswer)


    let steps = [questionStepzero,question1, question2,question6,dataPickerQuestionStep7]
    let task = ORKNavigableOrderedTask(identifier: "task", steps: steps)

    let predicate1 = ORKResultPredicate.predicateForChoiceQuestionResult(with: ORKResultSelector(resultIdentifier: "singlechoice0"), matchingPattern: "choice_1")
    let predicate2 = ORKResultPredicate.predicateForChoiceQuestionResult(with: ORKResultSelector(resultIdentifier: "singlechoice0"), matchingPattern: "choice_2")
    let predicate3 = ORKResultPredicate.predicateForChoiceQuestionResult(with: ORKResultSelector(resultIdentifier: "singlechoice0"), matchingPattern: "choice_3")


    let singleChulesArray:NSMutableArray =  NSMutableArray()

    var dict:NSMutableDictionary = NSMutableDictionary()
    dict.setObject(predicate1, forKey: "predicateInstance" as NSCopying)
    dict.setObject("datequestion7", forKey: "Destination" as NSCopying)
    singleChulesArray.add(dict)
    dict = NSMutableDictionary()

    dict.setObject(predicate2, forKey: "predicateInstance" as NSCopying)
    dict.setObject("question2", forKey: "Destination" as NSCopying)
    singleChulesArray.add(dict)

    dict = NSMutableDictionary()
    dict.setObject(predicate3, forKey: "predicateInstance" as NSCopying)
    dict.setObject("question6", forKey: "Destination" as NSCopying)
    singleChulesArray.add(dict)



    //Static loading of Predicates and Destintionidentifiers
    /*
    let predicateRule1 = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: [
        (resultPredicate: predicate1, destinationStepIdentifier: "datequestion7"),
        (resultPredicate: predicate2, destinationStepIdentifier: "question2"),
        (resultPredicate: predicate3, destinationStepIdentifier: "question6")
        ])
    */

    print("singleChulesArray",singleChulesArray)

    //Dynamic loading of Predicates and Destination identifiers
    var stuff:[(predicate: NSPredicate, destinationStepIdentifier: String)] = [(predicate: NSPredicate, destinationStepIdentifier: String)]()
    for (_, PredicateDict) in singleChulesArray.enumerated()
    
        stuff += [(predicate: (PredicateDict as AnyObject).value(forKey: "predicateInstance") as! NSPredicate, destinationStepIdentifier: (PredicateDict as AnyObject).value(forKey: "Destination") as! String)]
    

    let predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: stuff as! [(resultPredicate: NSPredicate, destinationStepIdentifier: String)])

    task.setNavigationRule(predicateRule, forTriggerStepIdentifier: "singlechoice0")
    let taskViewController = ORKTaskViewController(task: task, taskRun: nil)
    taskViewController.view.tintColor = TurboConstants.globalAccess.primaryClr
    taskViewController.delegate = self
    present(taskViewController, animated: true, completion: nil)

【问题讨论】:

【参考方案1】:

您错误地使用了ORKPredicateStepNavigationRule 初始化程序。初始化程序将元组数组作为参数。您需要在初始化程序中传递元组的元素名称:

let predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: [(resultPredicate: predicate1, destinationStepIdentifier: "datequestion7")])

或者使用多个元组:

let predicateRule = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: [
            (resultPredicate: predicate1, destinationStepIdentifier: "datequestion7"),
            (resultPredicate: predicate2, destinationStepIdentifier: "question2"),
            (resultPredicate: predicate3, destinationStepIdentifier: "question6"),
            ])

或动态(如您上面的代码):

var stuff = [(resultPredicate: NSPredicate, destinationStepIdentifier: String)]()
for predicateDict in singleChulesArray

    guard
        let predicateDict = predicateDict as? [String: Any],
        let predicate = predicateDict["predicateInstance"] as? NSPredicate,
        let identifier = predicateDict["Destination"] as? String
        else  continue 
    stuff.append((resultPredicate: predicate, destinationStepIdentifier: identifier))

要消除崩溃,您只需将元组元素名称predicate 更改为正确的名称resultPredicate。当元组用作方法中的参数时,元素名称的命名必须与方法签名中的完全一致。否则你会崩溃。

我冒昧地在您的代码的那部分进行了更多更改。我删除了强制转换(这几乎不是一个好主意),而是使用了可选的展开。此外,我使用appendstuff 数组添加一个新元组,而不是创建一个新数组(将元组作为其唯一元素),然后将该数组添加到 stuff 数组。

【讨论】:

是的,它仅适用于单个谓词的答案,但我无法导航具有多个选项(多个谓词)的单选问题。面临动态 JSON 框架中的问题。下面是实际代码 请查看编辑后的答案。这能解决你的问题吗? var predicateAndDestinationIdentifierArray:[(predicate: NSPredicate, destinationString: String)] = [(predicate: NSPredicate, destinationString: String)]() for (index, PredicateDict) in singleChoicePredicateRulesArray.enumerated() let PredicateDic:NSMutableDictionary = PredicateDict as! NSMutableDictionary predicateAndDestinationIdentifierArray += [(predicate: PredicateDic.value(forKey: "predicateInstance") as!NSPredicate, destinationString: PredicateDic.value(forKey: "Destination") as!String)] 让 singleChoicePredicate = ORKPredicateStepNavigationRule(resultPredicatesAndDestinationStepIdentifiers: predicateAndDestinationIdentifierArray as! [(resultPredicate: NSPredicate, destinationStepIdentifier: String)]) 感谢您的回复,请查看我的代码,您能否告诉我它崩溃的原因。

以上是关于Xcode 8.3.3 中的 iOS Swift Researchkit 谓词问题的主要内容,如果未能解决你的问题,请参考以下文章

xcode 8.3.3 是不是运行 swift 3.2

Apple Mach-O 链接器 (ld) 错误 swift 3.0 和 Xcode 8.3.3

Swift 开发的代码在 Xcode 8.x 或 Xcode 7.x 中不起作用

iOS 9.0 Xcode 8.3.3 MfiBtPrinterConnection.h streming 蓝牙 maxLength Zebra ZQ520

Xcode 8 / Swift 3 中的 iOS 异步单元测试(waitForExpectations 失败)

堆栈视图中的自动约束冲突、Swift 2、iOS 9.3、XCode 7