ObjectAtIndex: NSSet'ten olan bir nesneyi alamıyorsanız, nesneleri nasıl alırsınız?
ObjectAtIndex: NSSet'ten olan bir nesneyi alamıyorsanız, nesneleri nasıl alırsınız?
Yanıtlar:
Bir set için birkaç kullanım durumu vardır. Numaralandırabilir (örneğin ile enumerateObjectsUsingBlock
veya NSFastEnumeration), containsObject
üyeliği test etmek için çağrı yapabilir , anyObject
bir ü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.
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 hash
ve isEqual:
bunun faydalı olması için.
hash
ihtiyaçları uygulanmak üzere; Bunu yaparsan çok daha hızlı giderdi.
hash
NSObject 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ı hash
ve 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 hash
kılmasanız bile farklı karmalara sahip olacaktır. Bu, eşit nesnelerin eşit karmalara sahip olması koşulunu ihlal eder.
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.
-[NSObject hash]
0 olduğunu düşündüm. Bu çok şeyi açıklıyor. = S
NSSet'in objectAtIndex yöntemi yoktur:
Tüm nesnelerden bir NSArray döndüren allObjects çağırmayı deneyin.
İ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;
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]
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.
for (id currentElement in mySet)
{
// ** some actions with currentElement
}
Ç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);
}
[[nsSetObjects allObjects] objectAtIndex: anyInteger]