创建可变集的集副本,然后使(新)集副本的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()
要复制NSMutalbeSet
实例,请使用initWithSet:copyItems:
而不是copy
:
NSSet<NSString*> *newSet = [[NSSet alloc] initWithSet:self.mutableSet copyItems:YES];