我一直在搜索与我的问题相关的所有主题,但我似乎无法找到解决方案。在我的应用程序中,我有一个.h文件,其中包含构建“Lesson”对象库的信息(只是字符串和NSNumbers的集合)。当我只有一个对象时,似乎工作正常,但是当我添加第二个对象时,我得到了上述错误。
我扔了一些断点,似乎我通过我的viewDidLoad方法,但在该方法结束和我的tableView方法开始之间的某处,我收到了这个错误。我已经在下面发布了视图控制器的代码。如果您需要任何其他信息,请告诉我。在此先感谢:)
ViewController.h
#import <UIKit/UIKit.h>
#import "Lesson.h"
#import "PDFViewController.h"
#import "MediaPlayer/MediaPlayer.h"
#import "PracticeViewController.h"
#import "StoreViewController.h"
@interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
// Array to hold the purchased lessons.
@property (nonatomic,strong) NSMutableArray *purchasedLessons;
@property (nonatomic, strong) NSMutableArray *songLibrary;
@property (nonatomic, strong) NSNumber *purchaseMade;
@property (nonatomic, strong) ViewController *viewController;
// Lesson detail display items.
@property (strong, nonatomic) IBOutlet UIImageView *coverArt;
@property (weak, nonatomic) IBOutlet UILabel *lessonTitle;
@property (weak, nonatomic) IBOutlet UILabel *lessonSubtitle;
@property (weak, nonatomic) IBOutlet UILabel *durationLabel;
@property (weak, nonatomic) IBOutlet UILabel *notesLabel;
@property (weak, nonatomic) IBOutlet UILabel *timingLabel;
@property (weak, nonatomic) IBOutlet UILabel *keySignatureLabel;
@property (weak, nonatomic) IBOutlet UIImageView *difficultyImage;
@property (weak, nonatomic) IBOutlet UITextView *descriptionTextView;
@property (weak, nonatomic) IBOutlet UIImageView *dividerImage;
@property (weak, nonatomic) IBOutlet UIImageView *detailBackgroundImage;
@property (weak, nonatomic) IBOutlet UIImageView *detailsImage;
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) NSManagedObjectContext* managedObjectContext;
//Table Methods
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
// Variables and Methods for the Video Player
@property (strong, nonatomic) MPMoviePlayerViewController *player;
@end
ViewController.m
#import "ViewController.h"
#import "AppDelegate.h"
@interface ViewController ()
@end
@implementation ViewController
@synthesize coverArt;
@synthesize lessonTitle;
@synthesize lessonSubtitle;
@synthesize durationLabel;
@synthesize notesLabel;
@synthesize timingLabel;
@synthesize keySignatureLabel;
@synthesize difficultyImage;
@synthesize descriptionTextView;
@synthesize dividerImage;
@synthesize detailBackgroundImage;
@synthesize detailsImage;
@synthesize purchasedLessons;
@synthesize tableView;
@synthesize player;
@synthesize managedObjectContext;
@synthesize songLibrary;
@synthesize purchaseMade;
@synthesize viewController;
//TABLE METHODS
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return purchasedLessons.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create a cell.
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"purchased"];
// Populate the cell with data.
Lesson *temp = [[Lesson alloc] init];
temp = [purchasedLessons objectAtIndex:indexPath.row];
cell.textLabel.text = temp.title;
cell.detailTextLabel.text = temp.subtitle;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Determine what row is selected and retrieve the correct Lesson object.
Lesson *currentSelection = [[Lesson alloc] init];
int row = [indexPath row];
currentSelection = [purchasedLessons objectAtIndex:row];
UIImage *tempCoverArt = [UIImage imageNamed:currentSelection.coverArtFilename];
// Change the information in the details pane to the details for the current lesson.
[coverArt setImage:tempCoverArt];
lessonTitle.text = currentSelection.title;
lessonSubtitle.text = currentSelection.subtitle;
durationLabel.text = currentSelection.durationLabel;
timingLabel.text = currentSelection.timing;
keySignatureLabel.text = currentSelection.keySignature;
descriptionTextView.text = currentSelection.lessonDescription;
int diff = currentSelection.difficulty.intValue;
switch (diff) {
case 1:
difficultyImage.image = [UIImage imageNamed:@"storeDiff1.png"];
break;
case 2:
difficultyImage.image = [UIImage imageNamed:@"storeDiff2.png"];
break;
case 3:
difficultyImage.image = [UIImage imageNamed:@"storeDiff3.png"];
break;
case 4:
difficultyImage.image = [UIImage imageNamed:@"storeDiff4.png"];
break;
case 5:
difficultyImage.image = [UIImage imageNamed:@"storeDiff5.png"];
break;
default:
break;
}
}
//END TABLE METHODS
- (void)viewWillAppear:(BOOL)animated {
for (Lesson *lesson in purchasedLessons) {
[purchasedLessons removeObject:lesson];
}
for (Lesson *lesson in songLibrary) {
NSNumber *status = [[NSUserDefaults standardUserDefaults] objectForKey:lesson.productID];
if ([status isEqualToNumber:[NSNumber numberWithInt:1]]) {
[purchasedLessons addObject:lesson];
}
}
[tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
purchaseMade = [NSNumber numberWithInt:0];
viewController = self;
purchasedLessons = [[NSMutableArray alloc] init];
if (managedObjectContext == nil)
{
managedObjectContext = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
// Load background images.
UIImage *detailsDivider = [UIImage imageNamed:@"detailsDividerImage.png"];
[dividerImage setImage:detailsDivider];
UIImage *detailsBackground = [UIImage imageNamed:@"detailsBackgroundImage.png"];
[detailBackgroundImage setImage:detailsBackground];
UIImage *detailsPanel = [UIImage imageNamed:@"detailsDisplayImage.png"];
[detailsImage setImage:detailsPanel];
// Load default cover art.
UIImage *defaultCoverArt = [UIImage imageNamed:@"coverArtDefault.png"];
[coverArt setImage:defaultCoverArt];
// Get current version ("Bundle Version") from the default Info.plist file
NSString *currentVersion = (NSString*)[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
NSArray *prevStartupVersions = [[NSUserDefaults standardUserDefaults] arrayForKey:@"prevStartupVersions"];
if (prevStartupVersions == nil)
{
// Starting up for first time with NO pre-existing installs (e.g., fresh
// install of some version)
// Import the song library.
#import "songLibrary.h"
// Save out the library to CoreData.
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
// Fetch the library and store it in the songLibrary array.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Lesson" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *tempArray = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
songLibrary = [[NSMutableArray alloc] initWithArray:tempArray];
[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObject:currentVersion] forKey:@"prevStartupVersions"];
// Set the NSUserDefaults for the songLibrary
for (Lesson *lesson in songLibrary) {
[[NSUserDefaults standardUserDefaults] setObject:lesson.purchaseStatus forKey:lesson.productID];
}
}
else
{
if (![prevStartupVersions containsObject:currentVersion])
{
// Starting up for first time with this version of the app. This
// means a different version of the app was alread installed once
// and started.
// Clear out any previously saved songs from the CoreData store.
[managedObjectContext reset];
// Import the updated song library.
#import "songLibrary.h"
// Save out the updated song library.
NSError *error;
if (![managedObjectContext save:&error]) {
NSLog(@"Whoops, couldn't save: %@", [error localizedDescription]);
}
// Fetch the updated library and save it to the songLibrary array.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Lesson" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSArray *tempArray = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
songLibrary = [[NSMutableArray alloc] initWithArray:tempArray];
NSMutableArray *updatedPrevStartVersions = [NSMutableArray arrayWithArray:prevStartupVersions];
[updatedPrevStartVersions addObject:currentVersion];
[[NSUserDefaults standardUserDefaults] setObject:updatedPrevStartVersions forKey:@"prevStartupVersions"];
// Set the NSUserDefaults for the songLibrary
for (Lesson *lesson in songLibrary) {
[[NSUserDefaults standardUserDefaults] setObject:lesson.purchaseStatus forKey:lesson.productID];
}
}
}
if (songLibrary.count == 0) {
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Lesson" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error;
NSArray *tempArray = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
songLibrary = [[NSMutableArray alloc] initWithArray:tempArray];
}
// Save changes to disk
[[NSUserDefaults standardUserDefaults] synchronize];
// Determine purchased songs from NSDefaults and add to purchasedLessons.
for (Lesson *lesson in songLibrary) {
NSNumber *status = [[NSUserDefaults standardUserDefaults] objectForKey:lesson.productID];
if ([status isEqualToNumber:[NSNumber numberWithInt:1]]) {
[purchasedLessons addObject:lesson];
}
}
}
- (void)viewDidUnload
{
[self setLessonTitle:nil];
[self setLessonSubtitle:nil];
[self setCoverArt:nil];
[self setDurationLabel:nil];
[self setNotesLabel:nil];
[self setTimingLabel:nil];
[self setKeySignatureLabel:nil];
[self setDifficultyImage:nil];
[self setDescriptionTextView:nil];
[self setDividerImage:nil];
[self setDetailBackgroundImage:nil];
[self setDetailsImage:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Segue to the materials screen.
if ([segue.identifier isEqualToString:@"materials"]) {
PDFViewController *pdfViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
pdfViewController.selectedLesson = selected;
pdfViewController.fileToView = @"materials";
}
// Segue to the sheet screen.
else if ([segue.identifier isEqualToString:@"sheet"]) {
PDFViewController *pdfViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
pdfViewController.selectedLesson = selected;
pdfViewController.fileToView = @"sheet";
}
// Segue to the practice screen.
else if ([segue.identifier isEqualToString:@"practice"]) {
PracticeViewController *practiceViewController = [segue destinationViewController];
NSIndexPath *path = [self.tableView indexPathForSelectedRow];
int row = [path row];
Lesson *selected = [purchasedLessons objectAtIndex:row];
practiceViewController.selectedLesson = selected;
}
else if ([segue.identifier isEqualToString:@"store"]) {
StoreViewController *storeViewController = [segue destinationViewController];
storeViewController.songLibrary = songLibrary;
storeViewController.libraryViewController = viewController;
}
}
@end
答案 0 :(得分:15)
在快速枚举期间添加或删除可变数组中的对象确实违反了规则。在这种情况下,将从数组中删除课程对象,导致枚举变为无效。
在viewWillAppear中,点击
for (Lesson *lesson in purchasedLessons) {
[purchasedLessons removeObject:lesson];
}
而是尝试
[purchasedLessons removeAllObjects];
如果出于某种原因,您确实需要一次删除一个,则可以尝试
while(purchasedLessons.count > 0) {
[purchasedLesson removeLastObject];
}