2011-04-16 69 views
0

**注意:我更新了基於aroth建議的代碼 - 但它仍然崩潰。下面的帖子中的代碼是更新後的代碼。在UITableView中滾動時發生崩潰 - 對象被意外釋放

我想創建一個基於表視圖XCode模板(XCode 4)的iPhone應用程序。表視圖會以正確的順序填充正確的數據 - 但是當我滾動瀏覽表時,應用程序崩潰(有時候我可以滾動5或10多個單元格,有時會立即凍結)。表視圖是從另一個「iPodLibraryParser」對象的IVAR中的「藝術家」對象提供的。我相信問題在於'iPodLibraryParser'對象被過早釋放 - 但我不明白爲什麼。

我已經創建了下面的頭文件的iPodLibraryParser對象:

#import <Foundation/Foundation.h> 
#import <MediaPlayer/MediaPlayer.h> 
#import <CoreLocation/CoreLocation.h> 
#import "ArtistClass.h" 

@interface iPodLibraryParser : NSObject { 

    //Location stuff 
    CLLocationManager *locationManager; 
    IBOutlet UITextField *latitudeTextField; 
    IBOutlet UITextField *longitudeTextField; 
    IBOutlet UILabel *latitudeLabel; 
    IBOutlet UILabel *longitudeLabel; 

    //Music Library Stuff 
    NSString *currentArtist; 
    NSString *currentAlbum; 
    NSMutableArray *artistArray; 
    NSMutableArray *sortedArtistArray;  
} 

@property (nonatomic, retain) NSMutableArray *sortedArtistArray; 

-(void)parseiPodLibrary; 
-(id) initializeiPodLibraryParser; 

@end 

在這個類的.m文件相關的代碼:

@implementation iPodLibraryParser 

@synthesize sortedArtistArray; 

-(id) initializeiPodLibraryParser{ 

    [super init]; 

    sortedArtistArray = [[NSMutableArray alloc] initWithObjects:nil]; 

    return self; 

} 

    -(void)parseiPodLibrary{ 

    ..... 

NSArray *sortingArray = [[NSArray alloc] initWithObjects:artistTrackCountSorter,nil]; 
NSArray *tempSortedArray = [artistArray sortedArrayUsingDescriptors:sortingArray]; 
[sortedArtistArray removeAllObjects]; 
[sortedArtistArray addObjectsFromArray:tempSortedArray]; 

    } 

藝術家對象頭:

#import <UIKit/UIKit.h> 
#import "iPodLibraryParser.h" 

@interface ArtistClass : NSObject { 

    NSString *artistName; 
    int numberOfTracks; 

    id artistClassViewController; 
} 

-(id) initializeArtistObjectWithDocument:(id)myDocument withArtist:(NSString*) artist; 

@property (nonatomic, retain) NSString *artistName; 
@property (nonatomic, assign) int numberOfTracks; 

@end 

表視圖控制器(從正在使用的模板中稱爲RootViewController)

部首:

#import <UIKit/UIKit.h> 
#import "iPodLibraryParser.h" 
#import "ArtistClass.h" 

@interface RootViewController : UITableViewController { 

    iPodLibraryParser *iPodLibrary; 
} 

@property (nonatomic, retain) iPodLibraryParser *iPodLibrary; 

@end 

相關代碼

- (void)viewDidAppear:(BOOL)animated 
{ 
    [super viewDidAppear:animated]; 

    NSLog(@"In viewDidAppear"); 

    iPodLibrary = [[iPodLibraryParser alloc] initializeiPodLibraryParser]; 
    [iPodLibrary parseiPodLibrary]; 

} 

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
{ 
    return 1; 
} 

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
{ 

    NSLog(@"there are %i artists in the array", [[iPodLibrary sortedArtistArray] count]); 
    return [[iPodLibrary sortedArtistArray] count]; 

} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSLog(@"in tableView blah"); 

    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; 
    } 

    // Configure the cell. 

    NSLog(@"getting row: %i",indexPath.row); 

    cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName]; 

    return cell; 
} 

該錯誤是在這一行:

cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName]; 

我試圖創建與藝術家對象的數組,我的RootViewController的內創建 - 並且完美地工作(可以滾動整個桌子而不會崩潰)

再次感謝!

- 編輯:

這是有趣的是,我在不同的時間得到不同的錯誤:

大多數IT在該行只是EXC_BAD_ACCESS時代:

cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName]; 

有時候, :

-[UIAutoRotatingWindow isEqualToString:]: unrecognized selector sent to instance 0x1baa80 

而另一個與無法識別的RG有關B選擇器(很奇怪)。

回答

0

您的問題是,當你這樣做:

sortedArtistArray = [artistArray sortedArrayUsingDescriptors:sortingArray];

sortedArrayUsingDescriptors方法返回一個自動釋放的對象,所以當它得到你釋放,而沒有警告你不應該感到驚訝。

而且,因爲你的init作用:

sortedArtistArray = [[NSArray alloc] init];

...因爲你分配給它之前不釋放,你的代碼泄漏NSArray的實例。我會建議作如下修改:

  1. sortedArtistArrayNSMutableArray*,如:

    NSMutableArray* sortedArtistArray;

  2. 不要在parseiPodLibrary覆蓋數組引用。相反,只是排序的數據集複製到可變數組,如:

    -(void)parseiPodLibrary{ 
    
        //..... 
    
        NSArray* temp = [artistArray sortedArrayUsingDescriptors:sortingArray]; 
        [sortedArtistArray removeAllObjects]; 
        [sortedArtistArray addObjectsFromArray:temp]; 
    
    } 
    
  3. 不要在viewDidAppear調用[iPodLibrary retain];。你已經調用了alloc/init,所以不需要再保留它。

  4. 確保您在dealloc調用viewWillDisappear[iPodLibrary release];,並[sortedArtistArray release];讓你不泄漏內存。

0

我認爲你的iPodLibrary變量比它的數組過度釋放的可能性要大得多。

NSArray *artistArray = [iPodLibrary sortedArtistArray]; 
Artist *artist = [artistArray objectAtIndex:indexPath.row]; 
NSString *name = [artist artistName]; 
cell.textLabel.text = name; 

有沒有可能是你的initializeiPodLibraryParser實現返回一個自動釋放的對象:它失敗,您應通過拆分您的代碼到幾行,看到解決?它不應該違反公約。但這會導致這個問題,這是有道理的。

當調用此:

iPodLibrary = [[iPodLibraryParser alloc] initializeiPodLibraryParser]; 

你直接分配iPodLibrary伊娃,所以它的突變不叫,它並不重要的屬性標記爲保留。如果你認爲它被隱含地保留下來,那麼很可能你會在其他地方過度釋放它。我發現,如果你用這種風格來分配的屬性,你就會明白你自己的內存管理:

iPodLibraryParser *parser = [[iPodLibraryParser alloc] initializeiPodLibraryParser]; // retain count should be 1 if not autoreleased 
[self setIpodLibrary:parser]; // retain count is now 2 
[parser release]; // retain count is now 1, will go to zero when you release it in dealloc or viewDidUnload 

最後,我想你iPodLibrary初始化擺脫viewDidAppearviewDidLoad:。這就是你應該初始化視圖的地方。而且你應該清理在viewDidUnload中初始化的任何內容,這將在低內存情況下調用。

+0

原來問題出在我的ArtistClass - 藝術家字符串在我不知情的情況下被自動發佈。將代碼分解爲多行代碼是一個巨大的幫助。謝謝大家!!! – chrisgilpin 2011-04-16 23:03:57