【问题标题】:NSDictionary may not respond to setObject:forKey on a NSMutableDictionary objectNSDictionary 可能无法响应 NSMutableDictionary 对象上的 setObject:forKey
【发布时间】: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:程序编译运行没有任何问题)

【问题讨论】:

    标签: iphone xcode nsdictionary


    【解决方案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
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-11-17
          相关资源
          最近更新 更多