2011-07-05 94 views
-3

我的問題取決於我的其他問題的NSMutableArray NSArray的VS回合2

NSMutableArray vs NSArray

我創建了一個navigationController,並與來自其他問題裏面的數據加載的TableView。現在得到一個detailview並從xml獲取新數據,所以我複製我的方法並修改它們。

但它是相同的結構,我不會改變很多。

但現在我得到了同樣的錯誤。

我有detailview.h

NSMutableArray *seminareArray; 

@property (nonatomic, retain) NSMutableArray *seminareArray; 

在detailview.m

@synthesize SeminareListeTabelle, selectedSeminar, seminareArray, receivedData; 

我添加此代碼

seminareArray = [[NSMutableArray alloc] init]; 
self.seminareArray = [NSMutableArray arrayWithCapacity:10]; 

我添加數據之前。而我得到的錯誤這裏

cell.textLabel.text = [seminareArray objectAtIndex:row]; 

再次EXC_BAD_ACCESS某種類型的問題

我將數據添加到陣列這樣

if([elementName isEqualToString:@"seminar"]) 
    { 
     //NSLog(@"%@", [attributeDict objectForKey:@"name"]); 
     NSString *seminarName = [NSString stringWithFormat:@"%@", [attributeDict objectForKey:@"name"]]; 
     [seminareArray addObject:seminarName]; 
     [seminarName release]; 
    } 

陣列數據填充,但的tableView重裝後,我得到這個錯誤。

// 
// SeminareListingView.m 
// Seminar App2 
// 
// Created by Alexander Frischbutter on 05.07.11. 
// Copyright 2011 __MyCompanyName__. All rights reserved. 
// 

#import "SeminareListingView.h" 
//#import "SeminareView.h" 

@implementation SeminareListingView 
@synthesize SeminareListeTabelle, selectedSeminar, seminareArray, receivedData; 

- (void) parseData:(NSString *)url 
{ 
    if(receivedData) 
    { 
     receivedData = nil; 
    } 

    NSLog(@"Parsing... url: %@", url); 

    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@", url]] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 

    if(theConnection) 
    { 
     receivedData = [[NSMutableData data] retain]; 
    } 
    else 
    { 
     //label.text = @"XML nicht geladen"; 
     NSLog(@"XML nicht gefunden"); 
    } 
} 

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
{ 
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 
    if (self) { 
     // Custom initialization 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    [super dealloc]; 
} 

- (void)didReceiveMemoryWarning 
{ 
    // Releases the view if it doesn't have a superview. 
    [super didReceiveMemoryWarning]; 

    // Release any cached data, images, etc that aren't in use. 
} 

#pragma mark - View lifecycle 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    SeminareListeTabelle = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame] style:UITableViewStylePlain]; 
    SeminareListeTabelle.delegate = self; 
    SeminareListeTabelle.dataSource = self; 
    SeminareListeTabelle.autoresizesSubviews = YES; 

    seminareArray = [[NSMutableArray alloc] init]; 
    self.seminareArray = [NSMutableArray arrayWithCapacity:10]; 

    [self parseData:[NSString stringWithFormat:@"http://akademie.kunden.fincha.com/semapp/sem_kat_arbtechnik.xml", selectedSeminar]]; 

    self.navigationItem.title = [NSString stringWithFormat:@"%@", selectedSeminar]; 
    self.view = SeminareListeTabelle; 

    // Do any additional setup after loading the view from its nib. 
} 


- (void)startParsingData  
{ 
    NSLog(@"Parsing started"); 

    NSXMLParser *dataParser = [[NSXMLParser alloc] initWithData:receivedData]; 
    dataParser.delegate = self; 

    [dataParser parse]; 
    [dataParser release]; 
    [receivedData release]; 

    NSLog(@"Received Data in seminareArray"); 
    /* 
    for(int i = 0; i < [seminareArray count]; i++) 
    { 
     NSLog(@"%d is %@", i, [seminareArray objectAtIndex:i]); 
     //NSLog(@"Count %d", [kategorienArray count]); 
    } 
    */ 
    //[seminareArray release]; 
    NSLog(@"Reload data in TableView"); 
    [self.SeminareListeTabelle reloadData];  
    NSLog(@"Data reloaded");  
} 

- (void)viewDidUnload 
{ 
    //[seminareArray release]; 
    //[SeminareListeTabelle release]; 

    NSLog(@"Vew unloaded"); 

    [super viewDidUnload]; 
    // Release any retained subviews of the main view. 
    // e.g. self.myOutlet = nil; 
} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

    static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier"; 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier]; 

    if (cell == nil) { cell = [[[UITableViewCell alloc] 
           initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:SimpleTableIdentifier] autorelease]; 
    } 

    if([seminareArray count] != 0) 
    { 
     NSLog(@"Adding data to cell"); 

     NSUInteger row = [indexPath row]; 
     //cell.textLabel.text = [NSString stringWithFormat:@"bla, %d", row]; //[seminareArray objectAtIndex:row]; 
     cell.textLabel.text = [seminareArray objectAtIndex:row]; 

     NSLog(@"Added data to cell"); 
    } 
    return cell; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 
    //NSLog(@"Count %d", [self.seminareArray count]); 
    return [seminareArray count]; 
} 

-(NSInteger) tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    return 0; 
} 

