0

I have an app that keeps user data in a private database using CloudKit and iCloud. I have written code to handle when the user logs out of iCloud and back in as a different user via Settings -> iCloud on their device. I am currently in Beta Testing mode and when I try this as an internal tester, the app crashes when I change accounts. When I test this in development mode using either the Xcode simulator or a real device, my code works great. My question is: should CloudKit apps be able to handle when the iCloud account changes on the device? If so, is this case able to be tested with internal testing via TestFlight. My code to handle account changes is below...

func isCloudAccountAvailableASync() {
  container.accountStatusWithCompletionHandler { (accountStatus, error) in

    switch accountStatus {
    case .Available:
      print("INFO: iCloud Available!")
      // begin sync process by finding the current iCloud user
      self.fetchUserID()
      return
    case .NoAccount:
      print("INFO: No iCloud account")
    case .Restricted:
    print("WARNING: iCloud restricted")
    case .CouldNotDetermine:
      print("WARNING: Unable to determine iCloud status")
    }

    // if you get here, no sync happened so make sure to exec the callback
    self.syncEnded(false)
  }
}


func fetchUserID(numTries: Int = 0) {

  container.fetchUserRecordIDWithCompletionHandler( { recordID, error in

    if let error = error {

      // error handling code

      // reach here then fetchUser was a failure
      self.syncEnded(false)
    }
    else {

      // fetchUserID success

      if self.lastiCloudUser == nil {
        print("INFO: our first iCloud user! \(recordID)")
        self.saveUserID()
      }
      else if !recordID!.isEqual(self.lastiCloudUser) {
        // User has changed!!!!!!!!!!!!!
        self.saveUserID()

        // delete all local data

        // reset the saved server token
        self.saveServerToken(nil)
        // try again with reset fields
      }
      // else user never changed, then just create a zone

      // continue the sync process
      self.initZone()
    }
  })
}

---EDIT/UPDATE:--- Here is a screenshot of my crash log

CrashLogScreenshot

---EDIT/UPDATE 2:--- I was able to generate another crash with a different crash log. This crash log still doesn't point to my code, but at least describes a function...

CrashLog with sharedIMPL_removeObjectFromSet_core

Coder1224
  • 1,429
  • 2
  • 15
  • 21
  • Update your question with details about the crash. – rmaddy Jan 26 '17 at 03:49
  • Added a screenshot (wasn't sure how to copy/paste text from Xcode so its an image). It's just hex instructions and when I click "Open in Project" I get nothing. The blacked out lines are just the name of my app. – Coder1224 Jan 26 '17 at 19:32

2 Answers2

1

I kept making it crash and somehow got a crash log that included a line of code I could link to a line in my Xcode project. My issue was with NSOrderedSet and iOS 9. That issue can be found here. I do not know why I only got hex in my crash log before, if anyone knows how to deal with hex crash logs I would love to hear it.

Here are the answers to my original question for anyone out there:

  1. Should CloudKit apps be able to handle when the iCloud account changes on the device? Answer: Yes
  2. If so, is this case able to be tested with internal testing via TestFlight? Answer: Yes
Community
  • 1
  • 1
Coder1224
  • 1,429
  • 2
  • 15
  • 21
0

It's hard to say were your app crashes exactly. You have to be aware that after an account change you should reset the state of your app (clearing local user data and navigating away from the screen that has user specific data) On startup of your app you should call a function like this:

func reactToiCloudloginChanges() {
    NotificationCenter.default.addObserver(forName: NSNotification.Name.NSUbiquityIdentityDidChange, object: nil, queue: nil) { _ in
        // The user’s iCloud login changed: should refresh all local user data here.
        Async.main {
            self.viewController?.removeFromParentViewController()
            // Or some other code to go back to your start screen.
        }
        return
    }
}
Edwin Vermeer
  • 12,666
  • 2
  • 31
  • 56
  • I was able to get a different crash log this morning, which I added to my original question above as an edit/update. It points to Core Data. I thought I was cleaning up my user data by doing a core data delete and then save context. I was not changing my view controller however. – Coder1224 Jan 27 '17 at 18:16
  • Did you debug while you had added breakpoints for 'All exceptions' and 'Swift errors'? You can add those by going to your list of breakpoints and pressing the plus in the lower left corner. – Edwin Vermeer Jan 27 '17 at 21:17
  • The frustrating thing is this bug only shows up while running a beta test version via TestFlight used as internal testing (let me know if you aren't familiar). When I do the exact same steps on the exact same device (iPad mini running iOS 9.3.5) but while plugged into Xcode it does not crash and runs fine. The only difference I can think of is my iCloud development vs production data. I can only run the debugger while plugged into Xcode and running development code right? – Coder1224 Jan 28 '17 at 07:49