NSSet'ten bir nesne almak


Yanıtlar:


140

Bir set için birkaç kullanım durumu vardır. Numaralandırabilir (örneğin ile enumerateObjectsUsingBlockveya NSFastEnumeration), containsObjectüyeliği test etmek için çağrı yapabilir , anyObjectbir üye almak için kullanabilir (rastgele değil) veya ile bir diziye (belirli bir sırayla) dönüştürebilirsiniz allObjects.

Kopyaları istemediğinizde, siparişi önemsemediğinizde ve hızlı üyelik testi istediğinizde bir set uygundur.


7
Ayrıca, sete bir member:mesaj göndererek bilinen bir nesneyi olası bir kopyadan da arayabilirsiniz . Geri dönerse nil, set geçtiğinize eşit bir nesne içermez; bir nesne işaretçisi döndürürse, döndürdüğü işaretçi zaten kümede bulunan nesnedir. Kümedeki nesneler uygulamak zorundadır hashve isEqual:bunun faydalı olması için.
Peter Hosey

Sanmıyorum @PeterHosey hash ihtiyaçları uygulanmak üzere; Bunu yaparsan çok daha hızlı giderdi.
fumoboy007

2
@ fumoboy007: Bir sette saklama veya sözlükte anahtar olarak kullanım için evet öyle. hashNSObject protokolündeki dokümantasyonundan : "İki nesne eşitse ( isEqual:yöntem tarafından belirlendiği üzere ), aynı hash değerine sahip olmaları gerekir." Şu anda, NSObject'in nesnenin kimliğini (adresini) uygulamaları hashve isEqual:kullanmaktadır. Geçersiz kılarsanız isEqual:, aynı olmayan ancak eşit olan nesnelerin olasılığını ayarlamış olursunuz - bu, siz de geçersiz hashkılmasanız bile farklı karmalara sahip olacaktır. Bu, eşit nesnelerin eşit karmalara sahip olması koşulunu ihlal eder.
Peter Hosey

1
@ fumoboy007: Bir karma tablonun nasıl çalıştığını düşünün: Kapta bir dizi kümeden oluşan bir dizi vardır ve bu nesnenin hangi bölümde olması gerektiğini belirlemek için gelen her nesnenin karmasını kullanır. Gibi aramalar için member:, kapsayıcı yalnızca bu kümeye bakar grup (bu nedenle, üyelik testinde kümeler dizilerden çok daha hızlıdır ve sözlükler, anahtar-değer aramasında paralel dizilerden çok daha hızlıdır). Aranan nesne yanlış hash'e sahipse, konteyner yanlış kovaya bakar ve bir eşleşme bulamaz.
Peter Hosey

@PeterHosey Oops… Yanlışlıkla varsayılan uygulamasının -[NSObject hash]0 olduğunu düşündüm. Bu çok şeyi açıklıyor. = S
fumoboy007

31

NSSet'in objectAtIndex yöntemi yoktur:

Tüm nesnelerden bir NSArray döndüren allObjects çağırmayı deneyin.


döndürülen dizinin sıralı olup olmadığı hakkında bir fikriniz var mı? diğer bir deyişle, "setByAddingObject" kullanarak kümeye nesne ekliyorsam ve "allObjects" kullandıysam? dizideki öğeler, nesneleri eklediğim sırayla sıralanır mı?
iosMentalist

sadece ortaya çıkan diziyi bir NSSortPredicate ile sıralayın ve iyi olacaksınız
Jason

Yalnızca belirli bir nesneyle ilgileniyorsanız, filteredSetUsingPredicate yaklaşımını daha iyi kullanın.
akw

17

İhtiyacınız olan nesneyi seçmek için bir tür benzersiz tanımlayıcınız varsa filteredSetUsingPredicate kullanmak mümkündür.

Önce koşulu oluşturun (nesnedeki benzersiz kimliğinizin "tanımlayıcı" olarak adlandırıldığını ve bunun bir NSString olduğunu varsayarak):

NSPredicate *myPredicate = [NSPredicate predicateWithFormat:@"identifier == %@", identifier];

Ve sonra yüklemi kullanarak nesneyi seçin:

NSObject *myChosenObject = [mySet filteredSetUsingPredicate:myPredicate].anyObject;

13

NSArray *myArray = [myNSSet allObjects];

MyObject *object = [myArray objectAtIndex:(NSUInteger *)]

NSUInteger'ı istediğiniz nesnenin diziniyle değiştirin.


1
Olmalıdır: MyObject * object = [myArray objectAtIndex: (NSUInteger *)]
John D.

8

Swift3 ve iOS10 için:

//your current set
let mySet : NSSet
//targetted index
let index : Int
//get object in set at index
let object = mySet.allObjects[index]

6

NSSet, bir nesnenin içinde olup olmadığını belirlemek için isEqual: yöntemini (bu kümeye koyduğunuz nesnelerin ek olarak karma yöntemini geçersiz kılması gerekir) kullanır.

Dolayısıyla, örneğin, benzersizliğini bir kimlik değeriyle tanımlayan bir veri modeliniz varsa (özelliğin:

@property NSUInteger objectID;

o zaman isEqual: as

- (BOOL)isEqual:(id)object
{
  return (self.objectID == [object objectID]);
}

ve hash uygulayabilirsiniz:

- (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
}

Ardından, bu kimliğe sahip bir nesne elde edebilirsiniz (ayrıca NSSet'te olup olmadığını kontrol edebilirsiniz):

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

Ama evet, bir NSSet'ten bir şey çıkarmanın tek yolu, ilk etapta benzersizliğini tanımlayan şeyi dikkate almaktır.

Daha hızlı olanı test etmedim, ancak numaralandırmayı kullanmaktan kaçınıyorum çünkü bu doğrusal olabilir, oysa üye: yöntemini kullanmak çok daha hızlı olurdu. NSArray yerine NSSet kullanımını tercih etmenin nedenlerinden biri de budur.



0

Çoğu zaman belirli bir nesneyi bir setten almayı umursamıyorsunuz. Bir setin bir nesne içerip içermediğini görmek için test etmeyi önemsiyorsunuz. Setler bunun için iyidir. Bir nesnenin bir koleksiyonda olup olmadığını görmek istediğinizde, dizilerden çok daha hızlıdır.

Hangi nesneyi aldığınızı umursamıyorsanız -anyObject, elinizi bir çantaya koymak ve bir şey kapmak gibi size setten bir nesne veren kullanın .

Dog *aDog = [dogs anyObject]; // dogs is an NSSet of Dog objects

Hangi nesneyi aldığınızla ilgileniyorsanız -member, size nesneyi geri veren hangisini kullanın veya sette değilse sıfırlayın. Çağırmadan önce nesneye sahip olmanız gerekir.

Dog *spot = [Dog dogWithName:@"Spot"];
// ...
Dog *aDog = [dogs member:spot]; // Returns the same object as above

İşte daha fazlasını anlamak için Xcode'da çalıştırabileceğiniz bazı kodlar

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);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.