NSDictionary可能不响应NSMutableDictionary对象上的setObject:forKey

时间:2011-07-11 21:24:41

标签: iphone xcode nsdictionary

我是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:程序编译并运行没有任何问题)

4 个答案:

答案 0 :(得分:6)

运行时,您将myBookStore对象设置为NSMutableDictionary的实例。

编译时,它仍然被声明为NSDictionary,它不会响应设置或删除的消息。

如果您将变量声明为NSMutableDictionary,警告就会消失。

答案 1 :(得分:5)

更改这两行:

NSDictionary* mybookStore;

@property (retain) NSDictionary* myBookStore;

看起来像这样:

NSMutableDictionary* mybookStore;

@property (retain) NSMutableDictionary* myBookStore;

Xcode在确定它们实现的方法时会查看ivars的声明,以及是否应该始终将ivars声明为它们将会是什么样的。

答案 2 :(得分:4)

您已将mybookStore声明为NSDictionary。因此编译器认为它是NSDictionary。在运行时为其分配NSMutableDictionary的事实不会改变它。

您可能希望将@interface中的声明更改为NSMutableDictionary(尽管仍然有必要将其作为@property中的不可变项返回,因为您不需要外部演员认为他们有权修改它。)

答案 3 :(得分:2)

您的意图似乎是为了让您的班级用户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