Сбой приложения по причине: коллекция <__ NSArrayM: 0x7071700> была видоизменена при перечислении - PullRequest
1 голос
/ 25 февраля 2011

Не могли бы вы помочь мне найти причину сбоя моего приложения после нажатия на сегментированный элемент управления?Не всегда, но обычно после нескольких нажатий.

Сообщение об ошибке:

 *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x7071700> was mutated while being enumerated.(
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>",
    "<PLImageTableSegment: 0x7051d30>"
)'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x00e51be9 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x00fa65c2 objc_exception_throw + 47
    2   CoreFoundation                      0x00e516a9 __NSFastEnumerationMutationHandler + 377
    3   CoreFoundation                      0x00e4ae78 -[__NSArrayM dealloc] + 152
    4   PhotoLibrary                        0x0ac3a1c4 +[PLImageTable releaseSegmentCache] + 37
    5   PhotoLibrary                        0x0ac1898f -[PLPhotoLibrary dealloc] + 183
    6   CoreFoundation                      0x00d68a6c CFRelease + 92
    7   CoreFoundation                      0x00d8db8d _CFAutoreleasePoolPop + 237
    8   Foundation                          0x00018443 -[NSAutoreleasePool release] + 167
    9   UIKit                               0x002c9bf2 _UIApplicationHandleEvent + 8792
    10  GraphicsServices                    0x01787a36 PurpleEventCallback + 1550
    11  CoreFoundation                      0x00e33064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
    12  CoreFoundation                      0x00d936f7 __CFRunLoopDoSource1 + 215
    13  CoreFoundation                      0x00d90983 __CFRunLoopRun + 979
    14  CoreFoundation                      0x00d90240 CFRunLoopRunSpecific + 208
    15  CoreFoundation                      0x00d90161 CFRunLoopRunInMode + 97
    16  GraphicsServices                    0x01786268 GSEventRunModal + 217
    17  GraphicsServices                    0x0178632d GSEventRun + 115
    18  UIKit                               0x002cd42e UIApplicationMain + 1160
    19  Reportieris                         0x00001c60 main + 102
    20  Reportieris                         0x00001bf1 start + 53
)
terminate called after throwing an instance of 'NSException'

заголовочный файл:

#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>

@interface MainViewController : UIViewController <MFMailComposeViewControllerDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate,UIActionSheetDelegate, UIScrollViewDelegate>{
    IBOutlet UITextField *virsraksts;
    IBOutlet UITextField *paraksts;
    IBOutlet UITextField *apraksts;
    IBOutlet UIPageControl *pageControl;
    UISegmentedControl *segControl;
    UIScrollView *horView;
    UIButton *nosutitButton;
    UIImage *im;
    NSMutableArray *bildes;
    NSMutableArray *bildesFileName;
}

@property (nonatomic, retain) UITextField *virsraksts;
@property (nonatomic, retain) UITextField *paraksts;
@property (nonatomic, retain) UITextField *apraksts;
@property (nonatomic, retain) IBOutlet UIButton *nosutitButton;
@property (nonatomic, retain) IBOutlet UIScrollView *horView;
@property (nonatomic, retain) IBOutlet UISegmentedControl *segControl;
@property (nonatomic, retain) IBOutlet UIPageControl *pageControl;
-(IBAction)textFieldDoneEditing:(id)sender;
- (IBAction)buttonPressed;
-(NSString *)dataFilePath;
-(void)applicationWillTerminate:(NSNotification *)notification;
- (IBAction)segControlClicked:(id)sender;

@end

файл реализации:

#import "MainViewController.h"

@implementation MainViewController
@synthesize virsraksts;
@synthesize apraksts;
@synthesize paraksts;
@synthesize segControl;
@synthesize horView;
@synthesize nosutitButton;
@synthesize pageControl;

BOOL isCamera;
NSInteger nr;

-(NSString *)dataFilePath
{
    NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory=[paths objectAtIndex:0];
    return [documentsDirectory stringByAppendingPathComponent:@"data.plist"];
}

-(void)applicationWillTerminate:(NSNotification *)notification
{
    NSMutableArray *array=[[NSMutableArray alloc] init];
    [array addObject:paraksts.text];
    [array writeToFile:[self dataFilePath] atomically:YES];
    [array release];
}


