Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

updateValue not working for Dictionary

I'm creating a test app using Swift in Xcode, and I've run into an annoying issue. I'm writing a simple class that will act as a cache using a Dictionary object. My implementation is below:

import Foundation
import UIKit

class ImageCache {
    var dict:Dictionary<String,NSData>?;

    init() {
        dict = Dictionary<String,NSData>();
    }

    func exists(id:String) -> Bool {
        return dict!.indexForKey(id)!==nil;
    }

    func getImage(id:String) -> UIImage? {
        if(!exists(id)) {
            return nil;
        }
        return UIImage(data: (dict!)[id]);
    }

    func setData(id:String, data:NSData) {
        dict!.updateValue(data, forKey: id);
    }
}

The issue is in the last method, with Xcode stating "Could not find member 'UpdateValue'". This is weird, because the code hint seems to show it just fine:

Code hint

But when I try to compile:

Compilation error

Could this potentially be a bug in Xcode? Or am I missing something super-obvious?

like image 552
William Thomas Avatar asked Jun 03 '14 19:06

William Thomas


1 Answers

this is not a bug or a quirk in the compiler.

it is how Optional implemented (which may be flawed or not)

what happened is that the Optional store the Dictionary as immutable object (with let perhaps). So even Optional it is mutable, you can't modify the underlying Dictionaryobject directly (without reassign the Optional object).

updateValue(forKey:) is mutating method, you can't call it on immutable object and hence the error.

you can workaround it by doing

var d = dict!
d.updateValue(data, forKey: id)

because you copy the dictionary to another mutable variable, which then is mutable and able to call mutating method on it

but without dict = d, your change won't be applied on dict because Dictionary is value type, it makes copy on every assignment

related answer

like image 65
Bryan Chen Avatar answered Oct 09 '22 08:10

Bryan Chen