2014-10-22 2 views
3

У меня есть приложение, управляющее простым портфелем акций. Помимо всего прочего, он ведет учет требуемых обменных курсов в словаре, например: [EURUSD = X: 1.267548] Это свойство является одним из свойств словаря под названием CurrencyRateStore.Swift - доступ к словарю Singleton вызывает EXC_BAD_ACCESS

При обновлении штоков котировки, он проверяет наличие обновленного курса и обновляет словарь со следующим кодом:

CurrencyRateStore.sharedStore()[symbol] = fetchedRate.doubleValue 

Это вызывает:

subscript(index: String) -> Double? { 
    get { 
     return dictionary[index] 
    } 
    set { 
     // FIXME: crashes when getting out of the app (Home button) and then relaunching it 
      dictionary[index] = newValue! 
      println("CurrencyRateStore - updated rate for \(index) : \(newValue!)") 
    } 
} 

В первый раз приложение запускается , он отлично работает. Но если я выйти из приложения (с помощью кнопки Home), а затем возобновить его, курсы валют обновляются снова, но на этот раз, я получаю EXC_BAD_ACCESS на линии

dictionary[index] = newValue! 

Вот скриншот: enter image description here

[EDIT] Вот нить в отладочный навигатора: enter image description here

Я пытался обновить словарь без индекса, например, так:

CurrencyRateStore.sharedStore().dictionary[symbol] = fetchedRate.doubleValue 

но без особого успеха. То же самое, если я использую функцию updateValue: forKey: У меня не было проблемы в Objective-C.

Спасибо за помощь!

[EDIT] Вот весь класс CurrencyRateStore:

class CurrencyRateStore { 

// MARK: Singleton 
class func sharedStore() -> CurrencyRateStore! { 
    struct Static { 
     static var instance: CurrencyRateStore? 
     static var token: dispatch_once_t = 0 
    } 

    dispatch_once(&Static.token) { 
     Static.instance = CurrencyRateStore() 
    } 

    return Static.instance! 
} 

// MARK: Properties 

/** Dictionary of currency rates used by the portfolio, presented like [ EURUSD=X : 1.3624 ] */ 
var dictionary = [String : Double]() 

/** Returns a sorted array of all the keys on the currency rates dictionary */ 
var allKeys: [String] { 
var keysArray = Array(dictionary.keys) 
    keysArray.sort {$0 < $1} 
    return keysArray 
} 

init() { 
    if let currencyRateDictionary: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithFile(currencyRateArchivePath) { 
     dictionary = currencyRateDictionary as [String : Double] 
    } 
} 

subscript(index: String) -> Double? { 
    get { 
     return dictionary[index] 
    } 
    set { 
     // FIXME: crashes when getting out of the app (Home button) and then relaunching it 
     // (ApplicationWillEnterForeground triggers updateStocks) 
      dictionary[index] = newValue! 
      println("CurrencyRateStore - updated rate for \(index) : \(newValue!)") 
    } 
} 


func deleteRateForKey(key: String) { 
    dictionary.removeValueForKey(key) 
} 


/** Removes all currency rates from the Currency rate store */ 
func deleteAllRates() 
{ 
    dictionary.removeAll() 
} 


// MARK: Archive items in CurrencyRateStore 
var currencyRateArchivePath: String { // Archive path 
var documentDirectories: Array = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true) 

    // Get the only document directory from that list 
    let documentDirectory: AnyObject = documentDirectories.first! 

    return documentDirectory.stringByAppendingPathComponent("currencyRates.archive") 
} 

func saveChanges()-> Bool 
{ 
    // return success or failure 
    return NSKeyedArchiver.archiveRootObject(dictionary, toFile: currencyRateArchivePath) 
} 

} 
+0

не могли бы вы опубликовать всю ошибку войти? может быть, может помочь – Antonio

+0

вы могли бы также поделиться некоторыми соответствующие части 'CurrencyRateStore'? по крайней мере одноплодной реализации, декларирование словаря собственности – Antonio

+0

Но нет журнала на EXC_BAD_ACCESS ... То есть, поток в навигаторе отладки? –

ответ

1

Это выглядит как проблема параллелизма.Быстрые словари не являются потокобезопасными, и использование их из одноэлементного устройства может привести к многочисленным проблемам чтения/записи.

Редактировать: Я уверен, что это реальный ответ, основанный на заданном дампе источника/отладки. Чтобы исправить то, что я написал, в частности, словари и массивы MUTABLE (а также NSMutableDictionary и NSMutableArray) не являются потокобезопасными, и возникают проблемы при использовании их в синглтонах, к которым обращаются из нескольких потоков, и это похоже на то, делает или позволяет другим частям кода делать.

У меня нет ссылки Apple, в которой обсуждается вопрос о безопасности потоков классов Swift, но я достаточно уверен в общих знаниях. Но в следующем учебном пособии по Grand Central Dispatch подробно обсуждается проблема и как ее решить с помощью GCD.

http://www.raywenderlich.com/79149/grand-central-dispatch-tutorial-swift-part-1

+1

Теперь это кажется интересным. Не могли бы вы подробнее рассказать о своем ответе? Почему вы думаете, что использование их из одноэлементного может привести к множественным проблемам чтения/записи? Где вы узнали, что словари Swift не являются потокобезопасными, и считаете ли вы, что NSDictionary? Большое спасибо! –

+0

Я думаю, что это действительно связано со словарями, потому что я много раз использую массивы в одиночных играх, и у меня никогда не было такой проблемы ... –

1

ошибка, а сама линия:

dictionary[index] = newValue! 

заставляет меня думать, что проблема newValue быть nil - и ошибка вызвана принудительной разворачиванием. Я бы предложил установить контрольную точку и проверить ее значение или иначе распечатать ее перед добавлением в dict.

Кроме того, не было бы плохой идеей, чтобы защитить это утверждение с дополнительным связыванием:

if let value = newValue { 
    dictionary[index] = value 
} 

, потому что, если тип значения не является обязательным, он может быть равен нулю.

+0

Я только что попробовал ваше предложение, но оно все еще падает. На самом деле, я уже проверил, что новое_значение не был равен нулю при отладке, но нет, он имеет следующее значение: описание печати из NEWVALUE: (?) Двойной новое_значение = 1.266 Спасибо в любом случае! –

1

Итак, в конце концов, я связался с технической поддержкой Apple. Они не смогли воспроизвести проблему.

Я думал, что, возможно, мне не нужно сохранять валютные курсы, потому что во время обновления кавычек функция будет проверять, какие курсы валют им нужны в любом случае, и при необходимости заполнить словарь. Итак, я деактивировал методы, которые я создал для сохранения CurrencyRateStore, и перезагрузить его снова NSKeyedUnarchiver. Видимо, крушение пропало!

+0

Для других людей, видящих это: я исправил эту проблему, изменив имя каталога хранилища - внезапно исчезла авария. – Carter

Смежные вопросы