-(IBAction)textFieldDoneEditing:(id)sender
{
    [sender resignFirstResponder];
}





// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"bg.png"]];
    horView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"horviewbg.png"]];
    horView.delegate = self;

    NSString *filePath=[self dataFilePath];
    if ([[NSFileManager defaultManager] fileExistsAtPath:filePath]) 
    {
        NSArray *array=[[NSArray alloc] initWithContentsOfFile:filePath];
        paraksts.text=[array objectAtIndex:0];
        [array release];
    }
    UIApplication *app=[UIApplication sharedApplication];
    [[NSNotificationCenter defaultCenter] addObserver:self 
                                             selector:@selector(applicationWillTerminate:)
                                                 name:UIApplicationWillTerminateNotification
                                               object:app];


    bildes = [[NSMutableArray alloc] init];
    bildesFileName = [[NSMutableArray alloc] init];
    isCamera=NO;
    [horView setContentSize:CGSizeMake(0, 163)];

    UIImage *buttonImageNormal = [UIImage imageNamed:@"whiteButton.png"];
    UIImage *stretchableButtonImageNormal = [buttonImageNormal 
                                             stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [nosutitButton setBackgroundImage:stretchableButtonImageNormal 
                             forState:UIControlStateNormal];

    UIImage *buttonImagePressed = [UIImage imageNamed:@"blueButton.png"];
    UIImage *stretchableButtonImagePressed = [buttonImagePressed
                                              stretchableImageWithLeftCapWidth:12 topCapHeight:0];
    [nosutitButton setBackgroundImage:stretchableButtonImagePressed 
                             forState:UIControlStateHighlighted];

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 
    {
        [segControl setEnabled:NO forSegmentAtIndex:0];
    }

    //deleting images   
    for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL]) 
    {
        [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), file] error:NULL];
    }
    [super viewDidLoad];
}




- (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.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    self.horView = nil;
    //deleting images

    for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL]) 
    {
        [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), file] error:NULL];
    }
    [super viewDidUnload];
}


- (void)dealloc {
    [virsraksts release];
    [apraksts release];
    [paraksts release];
    [bildes release];
    [bildesFileName release];
    [segControl release];
    [pageControl release];
    [horView release];
    [nosutitButton release];
    [super dealloc];
}

-(void) showEmailModalView {

    MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
    picker.mailComposeDelegate = self; // &lt;- very important step if you want feedbacks on what the user did with your email sheet

    NSString *subject =[NSString stringWithFormat:@"Mobilais reportieris: %@",virsraksts.text];
    [picker setSubject:subject];

    // Set up recipients
    NSArray *toRecipients = [NSArray arrayWithObject:@"test@test.com"]; 


    [picker setToRecipients:toRecipients];

    // Attach an image to the email
    NSString *tempPath = NSTemporaryDirectory();
    for (int i=0;i<[bildesFileName count]; i++) 
    {
        NSString *imagePath = [tempPath stringByAppendingPathComponent:[bildesFileName objectAtIndex:i]];

        if ([[NSFileManager defaultManager] fileExistsAtPath:imagePath])
        {
            NSData *myData = [NSData dataWithContentsOfFile:imagePath];
            [picker addAttachmentData:myData mimeType:@"image/jpeg" fileName:[bildesFileName objectAtIndex:i]];
        }
    }

    // Fill out the email body text
    NSString *emailBody =[NSString stringWithFormat:@"%@<br />\n\n%@",apraksts.text,paraksts.text];
    [picker setMessageBody:emailBody isHTML:YES]; // depends. Mostly YES, unless you want to send it as plain text (boring)
    picker.navigationBar.barStyle = UIBarStyleBlack; // choose your style, unfortunately, Translucent colors behave quirky.
    [self presentModalViewController:picker animated:YES];
    [picker release];
}

- (IBAction)buttonPressed {
    [self showEmailModalView];   
}
#pragma mark -
#pragma mark MAIL DELEGATE

// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation.

- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{ 
    // Notifies users about errors associated with the interface
    switch (result)
    {
        case MFMailComposeResultCancelled:
            break;
        case MFMailComposeResultSaved:
            break;
        case MFMailComposeResultSent:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"E-pasts" message:@"Veiksmīgi nosūtīts"
                                                           delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
            [alert release];
        }
            break;
        case MFMailComposeResultFailed:
            break;

        default:
        {
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"E-pasts" message:@"Neizdevās nosūtīt"
                                                           delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];
            [alert show];
            [alert release];
        }

            break;
    }
    [self dismissModalViewControllerAnimated:YES];
}

#pragma mark -

- (IBAction)segControlClicked:(id)sender
{
    //int clickedSegment = [sender selectedSegment];
    UIImagePickerController *photoPicker =[[UIImagePickerController alloc] init];
    photoPicker.delegate = self;
    photoPicker.allowsEditing = NO;
    //NSLog(@"segmentAction: selected segment = %d", [sender selectedSegmentIndex]);
    if ([sender selectedSegmentIndex] == 0)
    {
        photoPicker.sourceType=UIImagePickerControllerSourceTypeCamera;
        isCamera=YES;
    }
    else {
        photoPicker.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum;;
        isCamera=NO;
    }

    [self presentModalViewController:photoPicker animated:YES];
    [photoPicker release];
}

#pragma mark  -


- (void)imagePickerController:(UIImagePickerController *)photoPicker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    if ([[info objectForKey:UIImagePickerControllerMediaType] isEqualToString:@"public.image"]) 
    {
        // you got an image

        UIImage * img = [info objectForKey:@"UIImagePickerControllerOriginalImage"];
        if (isCamera==YES)
            UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
        NSString *tempPath = NSTemporaryDirectory();
        NSString *tempName=[[NSString alloc] initWithFormat:@"temp%d.jpg", [bildes count]];
        NSString *imagePath = [tempPath stringByAppendingPathComponent:tempName];
        [bildesFileName insertObject:tempName atIndex:[bildesFileName count]];
        [tempName release];


        NSData* imageData = UIImageJPEGRepresentation(img, 1.0);
        [imageData writeToFile:imagePath atomically:YES];
        [bildes insertObject:imageData atIndex:[bildes count]];

        [[photoPicker parentViewController] dismissModalViewControllerAnimated:YES];
        if(img!=nil)
        {

            horView.frame = CGRectMake(0, 140, 320, 163);
            [horView setContentSize:CGSizeMake((320*[bildes count]), 163)];

            //pievienojam bildi
            UIImageView *i=[[UIImageView alloc] initWithImage:[UIImage imageWithData:imageData]];
            [i setFrame:CGRectMake((320*[bildes count]-320+50),5,220,153)]; //Adjust X,Y,W,H as needed
            i.contentMode = UIViewContentModeScaleAspectFit;
            [horView addSubview:i];
            [i release];

            //pievienojam dzēšanas pogu
            UIButton *deleteButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; 
            [deleteButton setFrame:CGRectMake(320*[bildes count]-50,10, 28, 28)];
            [deleteButton setImage:[UIImage imageNamed:@"deletebutton.png"] forState:UIControlStateNormal];

            [deleteButton addTarget:self action:@selector(deleteImage:) forControlEvents:UIControlEventTouchUpInside];
            [deleteButton setTag:[bildes count]-1];
            [horView addSubview:deleteButton];
            [deleteButton release];


            //pabīdam bildi redzamajā rāmī
            [self performSelector:@selector(moveHorView) withObject:nil afterDelay:.5];
            pageControl.numberOfPages = [bildes count];  
            pageControl.currentPage = [bildes count];
        }
    //[imageData release];
    }
    else 
    {
        // movie!

        [[photoPicker parentViewController] dismissModalViewControllerAnimated:YES];
    }
}

-(void) deleteImage:(UIButton *)sender{
    //NSLog(@"yyy%d",sender.tag);
    nr=sender.tag;
    UIActionSheet *actionSheet = [[UIActionSheet alloc] 
                                  initWithTitle:@"Delete image?" 
                                  delegate:self 
                                  cancelButtonTitle:@"No"
                                  destructiveButtonTitle:@"Yep" 
                                  otherButtonTitles:nil];
    [actionSheet showInView:self.view];
    [actionSheet release];

}
-(void) moveHorView{
    [horView scrollRectToVisible:CGRectMake((320*[bildes count]-320),0,320,163) animated:YES];
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)photoPicker {

    [photoPicker dismissModalViewControllerAnimated:YES];
}

