【问题标题】:dealloc/deinit called early when using objc_setAssociatedObject in swift在 swift 中使用 objc_setAssociatedObject 时提前调用了 dealloc/deinit
【发布时间】:2014-10-08 02:43:07
【问题描述】:

似乎 objc_setAssociatedObject 导致对象被提前释放。

我按照here提到的方法设置关联。

import ObjectiveC

// Define a variable whose address we'll use as key.
// "let" doesn't work here.
var kSomeKey = "s"

…

func someFunc() {
    var value = MyOtherClass()
    objc_setAssociatedObject(target, &kSomeKey, value, UInt(OBJC_ASSOCIATION_RETAIN))

    let assocValue : AnyObject! = objc_getAssociatedObject(target, &kSomeKey)
}

这导致对象在 objc_setAssociatedObject 调用期间被释放。正如您在此堆栈跟踪中看到的那样。

[MyOtherClass dealloc]
_objc_object::sidetable_release(bool)
_object_set_associative_reference
MyApp.MyClass.someFunc()

我最初认为它可能与 swift 类有关,所以我也尝试了标准的 Objective-C 类,并在 objc_setAssociatedObject 调用期间调用了 deinit 或 dealloc。

让我更加困惑的是 objc_getAssociatedObject 似乎返回了一个有效的对象,我可以毫无错误地访问它的变量。

这是一个快速的错误还是我错误地使用了 objc_setAssociatedObject?

我正在使用 Xcode6 beta5 以防万一。

【问题讨论】:

  • 您确定没有为该键设置关联对象吗?看起来现有的 MyOtherClass 实例正在被新实例替换。旧实例已被释放,因为没有其他对它的引用。
  • @Darren 感谢您的帮助,事实证明这毕竟是问题所在。我错误地假设“目标”每次都不同,而在某些情况下,相同的“目标”为其设置了不同的值,导致先前设置的对象被释放。如果您想写下您的评论作为答案,我愿意接受。

标签: ios objective-c memory-management swift


【解决方案1】:

我猜你的代码甚至无法编译,因为你使用了两次“值”作为常量名。

这在 beta 6 中作为 AppDelegate 可以正常工作:

import ObjectiveC

var kSomeKey = "this_is_a_key"

class MyOtherClass {
    var foo = "bar"

    deinit {
        println("deinit")
    }
}

@UIApplicationMain
class AppDelegateTest: UIResponder, UIApplicationDelegate {

    func someFunc() {
        var value = MyOtherClass()
        objc_setAssociatedObject(self, &kSomeKey, value, UInt(OBJC_ASSOCIATION_RETAIN))

        let value2: AnyObject! = objc_getAssociatedObject(self, &kSomeKey)

        println("type of is \(_stdlib_getTypeName(value2))")

        let value3 = value2 as MyOtherClass

        println("other is " + value3.foo)

        println("end of someFunc()")
    }


    func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
        self.someFunc()

        return true
    }
}

我几乎没有改变任何东西,并且从未调用过 deinit 方法。

【讨论】:

  • 我已更新我的代码示例以消除编译错误。这是我自己的代码的审查版本。重复值变量名称是无意的。我很快会尝试在 beta6 中再次重现它。
猜你喜欢
  • 2016-01-11
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 2018-12-18
  • 2015-08-25
  • 2015-10-21
  • 2019-09-26
  • 1970-01-01
相关资源
最近更新 更多