//Anzeige mit Seminaren öffnen bei Click auf die Zeile 
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    //gehe zurück zum ersten View 
    //NSLog(@"Received Data in seminareArray"); 

    [[self navigationController] popViewControllerAnimated:YES]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveResonse:(NSURLResponse *)response 
{ 
    [receivedData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    if(receivedData) 
    { 
     [receivedData appendData:data]; 
    } 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    [connection release]; 
    [receivedData release]; 

    //label.text = @"Connection failed"; 
    NSLog(@"Verbindung fehlgeschlagen!"); 
    //[[self navigationController] popViewControllerAnimated:YES]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    [self startParsingData]; 
    [connection release]; 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 
{ 
    //NSLog(@"Parser was called. Element: %@", elementName); 

    if([elementName isEqualToString:@"seminar"]) 
    { 
     //NSLog(@"%@", [attributeDict objectForKey:@"name"]); 
     NSString *seminarName = [NSString stringWithFormat:@"%@", [attributeDict objectForKey:@"name"]]; 
     [seminareArray addObject:seminarName]; 
     [seminarName release]; 
    } 
} 

- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError 
{ 
    NSLog(@"Parse Error %@", parseError); 
} 

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation 
{ 
    // Return YES for supported orientations 
    return (interfaceOrientation == UIInterfaceOrientationPortrait); 
} 

@end 
+0

爲什麼你在'self.seminareArray = [[NSMutableArray alloc] init];'? – jamapag

+1

你在哪裏初始化數組?你在哪裏添加元素到數組? – Kal

+0

ups,self was a try :)我已更新我的問題。我在這裏添加數據:[seminareArray addObject:seminarName]; –

回答

2

的問題,從這個代碼莖:

seminareArray = [[NSMutableArray alloc] init]; // owned 
seminareArray = [NSMutableArray arrayWithCapacity:10]; // autoreleased 

你首先初始化semiareArray作爲擁有對象,但隨後重新將其設置爲自動釋放的對象。

意義,它將運行循環結束後公佈。 刪除第二個(自動釋放)語句,但保持第一,一切都應該正常工作。

你得到EXC_BAD_ACCESS錯誤的原因是因爲seminareArray對象在被再次使用之前的某個點被釋放。

此外,嘗試調試您的

cell.textLabel.text = [seminareArray objectAtIndex:row]; 

嘗試將其設置爲id var = [seminareArray objectAtIndex:row];,然後設置cell.textLabel.text = var;如果被太早dealloc'd由於陣列發生錯誤,或不當的細胞/爲textLabel這會告訴你。


更新時間:

還有另外一個問題是與代碼:

NSString *seminarName = [NSString stringWithFormat:@"%@", [attributeDict objectForKey:@"name"]]; 
[seminareArray addObject:seminarName]; 
[seminarName release]; // <-- 

你創建一個自動釋放的對象seminarName,這在技術上有保留計數0。將它添加到semiareArray中,將對象保留爲1,然後再釋放它。這導致它在運行時被解除分配。問題在於,當您將值分配給textLabel時,該對象不再存在。

解決方案:刪除[seminarName release];不要擔心釋放seminarName,因爲它是自動釋放,當陣列dealloc'd它會被釋放時,或當對象從數組中刪除。

+0

http://imageshack.us/photo/my-images/692/bildschirmfoto20110706u.png/ –

+0

這幾乎總結了它。你的問題不是陣列的內存管理(至少在圖中)。你的cell.textLabel.text是無效的。確保'cell'是一個有效的(不是先前的dealloc'd)變量。與textLabel一樣。更可能的是,您的'textLabel'過早自動釋放。 – David

+0

但如果我使用cell.textLabel.text = [NSString stringWithFormat:@「bla,%d」,row];一切工作正常 –

1

在內存泄漏一個提示:

self.seminareArray = [[NSMutableArray alloc] init]; 

這會流失,因爲seminare內存聲明爲保留的財產:

@property (nonatomic, retain) NSMutableArray *seminareArray; 

這不是,反正,原因你其他問題。

您有錯誤是由row的量大造成你的陣列的count。因此,要麼不向陣列添加足夠的對象,要麼嘗試使用不正確的值作爲row。用調試器檢查該行,並確保row永遠不會超過[seminare count];你會很容易地發現它爲什麼會發生。

+1

這是不正確的。 NSArray從不會拋出EXC_BAD_ACCESS出現越界錯誤。出界限訪問被引發爲:''*** - [NSCFArray objectAtIndex:]:index(10)beyond bounds(0)「'。訪問異常是由於他訪問的內存不再有效(請參閱我的回答)。 – David

+0

我使用cell.textLabel.text = [NSString stringWithFormat:@「bla,%d」,row]; // [seminareArray objectAtIndex:row]; 它工作正常 –

2

大衛的答案是正確的,但我會建議你閱讀你的記憶管理。

如果你正在綜合屬性,那麼使用getters和setter並讓他們爲你做內存管理要容易得多。 init/dealloc方法中的例外情況是,您應該嘗試直接使用ivars以避免使用getters/setters的任何潛在副作用。

隨着兩行大衛強調

seminareArray = [[NSMutableArray alloc] init]; // owned 
seminareArray = [NSMutableArray arrayWithCapacity:10]; // autoreleased 

你可能請使用,如果內存管理正確完成。

第一行本身是正確的,因爲它創建了一個NSMutableArray的實例,保留計數爲+1,然後將其直接分配給伊娃。

然後,正如David指出的那樣,第二行用自動發佈的NSMutableArray代替了這一行,所以這行代碼太多了,導致程序崩潰。方法arrayWithCapacity:不是簡單地設置它給你一個新的自動釋放數組的數組容量。

如果你想使用一個自動釋放NSMutableArray那麼你就需要使用二傳手或者與傳遞消息的點符號:

self.seminareArray = [NSMutableArray arrayWithCapactiy:10]; 
OR 
[self setSeminareArray:[NSMutableArray arrayWithCapcity:10]]; 

通過簡單地參照的東西直奔seminareArray你避免了getter/setter方法你綜合了,因此負責你所有的內存管理。

+0

我改變它自我。 seminarearray它效果更好:)但我仍然得到錯誤。 –