0

Я сделал класс. Это файл h.Почему эта авария?

// MyClass.h 
#import <Foundation/Foundation.h> 


@interface MyClass : NSObject <NSCoding> { 
    NSString *string1; 
    NSString *string2; 

} 
@property (nonatomic, retain) NSString *string1; 
@property (nonatomic, retain) NSString *string2; 

@end 

Это файл m.

// MyClass.m 
#import "MyClass.h" 


@implementation MyClass 
@synthesize string1, string2; 

- (void)encodeWithCoder:(NSCoder *)coder; 
{ 
    if (self = [super init]){ 
     [coder encodeObject:string1 forKey:@"string1"]; 
     [coder encodeObject:string2 forKey:@"string2"]; 
    } 

} 

- (id)initWithCoder:(NSCoder *)coder; 
{ 
    self = [[MyClass alloc] init]; 
    if (self != nil) 
    { 
     string1 = [coder decodeObjectForKey:@"string1"]; 
     string2 = [coder decodeObjectForKey:@"string2"]; 

    } 
    return self; 
} 

- (void)viewDidUnload { 
    self.string1 = nil; 
    self.string2 = nil; 
} 


- (void)dealloc { 
    [super dealloc]; 
    [string1 release]; 
    [string2 release]; 
} 


@end 

Я создал массив этих объектов, как это:

MyClass *object1 = [[MyClass alloc] init]; 
object1.string1 = @"object1 string1"; 
object1.string2 = @"string1 string2"; 
MyClass *object2 = [[MyClass alloc] init]; 
object2.string1 = @"object2 string1"; 
object2.string2 = @"object2 string2"; 
theArray = [[NSMutableArray alloc] initWithObjects:object1, object2, nil]; 

Тогда я сохранил массив как это:

[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:theArray] forKey:@"savedArray"]; 

Затем я загрузил массив с диска, как это.

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults]; 
    NSData *dataRepresentingSavedArray = [currentDefaults objectForKey:@"savedArray"]; 
    if (dataRepresentingSavedArray != nil) 
    { 
     NSArray *oldSavedArray = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedArray]; 
     if (oldSavedArray != nil) 
     { 
      theArray = [[NSMutableArray alloc] initWithArray:oldSavedArray]; 
     } 
     else { 

      theArray = [[NSMutableArray alloc] init]; 
     } 


    } 

программа падает, когда он попадает в эту линию в - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

cell.textLabel.text = [[theArray objectAtIndex:indexPath.row] string1]; 

Почему аварии там? Это не сбой, если я не загружаю массив из NSUserDefaults. Тем не менее, я не вижу ничего, что я сделал неправильно с сохранением или загрузкой массива.

Edit: Я могу также сделать его падение с этой строки кода:

NSLog(@"%@", [[theArray objectAtIndex:0] string1]) ; 
+0

Какое исключение вызвало сбой? Вы убедились, что 'theArray' не был вне индекса, например. '- tableView: numberOfRowsInSection:' был правильно установлен? –

+0

Нет сообщений об ошибках, программа просто выходит. Если я использую отладчик, я вижу сообщение, полученное программой: «EXC_BAD_ACCESS». tableView: numberOfRowsInSection возвращает 1. –

ответ

6

В дополнение к отличным точкам cobbal, ваш метод initWithCoder: не использует сеттеры, и поэтому строки не сохраняются. Когда вы пытаетесь получить доступ к string1 на вашей линии сбоя, эта строка, вероятно, уже выпущена.Делайте это в initWithCoder: вместо:

self.string1 = [coder decodeObjectForKey:@"string1"]; 
self.string2 = [coder decodeObjectForKey:@"string2"]; 

Для решения первой точки cobbal, то просто не делать каких-либо инициализации вообще в encodeWithCoder:. Просто закодируйте свой объект. Зайдите на страницу Apple's Archives and Serializations Programming Guide for Cocoa для получения более подробной информации об объектах кодирования и декодирования.

+0

Спасибо, что решил! Почему не используются сеттеры и геттеры, если строки уже были синтезированы? –

+0

@awakeFromNib, потому что self.string1 на самом деле является синтаксическим сахаром для [self setString1]. Запись строки1 не может вызвать этот метод, как он мог знать, что это метод? – ustun

+2

Оператор @synthesize эффективно записывает методы настройки и геттера для вас; вам все равно называть их. Как указывает ustun, self.string1 = @ "z" заменяется на [self setString1: @ "z"], тогда как string1 = @ "z" просто устанавливает string1 без вызова setter. –

1

Я не читал весь код, так что я не уверен, что это проблема, но в dealloc вы должны позвонить [super dealoc] только после освобождения переменных экземпляра.

+0

Это не исправить. –

3

Несколько вещей выскочить у меня

  • вы звоните init в encodeWithCoder:. поскольку вы ничего не инициализируете здесь, вы не должны меняться. self
  • Вы звоните alloc в initWithCoder:. После того, как вы используете метод init, вам не нужно вызывать alloc, просто вызовите self = [super init].
  • у вас есть метод viewDidUnload. Даже если это было вызвано в подклассе NSObject, вы, вероятно, не захотите избавляться от своих данных при разгрузке представления.
  • вы вызываете [super dealloc] в начале вашего метода dealloc. Он должен идти в конце.
+0

Что я должен сделать с вашей первой точкой? Должен ли я просто удалить if (self = [super init])? Я пробовал это, и это не сработало. Я внес изменения в соответствии с вашими другими пунктами, и никто из них не исправил это. –

0

Если он выходит из строя из-за того из пределов, убедитесь, что ваш UITableViewController правильно реализует

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

и

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 

, чтобы отразить NSArray вы используете в качестве источника данных.

+0

Нет, это не так, я уже проверил это. См. Мое редактирование. –

Смежные вопросы