2017-02-26 4 views
0

Erstens, was ist, wenn der Benutzer die Anfrage verweigert, Push-Benachrichtigungen zu akzeptieren, wie kann dies ausgewertet werden.iOS, Wie werden Nachbenachrichtigungsanfragen für iCloudKit-Transaktionen behandelt?

Von dem, was ich gelesen habe, scheint es, dass es ein Problem mit stillen Benachrichtigungen gab, obwohl ich denke, dass es eine Beta war, wurde dieses Problem behoben.

Ich entwickle eine Kinder-App, wenn ich registerForRemoteNotifications anrufen, um stille Benachrichtigungen zu erfassen, wird dies die Benachrichtigung Erlaubnis Nachricht anzeigen.

Ich frage mich auch, was passiert mit der iCloud-Datenbank-Setup, wenn der Benutzer nur selten Internet-Zugang hat. Ich denke, sie müssen es haben, wenn die App zum ersten Mal heruntergeladen wird, aber wenn sie die App nach dem Download nie ausführen, wie bekommen sie dann das Datenbankschema? Müssen wir damit umgehen und den Benutzer bitten, sich mit dem Internet zu verbinden?

Ich weiß, dass vieles davon hypothetisch ist, aber wir müssten das natürlich erfassen und handhaben.

Ich wäre auch dankbar, wenn jemand auf nützliche und hilfreiche Pods hinweisen könnte.

+0

Ahh, ich habe eine meiner Fragen beantwortet, ich sehe, dass der Fehler behoben wurde http://StackOverflow.com/Questions/31108576/CloudKit-Push-Notifications-on-record-update-stopped-working – Jules

Antwort

1

Jules,

Wenn Sie einen Datensatz mit einem iCloud aktiviert App erstellen Sie so ein Stück Code viel wie diese verwenden.

func files_saveNotes(rex: Int) { 
    var localChanges:[CKRecord] = [] 

     let newRecordID = CKRecordID(recordName: sharedDataAccess.returnRexID(index2seek: rex)) 
     let newRecord = CKRecord(recordType: "Blah", recordID: newRecordID) 

     let theLinkID = CKReference(recordID: sharedDataAccess.iCloudID, action: .deleteSelf) 
     let thePath = sharedDataAccess.fnGet(index2seek: rex) 
     newRecord["theLink"] = theLinkID 
     newRecord["theBLAHnumber"] = rex as CKRecordValue? 
     newRecord["theBLAHpath"] = thePath as CKRecordValue? 

    localChanges.append(newRecord) 
    let records2Erase:[CKRecordID] = [] 

    let saveRecordsOperation = CKModifyRecordsOperation(recordsToSave: localChanges, recordIDsToDelete: records2Erase) 
    saveRecordsOperation.savePolicy = .allKeys 
    saveRecordsOperation.perRecordCompletionBlock = { record, error in 
     if error != nil { 
      //print(error!.localizedDescription) 
     } 
     // deal with conflicts 
     // set completionHandler of wrapper operation if it's the case 
    } 
    saveRecordsOperation.modifyRecordsCompletionBlock = { savedRecords, deletedRecordIDs, error in 
     self.theApp.isNetworkActivityIndicatorVisible = false 

     guard error == nil else { 
      if let ckerror = error as? CKError { 
       if ckerror.code == CKError.requestRateLimited { 
        let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval 
        DispatchQueue.main.async { 
         Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_saveNotes), userInfo: nil, repeats: false) 
        } 
       } else if ckerror.code == CKError.zoneBusy { 
        let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval 
        DispatchQueue.main.async { 
         Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_saveNotes), userInfo: nil, repeats: false) 
        } 
       } else if ckerror.code == CKError.limitExceeded { 
        let retryInterval = ckerror.userInfo[CKErrorRetryAfterKey] as? TimeInterval 
        DispatchQueue.main.async { 
         Timer.scheduledTimer(timeInterval: retryInterval!, target: self, selector: #selector(self.files_saveNotes), userInfo: nil, repeats: false) 
        } 
       } else if ckerror.code == CKError.notAuthenticated { 
        NotificationCenter.default.post(name: Notification.Name("noCloud"), object: nil, userInfo: nil) 
       } else if ckerror.code == CKError.networkFailure { 
        NotificationCenter.default.post(name: Notification.Name("networkFailure"), object: nil, userInfo: nil) 
       } else if ckerror.code == CKError.networkUnavailable { 
        NotificationCenter.default.post(name: Notification.Name("noWiFi"), object: nil, userInfo: nil) 
       } else if ckerror.code == CKError.quotaExceeded { 
        NotificationCenter.default.post(name: Notification.Name("quotaExceeded"), object: nil, userInfo: nil) 
       } else if ckerror.code == CKError.partialFailure { 
        NotificationCenter.default.post(name: Notification.Name("partialFailure"), object: nil, userInfo: nil) 
       } else if (ckerror.code == CKError.internalError || ckerror.code == CKError.serviceUnavailable) { 
        NotificationCenter.default.post(name: Notification.Name("serviceUnavailable"), object: nil, userInfo: nil) 
       } 
      } // end of guard statement 
      return 
     } 
     if error != nil { 
      print(error!.localizedDescription) 
     } else { 
      print("ok \(savedRecords)") 
     } 
    } 

    saveRecordsOperation.qualityOfService = .background 
    privateDB.add(saveRecordsOperation) 
    theApp.isNetworkActivityIndicatorVisible = true 
} 

