управление памятью и переменная-член класса

#iphone #objective-c

#iPhone #objective-c

Вопрос:

У меня есть следующий код:

   @interface Reservation : RKObject {
    NSNumber * _uid;
    NSNumber * _did;
    NSNumber * _rid;
    NSString* _origin;
    NSString* _destination;
    NSString* _time_range;
    NSDate * _start_date;
    NSDate * _end_date;
}

@property (nonatomic, retain) NSDate * start_date;
@property (nonatomic, retain) NSDate * end_date;
@property (nonatomic, retain) NSNumber * uid;
@property (nonatomic, retain) NSNumber * did;
@property (nonatomic, retain) NSNumber * rid;
@property (nonatomic, retain) NSString * time_range;
@property (nonatomic, retain) NSString * origin;
@property (nonatomic, retain) NSString * destination;
@end

#import "Reservation.h"

@implementation Reservation
@synthesize time_range= _time_range;
@synthesize origin=_origin;
@synthesize destination=_destination;
@synthesize uid=_uid;
@synthesize did=_did;
@synthesize rid=_rid;
@synthesize start_date=_start_date;
@synthesize end_date=_end_date;


  (NSDictionary*) elementToPropertyMappings {
    return [NSDictionary dictionaryWithKeysAndObjects:
            @"TIME_RANGE", @"time_range",
            @"ORIGIN_ADDRESS", @"origin",
            @"DESTINATION_ADDRESS", @"destination",
            @"UID", @"uid",
            @"DID", @"did",
            @"RID", @"rid",
            @"START_DATETIME", @"start_date",
            @"END_DATETIME", @"end_date",
            nil]; 
}


/*
  (NSDictionary*)elementToRelationshipMappings {
    return [NSDictionary dictionaryWithKeysAndObjects:
            @"NSDate", @"start_date",
            @"NSDate", @"end_date",
            nil];
}
 */

- (void)dealloc
{
    [_start_date release];
    [_end_date release];
    [_uid release];
    [_did release];
    [_rid release];
    [_origin release];
    [_destination release];
    [_time_range release];
    //[_deal release];
    //[_route release];
    [super dealloc];
}
  

@end

 @interface ReservationViewController : UIViewController <UITableViewDelegate, UITableViewDataSource, RKObjectLoaderDelegate>{
    Reservation * myres;
}

@property (nonatomic, retain) Reservation * myres;

#import "ReservationViewController.h"


@implementation ReservationViewController
@synthesize myres;

- (IBAction)makeReservation:(id)sender
{
    self.myres = [[[Reservation alloc] init] autorelease];  
    myres.start_date = [df dateFromString:[NSString stringWithFormat:@"%@ %@", [self.data objectForKey:@"date"], [self.data objectForKey:@"start_time"]]];
    myres.end_date = [df dateFromString:[NSString stringWithFormat:@"%@ %@", [self.data objectForKey:@"date"], [self.data objectForKey:@"end_time"]]];
    NSLog(@"date is %@", myres.start_date);
}

- (void)objectLoader: (RKObjectLoader*) objectLoader didLoadObjects:(NSArray *)objects {
        Interval * res_int = [[Interval alloc] init];
        res_int.date1 = myres.start_date; //why is it null here
        res_int.date2 = myres.end_date; //why is it null here
        res_int.rid =  [[objects objectAtIndex:0] rid];
        [[LocationDictionary sharedLocationDictionary] addLocationtoDictionary:[self.data objectForKey:@"route"] withKey:res_int];
  

}

Вопрос в том, почему res_int.date1 значение равно null, когда я пытался его распечатать? Когда я печатаю myres.start_date внутри метода makeReservation, он печатается соответствующим образом, Может кто-нибудь объяснить мне это и как это исправить?

Обновить:

Я сделал следующее в своем установщике:

 -(void) setStart_date:(NSDate *) boo
{
     NSAssert(boo != nil, @"why is this nil");
    _start_date = boo;    

}
  

в конце я получил трассировку стека:

  *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'why is this nil'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x019ac5a9 __exceptionPreprocess   185
    1   libobjc.A.dylib                     0x01b00313 objc_exception_throw   44
    2   CoreFoundation                      0x01964ef8  [NSException raise:format:arguments:]   136
    3   Foundation                          0x014013bb -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]   116
    4   Project                            0x00012d42 -[Reservation setStart_date:]   194
    5   Foundation                          0x0137e5e5 -[NSObject(NSKeyValueCoding) setValue:forKey:]   285
    6   Project                           0x0004c7b3 -[RKObjectMapper updateModel:ifNewPropertyValue:forPropertyNamed:]   172
    7   Project                            0x0004cd55 -[RKObjectMapper setPropertiesOfModel:fromElements:]   754
    8   Project                            0x0004d8f3 -[RKObjectMapper updateModel:fromElements:]   50
    9   Project                            0x0004bb7a -[RKObjectMapper mapObject:fromDictionary:]   201
    10  Project                            0x0004ba42 -[RKObjectMapper mapObject:fromString:]   148
    11  Project                            0x0004927b -[RKObjectLoader processLoadModelsInBackground:]   537
    12  Foundation                          0x01370cf4 -[NSThread main]   81
    13  Foundation                          0x01370c80 __NSThread__main__   1387
    14  libSystem.B.dylib                   0x931a085d _pthread_start   345
    15  libSystem.B.dylib                   0x931a06e2 thread_start   34
)
terminate called after throwing an instance of 'NSException'
  

