Неожиданно выпущено значение NSURL

У меня очень-очень странная проблема, и я понятия не имею, почему это происходит. Достаточно просто у меня есть класс, в котором хранятся NSString и NSURL. Таких классов может быть много, поэтому я сохраняю их в изменяемом массиве.

Этот массив используется для заполнения табличного представления. Когда пользователь попадает в ячейку таблицы, я получаю один из классов списка из массива, получаю его свойство URL и передаю его в подробное представление. Это работает нормально в 99% случаев, но в 1% случаев свойство URL, которое я передаю, иногда становится освобожденным.

В частности, в отладчике NSURL сообщает «недопустимая сводка», а его свойство urlstring говорит «»

Я закомментировал каждое место, где я публикую NSURL. Как ни странно, переменная NSString в том же классе не страдает таким же нежелательным поведением.

// list data
@interface ListData : NSObject {
    NSURL *URL;
    NSString *Title;

}

@property(nonatomic,retain) NSURL *URL;
@property(nonatomic,copy) NSString *Title;

@end

#import "ListData.h"


@implementation ListData
@synthesize URL;
@synthesize Title;

-(void)dealloc
{
    [URL release];
    [Title release];


    [super dealloc];
}

@end

// table delegate method

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ListData *rld=nil;

    rld=[listDataArray objectAtIndex:indexPath.row];

    if (self.listView) {
        //[remixView closeRemix];

        [self.listView release];
        self.listView=nil;
    }

    // occassionaly the value of rld.URL is being released somehow
    self.listView = [[ListView alloc] showWithData:rld.URL ];


    self.listView.title = rld.remixTitle;

    [table.navigationController pushViewController:listView animated:YES];

}

//population of list array

listArray =[[NSMutableArray alloc]init];


while (listelement!=nil) {


    listData *rld = [listData alloc];

    [rld setURL:[NSURL URLWithString:[TBXML textForElement:[TBXML childElementNamed:@"url" parentElement:listelement]]]];
    [rld setTitle:[TBXML textForElement:[TBXML childElementNamed:@"title" parentElement:listelement]]];

    [listArray addObject:rld];

    [rld release];
    listelement = [TBXML nextSiblingNamed:@"list" searchFromElement:listelement];
}

ИЗМЕНИТЬ 1

Я думаю, что нашел проблему, но я действительно не понимаю, что происходит.

В методе listview showWithData я передавал URL-адрес и назначал его переменной nsurl для listview, как это.

-(id) showWithData:(ListData *) data;

{
    if (  [super init]) {


        baseURL=data.URL;
}

baseURL каким-то образом выпускался (я думаю, в недрах TBXML), и это заставляло выпускать NSURL из родительского класса tableview.

Я изменил метод showWithData на следующий, и проблема исчезла. Похоже, что использование «копирования» защищает исходный NSURL от выпуска. Я этого не понимаю, потому что, когда я проверяю отладчик, как NSURl, передаваемый методу, так и baseURL var имеют один и тот же адрес памяти. Кто-нибудь может это объяснить?

-(id) showWithData:(xListData *) data;

{
    if (  [super init]) {


        self.baseURL=[data.URL copy];
}

person dubbeat    schedule 23.03.2011    source источник
comment
Как инициализировать listDataArray?   -  person hennes    schedule 23.03.2011
comment
Вы имеете в виду, что объект освобождается? Вы получаете сбои из-за плохого доступа? Указатель внезапно указывает на нуль? Или он указывает на действительный объект, содержащий пустое значение?   -  person Zaky German    schedule 23.03.2011
comment
действительный объект с пустым значением.   -  person dubbeat    schedule 23.03.2011
comment
@hennes. listDataArray = [[NSMutableArray alloc] инициализация];   -  person dubbeat    schedule 23.03.2011
comment
@dubbeat Нет, я имею в виду, как вы заполняете массив данными? (Приносим извинения за неточность.)   -  person hennes    schedule 23.03.2011
comment
@hennes, пожалуйста, обратитесь к моему обновленному вопросу   -  person dubbeat    schedule 23.03.2011
comment
AFAIK вы должны использовать if (self = [super init]), а не if ([super init]). Также, если свойство baseURL объявлено с ключевым словом keep, тогда self.baseURL = [data.URL copy] вызовет утечку памяти, потому что счетчик сохранения URL-адреса увеличивается вдвое (один раз копированием и один раз установщиком свойства).   -  person hennes    schedule 24.03.2011


Ответы (3)


Я удивлен, что это вообще работает

listData *rld = [listData alloc];

попробуйте это, и ваш URL-адрес может перестать исчезать

listData *rld = [[listData alloc] init];

также не закрывайте свои ivars. Иногда это сбивает с толку директиву синтеза.

@interface ListData : NSObject {
    NSURL *url;
    NSString *title;

}

@property(nonatomic,retain) NSURL *url;
@property(nonatomic,copy) NSString *title;

@end
person Warren Burton    schedule 23.03.2011
comment
self.listView = [[ListView alloc] showWithData: rld.URL]; выглядит подозрительно по тем же причинам. Если showWithData: инициализатор, он должен называться initWithData :. - person Sherm Pendley; 23.03.2011

Это может совсем не помочь, но вы можете попробовать. Вместо доступа к переменной URL через rld.URL попробуйте добавить что-то вроде следующего.

-(NSURL*)returnURLvalue {return URL;}

(конечно, с соответствующим объявлением в файле h)

И использовать

self.listView = [[ListView alloc] showWithData:[rld returnURLvalue]];

чтобы получить значение переменной.

Я подчеркиваю, что не знаю, сработает ли это в вашей ситуации, но это часто решает любую необъяснимую проблему, которая у меня была с файлом. обозначение. Просто мысль.

person Fate Torcivia    schedule 23.03.2011
comment
Можете ли вы объяснить, почему это имеет значение по сравнению с использованием rld.URL? - person hennes; 23.03.2011
comment
Не должно, но иногда бывает. Я так и не нашел хорошего ответа, почему. Не знаю, повлияет ли это на эту проблему, но для меня он решил аналогичные. - person Fate Torcivia; 24.03.2011

Если вы действительно храните много элементов в listDataArray, вы можете подумать о замене удобного конструктора [NSURL URLWithString: ...] явным выделением памяти с последующим освобождением. Что-то вроде

NSURL* URL = [[NSURL alloc] initWithString:...];
rld.URL = URL;
[URL release];

Удобный конструктор возвращает автоматически выпущенный объект, и использование автоматически выпущенных объектов не рекомендуется в ситуациях, когда создается много объектов. См. Также ответ на этот вопрос.

person hennes    schedule 23.03.2011
comment
Можете ли вы предположить, почему большую часть времени мой NSURL в порядке и лишь изредка оказывается пустым? - person dubbeat; 23.03.2011
comment
@dubbeat Я подозреваю, что это связано с автоматическим выпуском и тем фактом, что URL-адрес сохраняется только (тогда как заголовок копируется). В какой-то момент пул автозапуска переполнится, и тогда нужно что-то освободить. - person hennes; 23.03.2011