草庐IT

Swift - 访问单例字典导致 EXC_BAD_ACCESS

coder 2023-07-17 原文

我有一个管理简单股票投资组合的应用程序。除其他外,它在字典中记录了所需的汇率,如下所示: [ 欧元兑美元=X : 1.267548 ] 这个字典是一个名为 CurrencyRateStore 的单例的字典属性。

更新股票报价时,它会检查更新的汇率并使用以下代码更新字典:

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!)")
    }
}

应用首次启动时,运行良好。 但是如果我退出应用程序(使用主页按钮)然后重新启动它,货币汇率会再次更新,但这一次,我在行中得到 EXC_BAD_ACCESS

dictionary[index] = newValue!

截图如下:

[编辑] 这是调试导航器中的线程:

我尝试更新不带下标的字典,如下所示:

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

但没有更多的成功。如果我使用函数 updateValue:forKey: 我在 Objective-C 中没有问题。

感谢您的帮助!

[编辑] 这是整个类 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)
}

}

最佳答案

在我看来这像是一个并发问题。 Swift 字典不是线程安全的,从单例中使用它们会导致多个读取器/写入器问题。

编辑:我很确定这是真正的答案,基于给定的源代码/调试转储。为了更正我写的内容,特别是 MUTABLE 字典和数组(以及 NSMutableDictionary 和 NSMutableArray)不是线程安全的,在从多个线程访问的单例中使用它们时会出现问题,这似乎是示例源代码的内容正在执行或启用代码的其他部分执行。

我没有讨论 Swift 集合类线程安全的 Apple 链接,但我很确定这是常识。但是下面关于 Grand Central Dispatch 的教程深入讨论了这个问题以及如何使用 GCD 解决它。

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

关于Swift - 访问单例字典导致 EXC_BAD_ACCESS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26515968/

有关Swift - 访问单例字典导致 EXC_BAD_ACCESS的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  3. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  4. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  5. 微信小程序通过字典表匹配对应数据 - 2

    前言一般来说,前端根据后台返回code码展示对应内容只需要在前台判断code值展示对应的内容即可,但要是匹配的code码比较多或者多个页面用到时,为了便于后期维护,后台就会使用字典表让前端匹配,下面我将在微信小程序中通过wxs的方法实现这个操作。为什么要使用wxs?{{method(a,b)}}可以看到,上述代码是一个调用方法传值的操作,在vue中很常见,多用于数据之间的转换,但由于微信小程序诸多限制的原因,你并不能优雅的这样操作,可能有人会说,为什么不用if判断实现呢?但是if判断的局限性在于如果存在数据量过大时,大量重复性操作和if判断会让你的代码显得异常冗余。wxswxs相当于是一个独立

  6. Ruby 守护进程导致 ActiveRecord 记录器 IOError - 2

    我目前正在用Ruby编写一个项目,它使用ActiveRecordgem进行数据库交互,我正在尝试使用ActiveRecord::Base.logger记录所有数据库事件具有以下代码的属性ActiveRecord::Base.logger=Logger.new(File.open('logs/database.log','a'))这适用于迁移等(出于某种原因似乎需要启用日志记录,因为它在禁用时会出现NilClass错误)但是当我尝试运行包含调用ActiveRecord对象的线程守护程序的项目时脚本失败并出现以下错误/System/Library/Frameworks/Ruby.frame

  7. ruby - 有没有办法从 ruby​​ case 语句中访问表达式? - 2

    我想从then子句中访问c​​ase语句表达式,即food="cheese"casefoodwhen"dip"then"carrotsticks"when"cheese"then"#{expr}crackers"else"mayo"end在这种情况下,expr是食物的当前值(value)。在这种情况下,我知道,我可以简单地访问变量food,但是在某些情况下,该值可能无法再访问(array.shift等)。除了将expr移出到局部变量然后访问它之外,是否有直接访问caseexpr值的方法?罗亚附注我知道这个具体示例很简单,只是一个示例场景。 最佳答案

  8. ruby - 从外部访问类的实例变量 - 2

    我理解(我认为)Ruby中类变量和类的实例变量之间的区别。我想知道如何从该类外部访问该类的实例变量。从内部(即在类方法中而不是实例方法中),它可以直接访问,但是从外部,有没有办法做MyClass.class.[@$#]variablename?我没有任何具体原因要这样做,只是学习Ruby并想知道是否可行。 最佳答案 classMyClass@my_class_instance_var="foo"class上述yield:>>foo我相信Arkku演示了如何从类外部访问类变量(@@),而不是类实例变量(@)。我从这篇文章中提取了上述内

  9. ruby-on-rails - 使用 HTTP.get_response 检索 Facebook 访问 token 时出现 Rails EOF 错误 - 2

    我试图在我的网站上实现使用Facebook登录功能,但在尝试从Facebook取回访问token时遇到障碍。这是我的代码:ifparams[:error_reason]=="user_denied"thenflash[:error]="TologinwithFacebook,youmustclick'Allow'toletthesiteaccessyourinformation"redirect_to:loginelsifparams[:code]thentoken_uri=URI.parse("https://graph.facebook.com/oauth/access_token

  10. ruby - 从另一个私有(private)方法中使用 self.xxx() 调用私有(private)方法 xxx,导致错误 "private method ` xxx' called” - 2

    我正在尝试获得良好的Ruby编码风格。为防止意外调用具有相同名称的局部变量,我总是在适当的地方使用self.。但是现在我偶然发现了这个:classMyClass上面的代码导致错误privatemethodsanitize_namecalled但是当删除self.并仅使用sanitize_name时,它会起作用。这是为什么? 最佳答案 发生这种情况是因为无法使用显式接收器调用私有(private)方法,并且说self.sanitize_name是显式指定应该接收sanitize_name的对象(self),而不是依赖于隐式接收器(也是

随机推荐