我意识到每个类至少需要一个指定的初始化程序.我猜这是关键?
顺便说一下,我的“saveSession()到达”print语句在使用sim时登录到控制台,但在我使用设备时没有.即使使用设备,所有其他打印语句也会登录到控制台.有点奇怪.
我在初始化时的尝试会抛出各种错误,例如:
1.fatal error: use of unimplemented initializer ‘init()’ for class ‘DashboardController’
2.Missing argument for parameter ‘context’ in call
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实例.