2012-08-01 3 views
3

나는 내 문제와 관련된 모든 주제를 수색 해 왔지만 해결책을 찾을 수없는 것 같습니다. 내 응용 프로그램에서는 "학습"개체 (그냥 문자열 및 NSNumbers 컬렉션)의 라이브러리를 빌드하는 정보를 보유하는 .h 파일이 있습니다. 하나의 객체 만 가질 때 잘 동작하는 것처럼 보이지만 두 번째 객체를 추가하면 위의 오류가 발생합니다.컬렉션이 열거되어있는 동안 변형되었습니다

일부 중단 점을 던져서 내 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

FYI : ".h file"= "헤더 파일", 혀를 조금 더 쉽게 벗어납니다. – benzado

+0

Lol. 그건 사실이야 :) – Barks

답변

15

그것은 빠르고 열거하는 동안 변경 가능한 배열에서 객체를 추가하거나 제거 할 참 규칙에 위배됩니다. 이 경우 레슨 개체가 배열에서 제거되므로 열거 형이 유효하지 않게됩니다.

viewWillAppear에서

for (Lesson *lesson in purchasedLessons) { 
    [purchasedLessons removeObject:lesson]; 
} 

을 가지고 어떤 이유로, 당신은 한 번에 하나씩 제거해야 않는 경우 대신, 당신이 시도 할 수

[purchasedLessons removeAllObjects]; 

을 시도

while(purchasedLessons.count > 0) { 
    [purchasedLesson removeLastObject];   
} 
+0

질문에 대답 할 때 복사/붙여 넣기 코드를 게시하는 것보다 답변이 도움이되는만큼 많은 정보를 제공하십시오. 이 방법으로 사람들은 질문을하고 더 많은 것을 배울 수 있습니다 (이것이 우리 모두가 여기에있는 이유입니다). –

+0

잘 찍은 포인트. 좀 더 많은 정보를 추가하려고했습니다. – boxel

+0

대단히 감사합니다 @ boxel :) 매력처럼 일했습니다. 나는 내가 그것을 놓쳤다라고 생각할 수 없다 : P 위대한 대답! – Barks

관련 문제