- (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
    if (buttonIndex != [actionSheet cancelButtonIndex])
    {
        //deleting images from horView
        UIView* subview;
        while ((subview = [[horView subviews] lastObject]) != nil)
            [subview removeFromSuperview];

        //deleting image from tmp
        NSString *imagePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[bildesFileName objectAtIndex:nr]];
        if ([[NSFileManager defaultManager] fileExistsAtPath:imagePath])
        {
            [[NSFileManager defaultManager] removeItemAtPath:imagePath error:NULL];
        }

        //deleting image from arrays
        [bildes removeObjectAtIndex:nr];
        [bildesFileName removeObjectAtIndex:nr];


        //showing all images
        for (int i=0;i<[bildesFileName count]; i++) 
        {

            //adding image
            UIImageView *iw=[[UIImageView alloc] initWithImage:[UIImage imageWithData:[bildes objectAtIndex:i]]];
            [iw setFrame:CGRectMake((320*i)+50,5,220,153)]; //Adjust X,Y,W,H as needed
            iw.contentMode = UIViewContentModeScaleAspectFit;
            [horView addSubview:iw];
            [iw release];

            //adding delete button
            UIButton *deleteButton = [[UIButton buttonWithType:UIButtonTypeCustom] retain]; 
            [deleteButton setFrame:CGRectMake(320*i+320-50,10, 28, 28)];
            [deleteButton setImage:[UIImage imageNamed:@"deletebutton.png"] forState:UIControlStateNormal];

            [deleteButton addTarget:self action:@selector(deleteImage:) forControlEvents:UIControlEventTouchUpInside];
            [deleteButton setTag:i];
            [horView addSubview:deleteButton];
            [deleteButton release];
        }
        [horView setContentSize:CGSizeMake((320*[bildes count]), 163)]; 
        [horView scrollRectToVisible:CGRectMake((320 * nr),0,320,163) animated:YES];
        pageControl.numberOfPages = [bildes count];  
        pageControl.currentPage = [bildes count];
    }
}


#pragma mark -
#pragma mark UIScrollViewDelegate methods

-(void)scrollViewDidScroll:(UIScrollView *)sv
{
    //showing pageControl.currentPage
    pageControl.currentPage = floor((sv.contentOffset.x - 160) / 320) + 1;

}

@end

Я новичок в разработке для iOS, так что, возможно, произошла утечка памяти.Понятия не имею, что не так и как найти проблему: / Я пытался закомментировать некоторые функции, но ничего не помогло.

Ответы [ 3 ]

1 голос
/ 25 февраля 2011

Похоже, проблема была в UIImagePickerController и только в симуляторе (более подробно здесь: http://blog.airsource.co.uk/index.php/2008/11/12/memory-usage-in-uiimagepickercontroller/).На реальном устройстве все работает вполне нормально.

0 голосов
/ 25 февраля 2012

решено

У меня была такая же проблема при перечислении объектов coredata.

Не изменять подобъект, который использует ARRAY, на котором работает цикл

Мне нравится == >>

Если я изменяю / изменяю объект, находясь в цикле, это выдаст эту ошибку.

 for (LoadList *objLL in ArrLoadList) {             // here Enumaration is Going on
        // here I removed objects in ArrLoadList and reassign the ArrLoadList .. 
        // it will give me this error 
        // So Don't change the Main Array object 
 }
0 голосов
/ 25 февраля 2011

Я думаю, что проблема в этих строках кода

for (NSString *file in [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL]) 
{
    [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), file] error:NULL];
}

и вы используете его в двух методах didLoad и didUnload. Причина, по которой вы получаете, потому что вы обновляете содержимое следующего массива

[[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL]

Когда вы пройдете тщательный урок по перечислению, вы получите предупреждение о том, что «не обновляйте содержимое, пока используется перечислитель» ... Поэтому, чтобы преодолеть эту проблему, просто следуйте всем местам, где вы использовали этот код ....

NSArray* temp = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL];
for (NSString *file in temp) 
{
    [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@%@", NSTemporaryDirectory(), file] error:NULL];
}

Я надеюсь, что это решит вашу проблему ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...