NSDictionary 可能无法响应 NSMutableDictionary 对象上的 setObject:forKey
Posted
技术标签:
【中文标题】NSDictionary 可能无法响应 NSMutableDictionary 对象上的 setObject:forKey【英文标题】:NSDictionary may not respond to setObject:forKey on a NSMutableDictionary object 【发布时间】:2011-07-11 21:24:40 【问题描述】:我是 Xcode 新手,正在尝试这个小程序。
// BookStoreMine.h
// BookStore
#import <Cocoa/Cocoa.h>
#import "Book.h"
@interface BookStoreMine : NSObject
NSDictionary* mybookStore;
@property (retain) NSDictionary* myBookStore;
-(id)init;
-(void)printInventory;
-(BOOL)addBook:(Book *)newBook;
-(BOOL)removeBookWithTitle:(NSString *)whichTitle;
-(void)dealloc;
@end
// BookStoreMine.m
// BookStore
#import "BookStoreMine.h"
@implementation BookStoreMine
@synthesize myBookStore;
-(id)init
self = [super init];
if (self != nil)
myBookStore = [[NSMutableDictionary alloc] init];
return self;
-(BOOL)addBook:(Book *)newBook
**[myBookStore setObject:newBook forKey:newBook.title];**
return YES;
-(BOOL) removeBookWithTitle:(NSString *)whichTitle
if ([myBookStore objectForKey:whichTitle] != nil)
**[myBookStore removeObjectForKey:whichTitle];**
return YES;
return NO;
-(void)printInventory
Book *book;
for (NSString* key in myBookStore)
book = [myBookStore objectForKey:key];
NSLog(@" Title: %@",book.title);
NSLog(@" Author: %@",book.author);
NSLog(@" Description: %@",book.description);
NSLog(@"ID is:%@",book.ID);
-(void)dealloc
self.myBookStore = nil;
[super dealloc];
@end
我在 myBookStore 上使用 setObject 方法以及在 myBookStore 对象上使用 removeObject 方法时收到警告。警告是“NSDictionary 可能无法响应 setObject:forKey 或 removeObject:forKey。当我使用的对象是 NSMutableDictionary 时,为什么我会收到与 NSDictionary 相关的警告?如何摆脱警告?(PS:程序编译运行没有任何问题)
【问题讨论】:
【参考方案1】:在运行时,您将myBookStore
对象设置为NSMutableDictionary
的一个实例。
在编译时,它仍然被声明为NSDictionary
,它不会响应设置或删除的消息。
如果您将变量声明为NSMutableDictionary
,则警告将消失。
【讨论】:
【参考方案2】:改变这两行:
NSDictionary* mybookStore;
@property (retain) NSDictionary* myBookStore;
看起来像这样:
NSMutableDictionary* mybookStore;
@property (retain) NSMutableDictionary* myBookStore;
Xcode 在确定 ivars 实现哪些方法时会查看它们的声明,以及是否应该始终将 ivars 声明为它们将要成为的样子。
【讨论】:
谢谢,现在明白了!我想知道为什么编译器允许我将变量及其属性定义为 NSDictionary 并让我在运行时将其定义为 NSMutableDictionary。 有时您可能需要将变量声明为一个类,然后在实际使用时将其作为子类。例如,如果您有一个可能是几个特定子类之一的视图控制器。对于那些时候,您可以只转换变量。【参考方案3】:您已将 mybookStore
声明为 NSDictionary。因此编译器认为它是NSDictionary
。 NSMutableDictionary 在运行时分配给它的事实并没有改变这一点。
您可能希望将@interface
中的声明更改为NSMutableDictionary
(尽管在@property
中将其返回为不可变仍然有意义,因为您不希望外部参与者认为他们拥有修改它的权利)。
【讨论】:
【参考方案4】:您的意图似乎是为您的班级用户提供immutable
NSDictionary
,以便他们无法修改您在内部使用的 ivar。从你声明了这个方法的事实来看
-(void)printInventory;
我猜想你班级的用户根本不需要看到NSDictionary
ivar。如果是这种情况,那么我通常所做的就是根本不声明我将在头文件内部使用的 ivar。这具有使我的类的用户使用提供的 getter/setter 的效果,并且我可以随时更改内部数据结构。为此,您需要使用类扩展来添加额外的 ivar。
这将使您的类看起来像这样 - 请注意您的头文件(公共 API)看起来多么干净:
// BookStoreMine.h
// BookStore
#import <Cocoa/Cocoa.h>
#import "Book.h"
@interface BookStoreMine : NSObject
- (void)printInventory;
- (BOOL)addBook:(Book *)newBook;
- (BOOL)removeBookWithTitle:(NSString *)whichTitle;
@end
// BookStoreMine.m
// BookStore
#import "BookStoreMine.h"
@interface BookStoreMine ()
@property (retain) NSMutableDictionary* myBookStore;
@end
@implementation BookStoreMine
@synthesize myBookStore;
- (id)init
self = [super init];
if (self != nil)
myBookStore = [[NSMutableDictionary alloc] init];
return self;
- (BOOL)addBook:(Book *)newBook
[self.myBookStore setObject:newBook forKey:newBook.title];
return YES;
- (BOOL)removeBookWithTitle:(NSString *)whichTitle
if ([myBookStore objectForKey:whichTitle] != nil)
[self.myBookStore removeObjectForKey:whichTitle];
return YES;
return NO;
- (void)printInventory
Book *book;
for (NSString* key in self.myBookStore)
book = [myBookStore objectForKey:key];
NSLog(@" Title: %@",book.title);
NSLog(@" Author: %@",book.author);
NSLog(@" Description: %@",book.description);
NSLog(@"ID is:%@",book.ID);
- (void)dealloc
[myBookStore release];
[super dealloc];
@end
【讨论】:
以上是关于NSDictionary 可能无法响应 NSMutableDictionary 对象上的 setObject:forKey的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Swift 中将“__NSSingleObjectArrayI”类型的值转换为“NSDictionary”
如何在 NSDictionary 中访问本地 JSON 文件响应以在 UITableView 中显示?
无法分配“NSDictionary”类型的值?键入“字符串?”