objc_getAssociatedObject始终返回nil

时间:2018-02-11 10:45:01

标签: ios swift

我尝试使用关联对象向Timer的扩展添加属性,但函数objc_setAssociatedObject始终返回nil

Timer is a NSObject所以这应该有用。

代码:

extension Timer {
    private struct AssociatedKeys {
        static var counterAddress = "counter_address"
    }

    public var repeatCounter: Int {
        get {
            return objc_getAssociatedObject(self, AssociatedKeys.counterAddress) as? Int ?? 0
        }
        set {
            objc_setAssociatedObject(self,
                                     AssociatedKeys.counterAddress,
                                     newValue,
                                     .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

任何想法为什么这不起作用?

更多代码:

@nonobjc public class func new(every interval: TimeInterval, _ block: @escaping (Timer) -> Void) -> Timer {
    var timer: Timer!
    timer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + interval, interval, 0, 0) { _ in
        print("timer: \(timer.numberOfRepeats), : \(timer.repeatCounter), : \(timer)")
        if timer.numberOfRepeats > 0 {

            if timer.repeatCounter > timer.numberOfRepeats {

                timer.invalidate()
                return
            } else {

                timer.repeatCounter += 1
            }
        }

        block(timer)
    }
    return timer
}

所以一些问题是我没有使用相同的计时器对象。 还有一些问题:

  1. static let repeatCounterAddress = "repeat_counter_address"有时未初始化且字符串值为空。

  2. 有时我得到相同的关联值,有时则没有。

1 个答案:

答案 0 :(得分:4)

尝试以下(注意&符号):

extension Timer {
    private struct AssociatedKeys {
        static var counterAddress = "counter_address"
    }

    public var repeatCounter: Int {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.counterAddress) as? Int ?? 0
        }
        set {
            objc_setAssociatedObject(self,
                                     &AssociatedKeys.counterAddress,
                                     newValue,
                                     .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

始终确保将相同的地址作为key参数的值。如果您只使用字符串值,则对于objc_getAssociatedObjectobjc_setAssociatedObject的每次调用,其原始值可能会有所不同。

您可以使用以下代码进行检查:

func test(_ a: UnsafeRawPointer) {
    print("\(a)")
}

let a = "abc"

test(a)
test(a)
test(a)
test(a)

打印

0x00006040004427e0
0x00006040004427e0
0x0000608000052980
0x0000600000055c50
例如,

,不同的原始指针被解释为不同的关联对象。