为什么containsObject在NSMutableSet的NSSet副本上不起作用?

问题描述 投票:0回答:1

创建可变集的集副本,然后使(新)集副本的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()
ios objective-c nsstring nsset nsmutableset
1个回答
0
投票

要复制NSMutalbeSet实例,请使用initWithSet:copyItems:而不是copy

NSSet<NSString*> *newSet = [[NSSet alloc] initWithSet:self.mutableSet copyItems:YES];
© www.soinside.com 2019 - 2024. All rights reserved.