2012-02-13 34 views
7

有沒有一種方法通過點符號來訪問這樣的NSDictionary中的鍵的值?通過點符號訪問NSDictionary?

NSDictionary *returnVal = [NSDictionary dictionaryWithObjectsAndKeys:@"Saturn", @"name", @"Gas Giant", @"type", nil]; 
NSLog(@"VALUE: %@", [returnVal valueForKey:@"name"]); // This is how I am doing it now. 
+0

給我幾分鐘,我會做一些讓你使用點符號使用類別。 – 2012-02-13 16:59:50

+4

@ RichardJ.RossIII我不認爲你應該回答一個類別。它展示了一些Obj-C的功能,但這對於這一點來說是非常糟糕的做法。也許建議一個模型對象是'NSObject'的一個子類將是一個更好的方法。 – 2012-02-13 17:03:08

+1

我懷疑你可以做一些覆蓋' - (id)valueForUndefinedKey:'因爲編譯器會拒絕點... – JustSid 2012-02-13 17:04:51

回答

1

不,你這樣做是正確的。在iOS世界中,通常正確的方法是唯一的方法。 :)

如果你真的想要點符號(和其他你用類型對象得到的好東西),你將不得不將字典表示填充到一個對象中。最常見的是我的界面如下所示:

@interface FooBar : NSObject { 
    NSString *someData; 
    int someNumber; 
} 

@property (nonatomic, copy) NSString *someData; 
@property (nonatomic, assign) int someNumber; 

+ (FooBar *)FooBarFromDictionary:(NSDictionary *)dataDict; 

@end 

執行應該清楚。那麼你可以

FooBar *fb = [FooBar FooBarFromDictionary:data]; 
NSLog(@"fb.someData = %@", fb.someData); 
+0

不是技術上。你可以用塊和類別做一些非常瘋狂的東西,看看我的答案。 – 2012-02-13 17:05:10

1

不,我不這麼認爲。

從參考手冊。

Accessing Keys and Values 
– allKeys 
– allKeysForObject: 
– allValues 
– getObjects:andKeys: 
– objectForKey: 
– objectsForKeys:notFoundMarker: 
– valueForKey: 

這被列爲訪問鍵和值的唯一方法。所以你做得很好。

如果密鑰是公共屬性並且可讀性,您將可以訪問它。

6

沒有爲NSDictionary沒有點語法,但應該考慮使用的objectForKey:代替valueForKey:

Difference between objectForKey and valueForKey?

+0

謝謝,我會這樣做,我想知道有什麼不同。感謝您的鏈接。 – fuzzygoat 2012-02-13 17:03:44

+0

+1這個答案比我的答案更簡潔,所以我會刪除我的這個。 – 2012-02-13 17:35:19

+0

@fuzzygoat沒問題,希望它有幫助。 – kevboh 2012-02-13 21:55:52

1

你提到的訪問字典元素的方式是理想的方式(使用鍵)。 如果你想別的做的事,可能是你現在可以使用這個數組以及可以執行的任務使用 -

NSArray *allValues = [returnVal allValues]; 

。 如果你想要某些具體的東西,那就提一下,可能是因爲可以有其他的方式。

也作爲NSDictionary類將不會有任何定義的屬性,所以點符號是不可能的。

0

從技術上講,你可以做這樣的事情:

typedef id (^valueBlock)(id); 
@interface NSDictionary(dotNotationAddons) 

@property(nonatomic, readonly) valueBlock value; 

@end 

@implementation NSDictionary(dotNotationAddons) 

-(valueBlock) value 
{ 
    return [[^(id key) { 
     return [self objectForKey:key]; 
    } copy] autorelease]; 
} 

@end 

int main (int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"One", @"2", @"Two", @"3", @"Three", @"4", @"Four", nil]; 

     id value = dictionary.value(@"One"); 

     NSLog(@"%@", value); 
    } 


    return 0; 
} 

我不知道這是否是你所尋找的,但我希望它能幫助!

+0

我不明白爲什麼有人會誠實地投票。它回答了OP詢問的內容,我如何使用點符號訪問字典。這允許它。 – 2012-02-13 17:09:58

+2

這很有趣,但它與@ fuzzygoat的問題有什麼關係? – benzado 2012-02-13 17:10:20

+0

@benzado因爲它可以讓他使用點符號的NSDictionary,這是他想要的? – 2012-02-13 17:10:54

5

不是,不。

點符號是調用具有該選擇器名稱的方法的簡寫方式。換句話說,這...

NSLog(@"Hello, %@", foo.bar.name); 