Nun vergib mir gibt es eine Menge hier, und ich habe nicht die Zeit, in allem im Detail zu erklären, aber die Plattenschema stammt aus CKRecord call 4. Zeile in diesem Code, den Datensatztyp in diesem Fall "Blah" genannt.

Die Felder darin [das Schema], müssen Sie in Ihrem Code wie ich hier, so dass wir theLink, die BLAHnumber und die BLAHpath in diesem Fall. Diese Informationen werden nicht heruntergeladen, und sobald Sie in Produktion gehen, können Sie sie nicht mehr ändern. Daher müssen neue Schemata neue Datensatztypen sein, und Sie müssen mit Feldaktualisierungen für aktuelle Einträge vorsichtig sein, um sicherzustellen, dass Ihre App rückwärts läuft. kompatibel. Hoffnung, die hilft, die Dinge ein wenig klarer zu machen.

Dieser Artikel https://www.shinobicontrols.com/blog/ios8-day-by-day-day-33-cloudkit spricht in sehr viel mehr Details über das ganze Thema. Atomic Commits, eine Ihrer Fragen wird hier besonders erwähnt.

+0

Danke das antwortet viel, ich sehe deinen Fehler bei der Übergabe verschiedener Dinge, großartig. Behandelt das iCloudKit-Framework lokalen Speicher für uns (ich habe derzeit eine SqlLite-Datenbank), sagen, es gibt keinen Netzwerkzugriff und ein Datensatz kann nicht festgeschrieben werden? – Jules

+0

Lokaler Speicher, unsicher wenn ich Ihre Frage verstehe. Obwohl ich denke, die Antwort ist Nein. Sie können natürlich so etwas wie Core Data damit verwenden, was in der Lage ist, lokalen Speicher innerhalb eines Frameworks zu behandeln. Sie können natürlich auch Abfragen vom SQL-Typ innerhalb des iCloud-Frameworks verwenden, damit Ihre Frage zumindest teilweise beantwortet wird. – user3069232

+0

Ich meine, kann ich mich ausschließlich auf die iCloud-Datenbankfunktionalität verlassen oder muss ich Daten zwischenspeichern und an Transaktionen hängen, die möglicherweise nicht an iCloud übergeben wurden? – Jules

Verwandte Themen