我在创建可变集的集副本时遇到问题,然后对于(新)集副本的 containsObject 失败。例如:
NSString *sameID = @"XYZ";
然后在主线程/有时在不同的线程上:
[mutableSet addObject:sameID];
NSLog(@"adding Object: %@", sameID);
然后在后台线程上,总是在(我已经通过记录验证)添加了sameID之后:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
NSSet<NSString *> *newSet = self.mutableSet.copy;
if ([newSet containsObject:sameID]) {
// do stuff
}
});
看到有断点:
1. po [newSet containsObject:sameID] // returns NO
2. po [self.mutableSet containsObject:sameID] // returns YES
我已经测试了相同 ID 字符串没有额外或隐藏的空格。AFAIK containsObject 用于包含 NSString 的集合使用 isEqual 如果字符串具有不同的指针,这无关紧要,对吧?
编辑:一些附加信息:添加到 mutableSet 的 NSString 发生在不同的线程上,但总是在创建 newSet 副本之前发生。创建和检查 newSet 是在后台线程上完成的,这就是我复制 mutableSet 的原因(我在日志记录中看到这总是在向 mutableSet 添加字符串之后)。所以我在日志语句中看到字符串(sameID)已添加到 mutableSet,然后在后台线程上我将 mutableSet 复制为一个集合并快速检查该集合是否有相同的字符串(sameID),但它不存在。
Edit2:我已经测试了下面的代码并且它通过了,但是当我尝试实现与上述相同的解决方案时,它仍然具有相同的结果(mutableSet 包含字符串但 newSet 不包含)。
import XCTest
import Foundation
class CustomObj: NSObject {
let id: String
init(id: String) { self.id = id }
override func isEqual(_ object: Any?) -> Bool {
if let other = object as? CustomObj {
return self.id == other.id
} else {
return false
}
}
override var hash: Int {
return id.hashValue
}
}
func testSetStrings() {
let set = NSMutableSet(object: CustomObj(id: "String-1"))
let copySet: Set<CustomObj> = set.copy() as! Set<CustomObj>
let customObjForTest = CustomObj(id: "String-1")
XCTAssertTrue(set.contains(customObjForTest), "Does Not Contain")
XCTAssertTrue(copySet.contains(customObjForTest), "Copy Does Not Contain")
}
testSetStrings()