加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

swift – 使用WatchKit强制触摸MenuItem调用外部函数

发布时间:2020-12-14 05:43:30 所属栏目:百科 来源:网络整理
导读:我需要实现一个WatchKit强制触摸MenuItem来调用一个saveWorkout()方法,该方法位于一个不是WKInterfaceController子类的独立类中. 我意识到每个类至少需要一个指定的初始化程序.我猜这是关键? 顺便说一下,我的“saveSession()到达”print语句在使用sim时登录
我需要实现一个WatchKit强制触摸MenuItem来调用一个saveWorkout()方法,该方法位于一个不是WKInterfaceController子类的独立类中.

我意识到每个类至少需要一个指定的初始化程序.我猜这是关键?

顺便说一下,我的“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实例.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读