Swift 3.0: "objc_setAssociatedObject"问题

3
import UIKit
import ObjectiveC

var SubRowObjectKey: String = "subRow"
extension IndexPath {

    var subRow: Int {
        get {
            let subRowObj = objc_getAssociatedObject(self, &SubRowObjectKey)
        
            if subRowObj != nil {
                return (subRowObj as! Int)
            }
        
            return 0
        }
        set {
            let subRowObj = (newValue as NSInteger)
            objc_setAssociatedObject(self, &SubRowObjectKey, subRowObj, .OBJC_ASSOCIATION_RETAIN)
        
        }
    }

    static func indexPathForSubRow(_ subRow: NSInteger, inRow row: NSInteger, inSection section: NSInteger) -> IndexPath {
    
        var indexPath = IndexPath(row: row, section: section)
        indexPath.subRow = (subRow as Int)
        print(subRow)
        print(indexPath.subRow)
        return indexPath
    }
}

let indexPath = IndexPath.indexPathForSubRow(5, inRow: 1, inSection: 2)
print(indexPath.subRow)

enter image description here

  • 在静态函数indexPathForSubRow中,'subRow'的数量为5(附图中第30行)

  • 但是将subRow赋值给indexPath.subRow后,'indexPath.subRow'的数量为0,而不是5(附图中第29和31行)

  • 在Xcode版本8.2.1和Swift 3.0中进行了测试

    任何帮助都将不胜感激。


请在您的问题中发布实际代码。这样更容易阅读和参考。 - rmaddy
@rmaddy 发布的代码 - Rahul
1
请注意,这并不需要使用关联对象。IndexPath已经支持任意数量的索引。rowsection只是方便访问索引0和1处的值的属性。只需将您的subRow存储在索引路径的索引2处即可。 - rmaddy
2个回答

3

IndexPath是一个结构体,不支持关联对象。你可以通过直接尝试读取设置的对象来轻松检查它:

set {
    let subRowObj = (newValue as NSInteger)
    objc_setAssociatedObject(self, &SubRowObjectKey, subRowObj, .OBJC_ASSOCIATION_RETAIN)
    let subRowObj2 = objc_getAssociatedObject(self, &SubRowObjectKey)
    print(subRowObj2 ?? "nil") // prints "nil"
}

即使在setter中的代码“本来可以工作”,整个结构仍然不成立:由于在传输/赋值时(至少通过写入复制机制进行修改),结构体是被复制的,因此您的相关对象将不会包含在该副本中,您最终将失去这些信息。 尽管如此,您可以扩展NSIndexPath而不是扩展IndexPath,这样就可以正常工作--但我想这不是您想要的,因为您希望影响从表视图获取的IndexPath...

0

基于maddy的回答,这是我扩展的IndexPath,增加了subRow属性。

extension IndexPath {

    init(subRow: Int, row: Int, section: Int) {
        self.init(indexes: [IndexPath.Element(section), IndexPath.Element(row), IndexPath.Element(subRow)])
    }

    var subRow: Int {
        get { return self[index(at: 2)] }
        set { self[index(at: 2)] = newValue }
    }

    var row: Int {
        get { return self[index(at: 1)] }
        set { self[index(at: 1)] = newValue }
    }

    var section: Int {
        get { return self[index(at: 0)] }
        set { self[index(at: 0)] = newValue }
    }

    private func index(at idx: Int) -> IndexPath.Index {
        return self.startIndex.advanced(by: idx)
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接