2017-09-07 16 views
19

Tôi đã tìm kiếm câu trả lời cho câu hỏi này trong một thời gian khá dài, vì vậy tôi nghĩ rằng tôi sẵn sàng mạo hiểm một số downvotes để đăng nó.Mã mẫu Apple cho nền mở rộng WatchKit Làm mới

Về cơ bản, tôi muốn tạo mã mẫu do Apple cung cấp để làm mới nền Apple Watch thực sự hoạt động (liên kết và mã bên dưới).

Tôi đã thử cả trong trình mô phỏng và trên iPhone 6s với Apple Watch Series 2 và các tác vụ nền không bao giờ được hoàn thành thành công đến thời điểm cập nhật thời gian. Tôi đã thử ghim ứng dụng đồng hồ vào thanh công cụ và tôi đã cố giữ ứng dụng ở nền trước và gửi ứng dụng tới nền, cả trong trình mô phỏng và trên đồng hồ thực tế. Tôi thậm chí đã cố gắng chờ gần một năm để xem liệu Xcode hay Apple Watch có nhận được bản cập nhật có thể làm cho nó hoạt động không.

Có ai đã sửa đổi thành công mã được Apple cung cấp để mã hoạt động không?

Bạn có thể tải toàn bộ dự án mẫu Runnable đây: WatchBackgroundRefresh: Using WKRefreshBackgroundTask to update WatchKit apps in the background

/* 
Copyright (C) 2016-2017 Apple Inc. All Rights Reserved. 
See LICENSE.txt for this sample’s licensing information 

Abstract: 
The main interface controller. 
*/ 

import WatchKit 
import Foundation 


class MainInterfaceController: WKInterfaceController, WKExtensionDelegate, URLSessionDownloadDelegate { 
    // MARK: Properties 

    let sampleDownloadURL = URL(string: "http://devstreaming.apple.com/videos/wwdc/2015/802mpzd3nzovlygpbg/802/802_designing_for_apple_watch.pdf?dl=1")! 

    @IBOutlet var timeDisplayLabel: WKInterfaceLabel! 

    private let dateFormatter: DateFormatter = { 
     let formatter = DateFormatter() 
     formatter.dateStyle = .none 
     formatter.timeStyle = .long 

     return formatter 
    }() 

    // MARK: WKInterfaceController 

    override func awake(withContext context: Any?) { 
     super.awake(withContext: context) 

     // Configure interface objects here. 
     WKExtension.shared().delegate = self 
     updateDateLabel() 
    } 

    // MARK: WKExtensionDelegate 
    func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) { 
     for task : WKRefreshBackgroundTask in backgroundTasks { 
      print("received background task: ", task) 
      // only handle these while running in the background 
      if (WKExtension.shared().applicationState == .background) { 
       if task is WKApplicationRefreshBackgroundTask { 
        // this task is completed below, our app will then suspend while the download session runs 
        print("application task received, start URL session") 
        scheduleURLSession() 
       } 
      } 
      else if let urlTask = task as? WKURLSessionRefreshBackgroundTask { 
       let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlTask.sessionIdentifier) 
       let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) 

       print("Rejoining session ", backgroundSession) 
      } 
      // make sure to complete all tasks, even ones you don't handle 
      task.setTaskCompleted() 
     } 
    } 

    // MARK: Snapshot and UI updating 

    func scheduleSnapshot() { 
     // fire now, we're ready 
     let fireDate = Date() 
     WKExtension.shared().scheduleSnapshotRefresh(withPreferredDate: fireDate, userInfo: nil) { error in 
      if (error == nil) { 
       print("successfully scheduled snapshot. All background work completed.") 
      } 
     } 
    } 

    func updateDateLabel() { 
     let currentDate = Date() 
     timeDisplayLabel.setText(dateFormatter.string(from: currentDate)) 
    } 

    // MARK: URLSession handling 

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 
     print("NSURLSession finished to url: ", location) 
     updateDateLabel() 
     scheduleSnapshot() 
    } 

    func scheduleURLSession() { 
     let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString) 
     backgroundConfigObject.sessionSendsLaunchEvents = true 
     let backgroundSession = URLSession(configuration: backgroundConfigObject) 

     let downloadTask = backgroundSession.downloadTask(with: sampleDownloadURL) 
     downloadTask.resume() 
    } 

    // MARK: IB actions 

    @IBAction func ScheduleRefreshButtonTapped() { 
     // fire in 20 seconds 
     let fireDate = Date(timeIntervalSinceNow: 20.0) 
     // optional, any SecureCoding compliant data can be passed here 
     let userInfo = ["reason" : "background update"] as NSDictionary 

     WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fireDate, userInfo: userInfo) { (error) in 
      if (error == nil) { 
       print("successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire.") 
      } 
     } 
    } 

} 

Sau đây là kết quả khi chạy trên giả lập. đầu ra tương tự (nhưng không nhất thiết phải giống hệt nhau) khi chạy trong các cấu hình khác:

successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire. 
received background task: <WKSnapshotRefreshBackgroundTask: 0x7b019030> 
received background task: <WKApplicationRefreshBackgroundTask: 0x7a711290> 
application task received, start URL session 
+0

Một số lời khuyên chung: sử dụng quy ước đặt tên Swift, là camelCase thấp hơn cho các tên hàm ('scheduleRefreshButtonTapped()'). Về câu hỏi của bạn: vui lòng cung cấp thêm ngữ cảnh về nội dung không hoạt động. Lịch trình có thành công không? 'Handle (backgroundTasks:') có được gọi là không? Hãy cụ thể hơn. –

+0

@ DávidPásztor Cảm ơn, tôi chắc chắn sẽ sửa chữa các quy ước đặt tên khi tôi kết hợp bất kỳ mã Apple nào vào dự án của riêng tôi. Đối với các chi tiết cụ thể về những gì không hoạt động, tôi đã chỉnh sửa câu hỏi để thêm một mẫu đầu ra tương ứng. – PerpetualStudent

+0

Bạn đã thử mã này trên trình mô phỏng đồng hồ được kết nối với iPhone thực hay trên Apple Watch thực được kết nối với iPhone. –

Trả lời

6

Đối với bất cứ ai có thể tìm thấy điều này, có 2 vấn đề mà tôi đã thấy, cả hai với lịch trình URLSession. Với những thay đổi này, tôi nghĩ mã mẫu Apple thực sự hoạt động, ít nhất là trên trình mô phỏng.

-The sampleDownloadURL cần phải bảo mật, vì vậy cần có URL với HTTPS. Cái này hoạt động: https://api.weather.gov/points/42.3584,-71.0598/forecast

-Nó vẻ với tôi như các đại biểu cho URLSession không bao giờ được thiết lập để self, vì vậy sự thay đổi sau cố định rằng:

let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) 

Sau đây làm việc (mặc dù không hoàn chỉnh) mã rất hữu ích: What's New in watchOS 3: Background Tasks

Chỉnh sửa: Một vấn đề khác có thể xảy ra là các tác vụ được hoàn thành ngay sau khi nhận được. Trong thực tế, chúng nên được lưu (trong một biến cục bộ, ví dụ) và sau đó hoàn thành sau khi tất cả xử lý cho nhiệm vụ đó hoàn tất. Đối với mã này, tôi nghĩ điều đó có nghĩa là treo trên số WKApplicationRefreshBackgroundTask và không gọi số setTaskCompleted() trên đó cho đến khi cuộc gọi đến scheduleSnapshot.

Các vấn đề liên quan