NSDictionary may not respond to setObject:forKey on a NSMutableDictionary object
I am new to Xcode and I am trying out this small program.
// 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
I get warnings on the lines where I use setObject method on myBookStore and also when I use the removeObject method on the myBookStore object. The warning is "NSDictionary may not respond to setObject:forKey or removeObject:forKey. Why am I getting a warning related to NSDictionary when the object I am using is a NSMutableDictionary? How do I get rid of the warning? (PS: Th开发者_运维问答e program compiles and runs without any problem)
At runtime you are setting the myBookStore
object to be an instance of NSMutableDictionary
.
At compile time, it's still declared as an NSDictionary
, which doesn't respond to the messages for set or remove.
If you declare the variable as an NSMutableDictionary
, the warnings will go away.
Change these two lines:
NSDictionary* mybookStore;
@property (retain) NSDictionary* myBookStore;
to look like this:
NSMutableDictionary* mybookStore;
@property (retain) NSMutableDictionary* myBookStore;
Xcode is looking at the declarations of ivars when determining what methods they implement, and if you should always declare ivars as what they are going to be be.
You've declared mybookStore
as an NSDictionary. The compiler therefore believes it to be an NSDictionary
. The fact that an NSMutableDictionary is assigned to it at runtime doesn't alter that.
Probably you want to change the declaration within your @interface
to an NSMutableDictionary
(though it still makes sense to return it as immutable in your @property
, as you don't want external actors to think they have the right to modify it).
It would appear that your intention is to give the user of your class an immutable
NSDictionary
so they cannot modify the ivar you are using internally. Judging by the fact you have this method declared
-(void)printInventory;
I would guess that really the user of your class does not need to see the NSDictionary
ivar at all. If this is the case then what I normally do is not declare the ivar that I will use internally in the header file at all. This has the effect of making the user of my class use the getters/setters provided and I can change the internal data structure anytime I want. To achieve this you will need to use a class extension to add the additional ivar.
This will make your class look like this - notice how much cleaner your header file (public API) looks:
// 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
精彩评论