1

I have a very very strange problem and I am without a clue as to why its happening. Simply enough I have a class which stores an NSString and an NSURL. There can be many of these classes so I store them in a mutable array.

This array is used to populate a tableview. When a user hits a table cell I get one of the list class's from the array, get its URL property, and pass that to a detail view. This works fine 99% of the time but the other 1% of the time the URL property that I'm passing sometimes has become released.

Specifically in the debugger the NSURL says "invalid summary" and its urlstring property says ""

I've commented out every place that I release the NSURL. Oddly enough the NSString variable in the same class does not suffer from the same unwanted behavior.

// 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];
}

EDIT 1

I think I found the problem but I dont really understand whats going on.

In the listview showWithData method I was passing in a url and assigning it to a nsurl var of listview like this.

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

{
    if (  [super init]) {


        baseURL=data.URL;
}

baseURL was being released somehow (in the bowels of TBXML I think) and this was making the NSURL from the parent tableview class be released.

I changed the showWithData method to the following and the problem has ceased to occur. It seems that using 'copy' protected the original NSURL from being released. I dont understand it though because when I check in the debugger both the NSURl being passed to the method and the baseURL var both have the same memory address. Can somebody explain this ?

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

{
    if (  [super init]) {


        self.baseURL=[data.URL copy];
}
dubbeat
  • 7,706
  • 18
  • 70
  • 122
  • How do you initialize listDataArray? – hennes Mar 23 '11 at 15:45
  • Do you mean the object is being freed? Are you getting bad access crashes? Is the pointer suddenly pointing to null? Or is it pointing to a valid object that contains an empty value? – Zaky German Mar 23 '11 at 15:45
  • a valid object with an empty value. – dubbeat Mar 23 '11 at 15:47
  • @hennes. listDataArray =[[NSMutableArray alloc]init]; – dubbeat Mar 23 '11 at 15:49
  • @dubbeat No, I mean how do you populate the array with data? (Sorry for not being specific.) – hennes Mar 23 '11 at 15:52
  • @hennes please refer to my updated question – dubbeat Mar 23 '11 at 15:59
  • AFAIK you should use if (self = [super init]), not if ([super init]). Also if the baseURL property is declared with the retain keyword, then self.baseURL = [data.URL copy] will produce a memory leak, because the URL's retain count is increased twice (once by copy and once by the property setter). – hennes Mar 24 '11 at 18:28

3 Answers3

1

Im surprised that this works at all

listData *rld = [listData alloc];

try this and your URL's may stop vanishing

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

also dont cap your ivars. It confuses the heck out of the synthesise directive sometimes.

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

}

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

@end
Warren Burton
  • 17,451
  • 3
  • 53
  • 73
  • "self.listView = [[ListView alloc] showWithData:rld.URL ];" looks fishy, for similar reasons. If showWithData: is an initializer, it should be named initWithData:. – Sherm Pendley Mar 23 '11 at 17:41
0

This might not help, at all, but it is something you could try. Instead of accessing the URL variable through rld.URL, try adding something like the following.

-(NSURL*)returnURLvalue {return URL;}

(with the appropriate declaration in the h file of course)

And use

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

to get at the variable value.

I emphasize that I don't know that this will work in your situation, but its often solved whatever inexplicable problem I was having with the . notation. Just a thought.

Fate Torcivia
  • 85
  • 1
  • 7
  • Can you explain why this would make any difference as compared to using rld.URL? – hennes Mar 23 '11 at 16:15
  • It shouldn't, but I find sometimes it does. I've never found a good answer as to why. Don't know if it will affect this problem, but its solved similar ones for me. – Fate Torcivia Mar 24 '11 at 19:43
0

In case you're storing really a lot of elements in listDataArray, you might want to consider replacing the convenience constructor [NSURL URLWithString:...] by an explicit memory allocation with subsequent deallocation. Something along the lines of

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

The convenience constructor returns an auto-released object and the use of auto-released objects is discouraged in situations where many objects are created. See also the answer to this question.

Community
  • 1
  • 1
hennes
  • 9,147
  • 4
  • 43
  • 63
  • could you hypothesize as to why most of the time my NSURL is fine and only very occasionally it is empty? – dubbeat Mar 23 '11 at 16:41
  • @dubbeat I suspect it has to do with the autoreleases and the fact, that the URL is only retained (whereas the title is copied). At some point the autorelease pool will overflow and then something has to be released. – hennes Mar 23 '11 at 16:55