Как просыпаться приложение iPhone от watchOS 2?

У меня есть приложение с очень богатым сетевым слоем, и приложение apple watch зависит от всех моделей. К сожалению, приложение недостаточно модульно, чтобы сделать этот слой доступным в приложении часов.

Я решил эту проблему, используя openParentApplication: чтобы пробудить приложение iPhone, выполнить запрос и вернуть результаты.

В watchOS 2 этот метод исчез, и я должен использовать WatchConnectivity. Лучшим способом использования этого является отправка пользовательских словарей.

Но как я могу разбудить приложение iPhone для обработки моих запросов? Чтобы получать уведомления о новых userInfos, я должен использовать WCSessionDelegate, и для этого мне нужен объект WCSession. Но когда я должен это создать? И как разбудить приложение?

Ответ 1

Я спросил об этом Apple Engineer и получил следующий совет: iOS-приложение должно быть запущено в фоновом задании. Итак, следующее работало для меня довольно хорошо:

UIApplication *application = [UIApplication sharedApplication];

__block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid;
dispatch_block_t endBlock = ^ {
    if (identifier != UIBackgroundTaskInvalid) {
        [application endBackgroundTask:identifier];
    }
    identifier = UIBackgroundTaskInvalid;
};

identifier = [application beginBackgroundTaskWithExpirationHandler:endBlock];

Добавьте это к методу session:didReceiveMessage: или session:didReceiveMessageData:, чтобы запустить фоновое задание с трехминутным таймаутом.

Ответ 2

Быстрая версия предложения Бенджамина Херцога ниже. Следует отметить, что, хотя я решил нажать работу, начатую Watch, на фоновое задание, пока мое приложение было в фоновом режиме, система разбудила его просто отлично. Выполнение работы в фоновом задании не требовалось, но это лучшая практика.

override init() {
    super.init()
    if WCSession.isSupported() {
        session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        let taskID = self.beginBackgroundUpdateTask()
        //Do work here...
        self.endBackgroundUpdateTask(taskID)
    })
    var replyValues = Dictionary<String, AnyObject>()
    let status = "\(NSDate()): iPhone message: App received and processed a message: \(message)."
    print(status)
    replyValues["status"] = status
    replyHandler(replyValues)
}

func beginBackgroundUpdateTask() -> UIBackgroundTaskIdentifier {
    return UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({})
}

func endBackgroundUpdateTask(taskID: UIBackgroundTaskIdentifier) {
    UIApplication.sharedApplication().endBackgroundTask(taskID)
}

Ответ 3

В расширении WatchKit вы захотите использовать API-интерфейс WatchConnectivity WCSession sendMessage. В расширении проверьте, что приложение iOS доступно, а затем отправьте сообщение:

let session = WCSession.defaultSession();
if session.reachable {
    let message = ["foo":"bar"]
    session.sendMessage(message, replyHandler: nil, errorHandler: { (error) -> Void in
        print("send failed with error \(error)")
    })
}

Это сообщение приведет к тому, что система пробудит приложение iOS в фоновом режиме, поэтому обязательно настройте WCSession в куске кода приложения iOS, который вызывается при запуске в фоновом режиме (например: t хотите поместить его в подкласс класса UIViewController viewDidLoad), чтобы сообщение было получено. Поскольку вы будете запрашивать некоторую информацию, вы можете использовать блок ответа.

Итак, вот как вы запускаете приложение iOS в фоновом режиме, хотя сеанс WatchConnectivity WWDC рекомендовал, если это возможно, использовать методы передачи "фона". Если ваше часовое приложение доступно только для чтения, вы должны иметь возможность приостанавливать любые изменения на устройстве iOS с помощью переноса фона, а затем они будут доставлены в приложение часов в следующий раз.