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”

无法保存 AFNetworking 响应对象

如何在 NSDictionary 中访问本地 JSON 文件响应以在 UITableView 中显示?

无法分配“NSDictionary”类型的值?键入“字符串?”

无法将 JSONValue 写入 NSDictionary - JSON 框架不起作用

无法将“__NSSingleObjectArrayI”类型的值转换为“NSDictionary”