...是一樣的,因爲這...

NSLog(@"Hello, %@", [[foo bar] name]); 

當我說「相同」,我的意思是,他們被編譯成相同的代碼。這只是語法糖。

一個普通的NSDictionary不會這樣。你可以排序的假貨與核心價值編碼,它可以讓你打電話valueForKeyPath得到這樣的特性:

NSLog(@"Hello, %@", [foo valueForKeyPath:@"bar.name"]); 

如果你真的希望能夠寫foo.bar.name在你的代碼,但是,你必須制定一個覆蓋forwardInvocation:的自定義類;這可以讓你捕捉一個未知的消息給一個對象,並且除了拋出一個錯誤之外還可以用它來做其他事情在這種情況下,您可以將未知選擇器更改爲它所包含的NSDictionary實例的查找。

但即使你這樣做,編譯器可能仍然會生成警告,除非你做出聲明這些屬性名稱存在的頭文件。

3

我同意使用objectForKey:或類似方法訪問NSDictionary的大部分答案。但是,可以允許點符號訪問NSDictionary,並且出於學習目的,這可能對某人有意思。另外,例如,當您通過AFNetworking檢索大型JSON字典時,此方法可以簡化代碼的訪問和可讀性。

這是我的解決方案:

DictionaryProperties.h:(類包裹的NSDictionary的屬性訪問)

@interface DictionaryProperties : NSObject{ 
    NSMutableDictionary* _backingDict; 
} 

@property (nonatomic, strong) NSMutableDictionary* backingDict; 

+ (DictionaryProperties*) allocWithDictionary:(NSDictionary*)dict; 

@end 

DictionaryProperties.m:

#import "DictionaryProperties.h" 

@implementation DictionaryProperties 

@synthesize backingDict = _backingDict; 

- (id) initWithDictionary:(NSDictionary*)dict { 
    if (self) { 
     if ([dict isKindOfClass:[NSMutableDictionary class]]) { 
      self.backingDict = (id)dict; 
     } else { 
      self.backingDict = [[NSMutableDictionary alloc] initWithDictionary:dict]; 
     } 
    } 
    return self; 
} 
+ (DictionaryProperties*) allocWithDictionary:(NSDictionary*)dict { 
    return [[DictionaryProperties alloc] initWithDictionary:dict]; 
} 


- (void)forwardInvocation:(NSInvocation *)invocation 
{ 
    NSString* key = NSStringFromSelector(invocation.selector); 
    invocation.selector = @selector(objectForKey:); 
    [invocation setArgument:&key atIndex:2]; 

    if ([self.backingDict objectForKey:key]) { 
     [invocation invokeWithTarget:self.backingDict]; 
    } else { 
     [self doesNotRecognizeSelector:invocation.selector]; 
    } 
} 

- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{ 
    return [self.backingDict methodSignatureForSelector:@selector(objectForKey:)]; 

} 
@end 

ExampleDictContent.h:(類宣佈字典裏面有什麼)

#import "DictionaryProperties.h" 

@interface ExampleDictContent : DictionaryProperties 

@property (strong, nonatomic) NSString* someData; 
@property (strong, nonatomic) NSString* someOtherData; 

@end 

@implementation ExampleDictContent 
@end 

用法:(一本字典的簡單聲明,包裝和屬性訪問的分配)

#import "ExampleDictContent.h" 

NSDictionary* d = [NSDictionary dictionaryWithObjects:NSArray arrayWithObjects:@"someData content", @"someOtherData content", nil 
               forKeys:NSArray arrayWithObjects:@"someData", @"someOtherData", nil]; 

ExampleDictContent* dictWProps = [ExampleDictContent allocWithDictionary:d]; 

NSLog(dictWProps.someData); 
NSLog(dictWProps.someData); 

這將打印:

someData content 
someOtherData content 

所以基本上DictionaryProperties作品用於訪問NSDictionary一個門面。它使用forwardInvocationget-property方法調用轉換爲字典上的getObjectForKey:調用。我喜歡它的是,它允許在字典上自動完成,並允許我明確聲明我想訪問的密鑰(在ExampleDictContent.h文件中)。請注意,此解決方案不允許對這些屬性進行寫入訪問,但可以按照以下鏈接所示添加該解決方案。

該解決方案部分受到karstenlitsche's solution的啓發。主要區別在於此解決方案基於子類而不是類別。

+0

[可下載\ [h | m \]文件](https://gist.github.com/warpling/829e93a1357e9ef7f282):) – Warpling 2015-04-02 20:04:48