2017-02-26 7 views
0

먼저 푸시 알림을 수락하라는 요청을 사용자가 거부하면 어떻게 평가할 수 있습니까?iOS, iCloudKit 거래에 대한 알림 요청을 처리하는 방법은 무엇입니까?

내가 읽은 바로는 침묵 알림에 문제가있는 것으로 보입니다. 베타 버전이라고 생각되지만이 문제는 해결되었습니다.

아이들 앱을 개발 중입니다. registerForRemoteNotifications에 침묵 알림을 캡처하도록 요청하면 알림 권한 메시지가 표시됩니다.

사용자가 인터넷에 자주 액세스하지 않는 경우 iCloud 데이터베이스 설정이 어떻게되는지 궁금합니다. 내 생각 엔 앱을 처음 다운로드 할 때 앱 스토어가 있어야한다고 생각하지만 앱을 다운로드 한 후에 앱을 실행하지 않으면 데이터베이스 스키마를 어떻게 얻을 수 있을까요? 이것은 우리가 처리해야 할 것이고 사용자에게 인터넷에 연결하도록 요청할 것입니까?

나는 이것이 많은 사실을 알고 있지만 분명히 이것을 포착하고 처리해야 할 것입니다.

누구든지 유용한 포드를 지적 해 주시면 고맙겠습니다.

+0

아, 내 질문 중 하나에 답변했습니다. 버그가 수정되었음을 알았습니다. http://stackoverflow.com/questions/31108576/cloudkit-push-notifications-on-record-update-stopped-working – Jules

답변

1

쥘,

당신이 너무 많은 이와 같은 코드의 조각을 사용하여 말고, 아이 클라우드를 사용할 앱 기록을 작성

. 이제

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 
} 

여기에서 많은이 저를 용서, 나는 상세하게 모두 설명 할 시간이 없다,하지만 기록 방식은,이 코드에 CKRecord 생성 호출 4 번째 줄에서 레코드 유형을 제공 이 경우에는 "Blah"라고 불립니다.

[스키마] 내의 필드는 코드에서 자세히 설명해야하므로 여기서는 theLink, BLAHnumber 및 BLAHpath를 사용합니다. 이 정보는 다운로드되지 않으며 제작에 들어가면 변경할 수 없습니다. 따라서 새로운 스키마는 새로운 레코드 유형이어야하며 현재 업데이트 된 필드 업데이트를 통해 앱이 이전 버전인지 확인해야합니다. 호환 가능. 희망은 물건을 조금 더 분명하게하는 데 도움이됩니다.

이 기사 https://www.shinobicontrols.com/blog/ios8-day-by-day-day-33-cloudkit은 전체 주제에 대해 자세히 설명합니다. Atomic 커밋, 특히 여기에 귀하의 질문 중 하나가 언급되어 있습니다.

+0

감사합니다. 그 대답은 많이, 나는 여러 가지를 위해 당신의 오류를 잘 보았다. iCloudKit 프레임 워크가 로컬 스토리지를 처리합니까 (현재 SqlLite 데이터베이스가 있습니다), 네트워크 액세스가 없으며 레코드를 커밋 할 수 없다고 말하면됩니까? – Jules

+0

로컬 저장소. 질문을 이해할 수 있는지 확실하지 않습니다. 물론 대답은 '아니요'라고 생각할 수도 있지만, 물론 코어 데이터와 같은 것을 사용할 수도 있습니다.이 데이터는 프레임 워크 내에서 로컬 저장소를 처리하는 데 사용됩니다. 물론 iCloud 프레임 워크 내에서 SQL 유형 쿼리를 사용할 수도 있습니다. 따라서 어쩌면 적어도 부분적으로 질문에 대답 할 수 있습니다. – user3069232

+0

iCloud 데이터베이스 기능에만 의존하거나 데이터를 캐시하고 iCloud에 커밋되지 않은 트랜잭션을 처리해야합니까? – Jules