2 votes

Utilisation correcte de UIImagePickerController pour prendre des photos avec l'appareil photo ou les sélectionner dans la bibliothèque de l'iPhone

Ce que je veux faire, c'est utiliser toujours la même instance de UIImagePickerController dans toute mon application, puisque je ne veux pas allouer et détruire mon sélecteur à chaque fois que l'utilisateur prend une photo. L'application utilise un sélecteur et un UIImageView nommé pictureA pour afficher la photo choisie dans l'album de l'iPhone ou prise avec l'appareil photo.

Au départ, j'ai bloqué mon contrôleur de vue picker comme ceci :

    imagePickerController = [[UIImagePickerController alloc] init];
    imagePickerController.delegate = self;
    [self addSubview:imagePickerController.view];

Lorsque je prends une image dans le sélecteur et que je la place dans mon UIImageView :

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{

    // newImage is a UIImage do not try to use a UIImageView    
    UIImage *newImage = [info objectForKey:@"UIImagePickerControllerEditedImage"];

        [pictureA removeFromSuperview];

        CGRect myImageRect = CGRectMake(30.0f, 38.0f, 125.0f, 125.0f); 
        pictureA = [[UIImageView alloc] initWithFrame:myImageRect];
        pictureA.contentMode= UIViewContentModeScaleAspectFit;
        [pictureA setImage:newImage];
        pictureA.opaque = YES;
        [self addSubview:pictureA];

        [newImage release];

        [picker dismissModalViewControllerAnimated:YES];
        [picker.view setHidden:YES];

    }

Il choisit une image dans la bibliothèque de l'iPhone :

- (void) chooseImageFromLibrary {
    [imagePickerController.view setHidden:NO];
        imagePickerController.allowsEditing = YES;
    [imagePickerController viewWillAppear:YES];
    [imagePickerController viewDidAppear:YES];
}

Annuler :

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker{   
    [[picker parentViewController] dismissModalViewControllerAnimated:YES];
    [picker.view setHidden:YES];
}

- (void) takePicture {

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) 
    {
        [(MainScene*)[melonGame actualScene] setCameraDissabled:YES];
        return;
    }

    [imagePickerController.view setHidden:NO];

    imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera; 
    imagePickerController.allowsEditing = YES;

    [imagePickerController takePicture];

    [imagePickerController viewWillAppear:YES];
    [imagePickerController viewDidAppear:YES];
}

L'application fonctionne correctement lorsque je prends la première photo, mais lorsque j'essaie de prendre une autre photo ou de choisir une autre photo dans ma bibliothèque, elle ressemble exactement à la dernière fois que j'ai sélectionné une photo (avec la photo dans tout l'écran et un menu inactif pour choisir et annuler en bas de l'écran). Mon application ne fonctionne correctement que si je retire le contrôleur de ma vue et que je l'alloue à chaque fois que l'utilisateur prend une photo. Est-ce qu'il y a un moyen de "nettoyer" ou de "redémarrer" le sélecteur sans le libérer et le retirer de ma vue ?

Je ne suis pas sûr non plus de pouvoir instance une fois l'UIImageView ( pictureA) où je stocke l'image prise par l'imagePickerController et de la modifier à chaque fois que l'utilisateur prend une photo ou en choisit une dans l'album, je soupçonne qu'il est incorrect de la détruire et de la réallouer à chaque fois que l'utilisateur prend une photo. Des suggestions, des erreurs dans la gestion de la mémoire ou dans l'utilisation de UIImagePickerController et de UIImageView ?

merci !

0voto

Cameron Saul Points 755

Je ne pense pas que les UIImagePickerControllers soient destinés à être réutilisés. Quoi qu'il en soit, ils utilisent une TONNE de mémoire (en particulier la caméra), donc vous ne voulez pas les garder plus longtemps que nécessaire. Donc oui, vous devriez libérer le sélecteur d'image quand vous en avez fini avec lui, et en créer un nouveau quand vous voulez ajouter une autre image.

Vous devriez probablement présenter votre imagepicker de manière modale :

[self presentModalViewController:imagePickerController animated:YES];

Il n'est pas nécessaire de libérer la vue pictureA image chaque fois que vous souhaitez modifier l'image. Il suffit de modifier la propriété de l'image.

pictureA.image = newImage;

Si vous voulez instancier la vue de l'image la première fois que vous l'utilisez, faites quelque chose comme

if (!pictureA) {
    pictureA = [[UIImageView alloc] initWithFrame:aFrame];
}

pictureA.image = ...

Gardez à l'esprit qu'un appel à l'allocation nécessite un appel correspondant à la libération ou à la libération automatique. Lorsque vous avez alloué "pictureA" ci-dessus, son compte de conservation est devenu 1. L'appel à "[self addSubview:pictureA] ;" a augmenté son compte de conservation à 2. Lorsque vous avez appelé "[pictureA removeFromSuperview] ;" la fois suivante, le compte de conservation a été ramené à 1, et vous avez créé une nouvelle imageview. Ainsi, chaque fois que imagePickerController:didFinishPickingMediaWithInfo : est appelé, il y a une fuite de mémoire. Au lieu de cela, faites

[pictureA removeFromSuperview];
[pictureA release];

lorsque vous le retirez de la vue secondaire. Ou, mieux encore, faites de l'image une propriété de la classe :

@property (nonatomic, retain) UIImageView *pictureA;

qui libérera l'ancien imageView lorsque vous en assignerez un nouveau. Veillez simplement à libérer l'imageView lorsque vous l'attribuez :)

self.pictureA = [[[UIImageView alloc] init] autorelease];

o

UIImageView *imageView = [[UIImageView alloc] init];
self.pictureA = imageView;
[imageView release];

Personnellement, je m'en tiendrais au style autorelease car vous serez toujours en mesure de savoir d'un coup d'œil si vous allouez/désallouez correctement.

De plus, vous pouvez toujours vérifier votre gestion de la mémoire en utilisant Produit>Analyse dans Xcode 4.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X