답변:
세트에 대한 몇 가지 사용 사례가 있습니다. 열거 (예 : enumerateObjectsUsingBlock
또는 NSFastEnumeration), containsObject
멤버십 테스트 호출 anyObject
, 멤버 가져 오기 (무작위 아님) 또는 다음을 사용하여 배열로 변환 (특정 순서 없음) 할 수 있습니다.allObjects
있습니다.
세트는 중복을 원하지 않고 주문에 신경 쓰지 않고 빠른 멤버십 테스트를 원할 때 적합합니다.
member:
메시지를 보내 잠재적 중복으로 알려진 개체를 찾을 수도 있습니다 . 을 반환 nil
하면 세트에는 전달한 것과 동일한 객체가 포함되지 않습니다. 객체 포인터를 반환하면 반환하는 포인터는 이미 세트에있는 객체에 대한 것입니다. 세트의 객체가 구현해야 hash
하고 isEqual:
이 유용 할 수 있습니다.
hash
필요 가 없다고 생각 합니다 . 그렇게한다면 훨씬 더 빨라질 것입니다.
hash
NSObject 프로토콜 의 문서 에서 : "두 개체가 동일한 경우 ( isEqual:
메서드에 의해 결정됨) 두 개체는 동일한 해시 값을 가져야합니다." 현재의 NSObject의의 구현 hash
및 isEqual:
개체의 ID (주소)를 사용합니다. 를 재정의 isEqual:
하면 동일하지는 않지만 동일한 개체의 가능성을 설정하는 것입니다.이 개체도 재정의하지 않으면 hash
다른 해시를 갖게됩니다. 이는 동일한 객체에 동일한 해시가 있어야한다는 요구 사항을 위반합니다.
member:
경우 컨테이너는 해당 버킷 만 찾습니다. 버킷 (이것이 멤버십 테스트에서 집합이 배열보다 훨씬 빠르고 키-값 조회에서 사전이 병렬 배열보다 훨씬 빠른 이유입니다). 찾고있는 객체에 잘못된 해시가있는 경우 컨테이너는 잘못된 버킷을보고 일치 항목을 찾지 못합니다.
-[NSObject hash]
이 0 이라고 잘못 생각했습니다 . 그게 많은 것을 설명합니다. = S
NSSet에는 objectAtIndex 메소드가 없습니다.
모든 객체의 NSArray를 반환하는 allObjects를 호출 해보십시오.
필요한 개체를 선택할 수있는 고유 식별자가있는 경우에는 filtersSetUsingPredicate를 사용할 수 있습니다.
먼저 술어를 작성하십시오 (객체의 고유 ID가 "식별자"이고 NSString이라고 가정).
NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];
그런 다음 조건자를 사용하여 개체를 선택합니다.
NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;
Swift3 및 iOS10의 경우 :
//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]
NSSet은 isEqual : 메소드를 사용합니다 (해시 메소드와 함께 해당 세트에 넣은 객체가 오버라이드해야 함). 객체가 그 안에 있는지 확인합니다.
예를 들어 ID 값으로 고유성을 정의하는 데이터 모델이있는 경우 (예 : 속성은 다음과 같습니다.
@property NSUInteger objectID;
그런 다음 isEqual : as
- (BOOL)isEqual:(id)object
{
return (self.objectID == [object objectID]);
}
해시를 구현할 수 있습니다.
- (NSUInteger)hash
{
return self.objectID; // to be honest, I just do what Apple tells me to here
// because I've forgotten how Sets are implemented under the hood
}
그런 다음 다음을 사용하여 해당 ID를 가진 객체를 가져올 수 있습니다 (NSSet에 있는지 확인).
MyObject *testObject = [[MyObject alloc] init];
testObject.objectID = 5; // for example.
// I presume your object has more properties which you don't need to set here
// because it's objectID that defines uniqueness (see isEqual: above)
MyObject *existingObject = [mySet member: testObject];
// now you've either got it or existingObject is nil
그러나 네, NSSet에서 무언가를 얻는 유일한 방법은 처음에 그것의 고유성을 정의하는 것을 고려하는 것입니다.
더 빠른 것을 테스트하지는 않았지만, 열거 형은 선형적일 수 있지만 member : 메서드를 사용하는 것이 훨씬 빠르기 때문에 사용하지 않습니다. 이것이 NSArray 대신 NSSet 사용을 선호하는 이유 중 하나입니다.
for (id currentElement in mySet)
{
// ** some actions with currentElement
}
대부분의 경우 세트에서 하나의 특정 개체를 가져 오는 데 관심이 없습니다. 세트에 객체가 포함되어 있는지 테스트하는 데 관심이 있습니다. 그것이 세트가 좋은 이유입니다. 객체가 컬렉션에 있는지 확인하려는 경우 집합이 배열보다 훨씬 빠릅니다.
어떤 물건을 얻을지 신경 쓰지 않는다면 -anyObject
가방에 손을 넣고 무언가를 잡는 것과 같이 세트에서 하나의 물건 만주는 것을 사용하십시오.
Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects
어떤 객체를 얻는 지 신경 -member
쓰면 객체를 돌려주는 사용 을 사용 하거나 세트에 없으면 nil을 사용하십시오. 호출하기 전에 이미 개체가 있어야합니다.
Dog *spot = [Dog dogWithName:@"Spot"];
// ...
Dog *aDog = [dogs member:spot]; // Returns the same object as above
더 많은 것을 이해하기 위해 Xcode에서 실행할 수있는 코드는 다음과 같습니다.
NSString *one = @"One";
NSString *two = @"Two";
NSString *three = @"Three";
NSSet *set = [NSSet setWithObjects:one, two, three, nil];
// Can't use Objective-C literals to create a set.
// Incompatible pointer types initializing 'NSSet *' with an expression of type 'NSArray *'
// NSSet *set = @[one, two, three];
NSLog(@"Set: %@", set);
// Prints looking just like an array but is actually not in any order
//Set: {(
// One,
// Two,
// Three
// )}
// Get a random object
NSString *random = [set anyObject];
NSLog(@"Random: %@", random); // Random: One
// Iterate through objects. Again, although it prints in order, the order is a lie
for (NSString *aString in set) {
NSLog(@"A String: %@", aString);
}
// Get an array from the set
NSArray *array = [set allObjects];
NSLog(@"Array: %@", array);
// Check for an object
if ([set containsObject:two]) {
NSLog(@"Set contains two");
}
// Check whether a set contains an object and return that object if it does (nil if not)
NSString *aTwo = [set member:two];
if (aTwo) {
NSLog(@"Set contains: %@", aTwo);
}
[[nsSetObjects allObjects] objectAtIndex: anyInteger]