NSDictionary может не отвечать на setObject: forKey для объекта NSMutableDictionary - PullRequest
5 голосов
/ 12 июля 2011

Я новичок в 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

Я получаю предупреждения в строках, где я использую метод setObject в myBookStore, а также когда я использую метод removeObject в myBookStoreобъект.Предупреждение: «NSDictionary может не отвечать на setObject: forKey или removeObject: forKey. Почему я получаю предупреждение, связанное с NSDictionary, когда объект, который я использую, является NSMutableDictionary? Как мне избавиться от предупреждения? (PS: программакомпилируется и запускается без проблем)

Ответы [ 4 ]

6 голосов
/ 12 июля 2011

В время выполнения вы устанавливаете объект myBookStore как экземпляр NSMutableDictionary.

В время компиляции , он по-прежнему объявлен как NSDictionary, который не отвечает на сообщения для установки или удаления.

Если вы объявите переменную как NSMutableDictionary, предупреждения исчезнут.

5 голосов
/ 12 июля 2011

Измените эти две строки:

NSDictionary* mybookStore;

@property (retain) NSDictionary* myBookStore;

чтобы выглядеть так:

NSMutableDictionary* mybookStore;

@property (retain) NSMutableDictionary* myBookStore;

Xcode просматривает объявления ivars при определении того, какие методы они реализуют, и если вы всегда должны объявлять ivars как то, чем они будут.

4 голосов
/ 12 июля 2011

Вы объявили mybookStore как NSDictionary. Поэтому компилятор считает, что это NSDictionary. Тот факт, что NSMutableDictionary назначается ему во время выполнения, не меняет этого.

Возможно, вы хотите изменить объявление в вашем @interface на NSMutableDictionary (хотя все еще имеет смысл возвращать его неизменным в вашем @property, поскольку вы не хотите, чтобы внешние субъекты думали, что у них есть право изменять его).

2 голосов
/ 12 июля 2011

Может показаться, что вы намереваетесь дать пользователю вашего класса immutable NSDictionary, чтобы он не мог модифицировать ивара, который вы используете внутри себя.Судя по тому, что у вас объявлен этот метод

-(void)printInventory;

, я бы предположил, что на самом деле пользователю вашего класса вообще не нужен ивар NSDictionary.Если это так, то, что я обычно делаю, это не объявляю ivar, который я вообще буду использовать внутри заголовочного файла.Это приводит к тому, что пользователь моего класса использует предоставляемые методы получения / установки, и я могу изменить внутреннюю структуру данных в любое время.Для достижения этого вам нужно будет использовать расширение класса, чтобы добавить дополнительный 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
...