swift – 使用WatchKit强制触摸MenuItem调用外部函数
我需要实现一个WatchKit强制触摸MenuItem来调用一个saveWorkout()方法,该方法位于一个不是WKInterfaceController子类的独立类中.
我意识到每个类至少需要一个指定的初始化程序.我猜这是关键? 顺便说一下,我的“saveSession()到达”print语句在使用sim时登录到控制台,但在我使用设备时没有.即使使用设备,所有其他打印语句也会登录到控制台.有点奇怪. 我在初始化时的尝试会抛出各种错误,例如:
Dashboard.swift class DashboardController: WKInterfaceController { @IBOutlet var timerLabel: WKInterfaceTimer! @IBOutlet weak var milesLabel: WKInterfaceLabel! // var wSM: WorkoutSessionManager //init(wSM: WorkoutSessionManager) { // self.wSM = wSM // super.init() // } override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) addMenuItemWithItemIcon(.Accept,title: "Save",action: #selector(DashboardController.saveSession)) } override func willActivate() { super.willActivate() print("Dashboard controller reached") } func saveSession() { //wSM.saveWorkout() print("saveSession() reached") } WorkoutSessionManager.swift class WorkoutSessionContext { let healthStore: HKHealthStore let activityType: HKWorkoutActivityType let locationType: HKWorkoutSessionLocationType init(healthStore: HKHealthStore,activityType: HKWorkoutActivityType = .Other,locationType: HKWorkoutSessionLocationType = .Unknown) { self.healthStore = healthStore self.activityType = activityType self.locationType = locationType } } protocol WorkoutSessionManagerDelegate: class { // ... protocol methods } class WorkoutSessionManager: NSObject,HKWorkoutSessionDelegate { let healthStore: HKHealthStore let workoutSession: HKWorkoutSession init(context: WorkoutSessionContext) { self.healthStore = context.healthStore self.workoutSession = HKWorkoutSession(activityType: context.activityType,locationType: context.locationType) self.currentActiveEnergyQuantity = HKQuantity(unit: self.energyUnit,doubleValue: 0.0) self.currentDistanceQuantity = HKQuantity(unit: self.distanceUnit,doubleValue: 0.0) super.init() self.workoutSession.delegate = self } func saveWorkout() { guard let startDate = self.workoutStartDate,endDate = self.workoutEndDate else {return} // ...code...
致命错误是(或曾)由此行引起的:
让wSM = WorkoutSessionManager() 该行创建WorkoutSessionManager的新实例并在其上调用init(). Swift为任何为其所有属性提供默认值的结构或类提供了一个名为init()的默认初始化程序,并且本身不提供至少一个初始化程序.但WorkoutSessionManager不提供healthStore和workoutSession属性的默认值(并且这些属性不是选项),并且它提供了自己的名为init(context :)的初始化程序,因此它没有默认初始值设定项. 您需要使用指定的初始化程序init(context :)(传递WorkoutSessionContext的相应实例)创建WorkoutSessionManager实例,或者为WorkoutSessionManager提供名为init()的默认初始化程序. 您应该以何种方式完成前者取决于应用程序其余部分的实现以及DashboardController的演示.我假设您正在尝试重新创建WWDC 2015 Session 203中显示的“Fit”应用程序. 在该演示中,初始控制器是ActivityInterfaceController的一个实例,该控制器负责呈现下一个界面(通过故事板中创建的segue).您可以在ActivityInterfaceController类中看到以下代码: override func contextForSegueWithIdentifier(segueIdentifier: String) -> AnyObject? { let activityType: HKWorkoutActivityType switch segueIdentifier { case "Running": activityType = .Running case "Walking": activityType = .Walking case "Cycling": activityType = .Cycling default: activityType = .Other } return WorkoutSessionContext(healthStore: self.healthStore,activityType: activityType) } 上面的函数使用初始控制器持有的HKHealthStore实例创建并返回WorkoutSessionContext的新实例.该函数返回的上下文通过awakeWithContext传递给相关segue的目标接口控制器. 对于代码中的转换,您可以使用等效函数传递上下文实例,例如pushControllerWithName(context :),这也会导致awakeWithContext. 如果您的初始控制器与上面的类似,您可以在DashboardController类的awakeWithContext中访问传递的上下文,并使用它来配置WorkoutSessionManager的新实例: class DashboardController: WKInterfaceController { // ... var wSM: WorkoutSessionManager? override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) if context is WorkoutSessionContext { wSM = WorkoutSessionManager(context: context as! WorkoutSessionContext) } addMenuItemWithItemIcon(.Accept,action: #selector(DashboardController.saveSession)) } // ... } 以这种方式创建WorkoutSessionManager的实例可以避免调用(不存在的)init()初始化程序并允许重用HKHealthStore实例.这种方法是否对您开放取决于您的代码的其余部分以及您呈现DashboardController的方式. 请注意,您应该避免创建WorkoutSessionManager的多个实例.使用singleton提供在您的扩展程序中共享的单个WorkoutSessionManager实例. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |