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