**注意:我已经根据aroth的建议更新了代码 - 但是它仍在崩溃。以下帖子中的代码是更新后的代码。
我正在尝试基于表视图XCode模板(XCode 4)创建一个iPhone应用程序。表格视图以正确的顺序填充正确的数据 - 但是当我滚动表格时应用程序崩溃(有时我可以滚动5或10个以上的单元格,有时它会立即冻结)。表格视图由NSArray中的“Artist”对象提供,NSArray是另一个“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中创建的Artist对象创建一个数组 - 并且完美地工作(可以滚动整个表而不会崩溃)
再次感谢!
- 编辑:
值得注意的是,我在不同时间会遇到不同的错误:
大多数时候,这一行只是EXC_BAD_ACCESS:
cell.textLabel.text = [[[iPodLibrary sortedArtistArray] objectAtIndex:indexPath.row] artistName];
有时它是:
-[UIAutoRotatingWindow isEqualToString:]: unrecognized selector sent to instance 0x1baa80
另一个与无法识别的RGB选择器有关(非常奇怪)。
答案 0 :(得分:0)
问题在于你这样做:
sortedArtistArray = [artistArray sortedArrayUsingDescriptors:sortingArray];
sortedArrayUsingDescriptors
方法正在返回一个自动释放的对象,所以当你在没有警告的情况下释放它时,你不应该感到惊讶。
此外,因为您的init
会:
sortedArtistArray = [[NSArray alloc] init];
...并且因为在分配给它之前你没有释放它,你的代码正在泄漏NSArray实例。我建议进行以下修订:
将sortedArtistArray
设为NSMutableArray*
,例如:
NSMutableArray* sortedArtistArray;
请勿覆盖parseiPodLibrary
中的数组引用。而只是将已排序的数据集复制到可变数组中,如:
-(void)parseiPodLibrary{
//.....
NSArray* temp = [artistArray sortedArrayUsingDescriptors:sortingArray];
[sortedArtistArray removeAllObjects];
[sortedArtistArray addObjectsFromArray:temp];
}
请勿在{{1}}中致电[iPodLibrary retain];
。你已经调用了alloc / init,因此不需要再次保留它。
确保您致电viewDidAppear
中的[iPodLibrary release];
和viewWillDisappear
中的[sortedArtistArray release];
,以便您不会泄漏内存。
答案 1 :(得分: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
ivar,因此不会调用其mutator,并且该属性被标记为retain并不重要。如果您认为它被隐式保留,那么您可能会在其他地方过度释放它。如果您使用此样式分配属性,我发现您将了解自己的内存管理:
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
初始化从viewDidAppear
移至viewDidLoad:
。这就是你应该初始化你的观点的地方。你应该清理viewDidUnload
中初始化的任何内容,这些内容将在低内存情况下调用。