Search code examples
iosswifticloud

Confused on snippet of code for implementing iCloud behavior on iOS


The code is from a book. In terms of overall app architecture (MVC), it's part of the Model. The model has two main components:

  • An array of tags called tags
  • A dictionary of tag - query called searches

The app saves these pieces of data in the NSUserDefaults (iOS defaults system) and on iCloud. The following method is called when a change in iCloud is signaled. The parameter is an instance of NSNotification.userInfo

// add, update, or delete searches based on iCloud changes
func performUpdates(userInfo: [NSObject: AnyObject?]) {

    // get changed keys NSArray; convert to [String]
    let changedKeysObject = userInfo[NSUbiquitousKeyValueStoreChangedKeysKey]
    let changedKeys = changedKeysObject as! [String]

    // get NSUbiquitousKeyValueStore for updating
    let keyValueStore = NSUbiquitousKeyValueStore.defaultStore()

    // update searches based on iCloud changes
    for key in changedKeys {
        if let query = keyValueStore.stringForKey(key) {
            saveQuery(query, forTag: key, saveToCloud: false)
        } else {
            searches.removeValueForKey(key)
            tags = tags.filter{$0 != key}
            updateUserDefaults(updateTags: true, updateSearches: true)
        }

        delegate.modelDataChanged() // update the view
    }
}

My question is on the if - else inside the for loop. The for loop iterates over keys that where changed; either the user adds a new search, updates an existing search, or deletes a search. But, I don't understand the logic behind the if-else. Some clarifying thoughts would be appreciated. I've read it over and over but it doesn't tick with me.


Solution

  • if let query = keyValueStore.stringForKey(key)
    

    means that if keyValueStore contains a string corresponding to key, then this string will be assigned to the constant query.

    This is called "safe unwrapping":

    inside the if let ... condition, the query is safely saved with saveQuery because using if let ... guarantees that the value of keyValueStore.stringForKey(key) won't be nil.

    If the value is nil, then in the else branch, the filter method is used to update the tags array without the key we just processed: tags.filter{$0 != key} means "return all items in tags that are different from key" (the $0 represents the current item from the array processed by filter).