Комментарии:

1. -1 Я не вижу здесь никаких глобальных переменных.

2. myres — это глобальная переменная, верно

3. Согласно приведенному выше коду myres является переменной-членом класса в `ReservationViewController’. Следовательно, это не глобальное.

4. отредактировал заголовок вопроса, пожалуйста, поддержите его еще раз

5. Теперь это больше похоже на неправильное понимание RKObjectMapper, чем на что-либо в управлении памятью.

Ответ №1:

Какова последовательность вызова makeReservation (из IBAction) и objectLoader ? Возможно ли, что objectLoader вызывается ранее, makeReservation поэтому myres еще не было инициализировано?

Каково определение интерфейса для did свойства резервирования? Ваша строка:

 myres.did = [[NSNumber alloc] initWithInt:[[[data objectForKey:@"discount"] did] intValue]];
  

Если она определена как (nonatomic, retain) , возможно, вы сохраняете объект NSNumber, не освобождая его. Если это так, измените строку на:

 myres.did = [NSNumber numberWithInt:[[[data objectForKey:@"discount"] did] intValue]];
  

Вам также следует раскомментировать свою строку:

//[res_int release]

Комментарии:

1. Я выполнил все ваши предложения, и makeReservation вызывается первым перед ObjectLoader … по-прежнему имеет значение null

2. происходит много чего, чего мы не видим в этом примере кода. Например, вы проверили это myres.start_date != nil в objectLoader после его первого назначения? [df dateFromString:...] также может произойти сбой. Я бы начал с этого и продвигался вперед, проверяя все предположения по ходу дела. Добавьте несколько NSLog() инструкций для вывода значений в консоль отладки.

3. просто попытался выполнить myres.start_date внутри ObjectLoader и да, это ноль, но почему?????

4. вам нужно продолжать отладку. итак, теперь вы знаете, что [df dateFromString:...] происходит сбой. Разбейте функцию на части и проверьте значения аргументов. Один или несколько из них явно недопустимы, поэтому где-то в процессе вы что-то неправильно настраиваете. Опять же, я бы начал с самого начала. Например. где присвоены самые первые значения, проверьте, работает ли это. Затем перейдите к следующему шагу и т.д. В конце концов вы найдете точное место, где он ломается, и тогда «почему» должно стать ясно.

5. кроме того, где вы выделяете и настраиваете df ? Я предполагаю, что это экземпляр NSDateFormatter. Попробуйте [df dateFromString:@"REPLACE_WITH_YOUR_SAMPLE_DATE_STRING"] и используйте допустимую строку, которую вы ожидаете от своих аргументов. Это работает? Проверьте каждый аргумент, который вы используете для построения строки даты. Они правильные? И т.д. и т.п. Это просто стандартная отладка. Вы обнаружите проблему.

Ответ №2:

в вашем методе сохранения makeReservation попробуйте следующее:

 self.myres = [[[Reservation alloc] init] autorelease];
  

При этом сохранится объект резервирования.

Редактировать: XJones прав. Редактирование строки кода.

Комментарии:

1. На самом деле, хорошей практикой является называть ваши переменные как-то иначе, чем имя вашего свойства, чтобы избежать путаницы. Итак, что-то вроде резервирования @property (неатомное, сохранить) * myres; @synthesize myres = _myres;

2. это неправильно. свойство myres определено как «сохранить», поэтому ваша строка кода должна быть такой, self.myres = [[[Reservation alloc] init] autorelease] иначе экземпляр будет сохранен дважды (один раз с помощью alloc и еще раз с помощью myres установщика свойств). Или просто оставьте все так, как у вас есть. Вы выделяете myres непосредственно в iVar, поэтому он уже сохраняется должным образом. Я согласен с @Micah Hainline относительно именования.

3. Вы уверены, что dateFromString в makeReservation указывает правильную дату?

4. Я распечатал myres.start_date в функции makeReservation, и она выводит дату.. когда я печатаю myres.start_date в методе ObjectLoader, оно равно нулю

5. В ObjectLoader значение myres равно нулю или просто значение start_date равно нулю? Если это просто start_date nil, я не уверен, почему значение не сохраняется, поскольку вы подтвердили ниже, что это свойство с ‘retain’ .

Ответ №3:

Ваша проблема, скорее всего, в Reservation.h .

Убедитесь, что для ваших дат указано следующее:

 @property (non-atomic, retain) NSDate *start_date;
@property (non-atomic, retain) NSDate *end_date;
  

Атрибутом импорта здесь является сохранить.

Комментарии:

1. и интервал класса такой же для свойства date1 amp; date2?

2. Ну, я бы добавил немного NSLog в метод makeReservation, чтобы увидеть, что равно null. Используется NSAssert. Например: NSLog(@"Date Formatter: %@", df); , NSLog(@"Data Date: %@", [self.data objectForKey:@"date"]); и т. Д

3. поскольку я отредактировал вопрос выше … myres.start_date не равен нулю при сохранении makeReservation

4. И когда вы достигнете метода ObjectLoader, вы уверены myres != nil ?

5. значение myres не равно нулю, но значение myres.start_date равно нулю… теперь вопрос в том, почему