MFMailComposeViewController: прикрепление изображений из фотогалереи - PullRequest
1 голос
/ 06 марта 2012

У меня проблемы с прикреплением изображений из фотогалереи к электронному письму.

По сути, одна из функций моего приложения позволяет пользователю делать фотографии.Когда они делают снимок, я записываю ссылку URL на изображение в Core Data.Я понимаю, что вам нужно пройти через ALAssetRepresentation, чтобы добраться до изображения.У меня есть это и работает в моем приложении, когда пользователь хочет просмотреть изображение, которое он сделал.

Я сейчас пытаюсь разрешить пользователю прикрепить все фотографии, сделанные для события, к электронному письму,При этом я перебираю сущность Core Data, которая хранит URL-ссылки, вызывает метод, который возвращает UIImage из ALAssetsLibrary, а затем присоединяет его, используя NSData / UIImageJPEGRepresentation и MFMailComposeViewController / addAttachmentData методов.

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

Вот код:

- (void)sendReportReport
{

    if ([MFMailComposeViewController canSendMail])
    {

        MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];

        mailer.mailComposeDelegate = self;

        [mailer setSubject:@"Log: Report"];

        NSArray *toRecipients = [NSArray arrayWithObjects:@"someone@someco.com", nil];
        [mailer setToRecipients:toRecipients];


        NSError *error;

        NSFetchRequest *fetchPhotos = [[NSFetchRequest alloc] init];
        NSEntityDescription *entity = [NSEntityDescription 
                                       entityForName:@"Photo" inManagedObjectContext:__managedObjectContext];
        [fetchPhotos setEntity:entity];
        NSArray *fetchedPhotos = [__managedObjectContext executeFetchRequest:fetchPhotos error:&error];
        int counter;

        for (NSManagedObject *managedObject in fetchedPhotos ) {
            Photo *photo = (Photo *)managedObject;

//            UIImage *myImage = [UIImage imageNamed:[NSString stringWithFormat:@"%@.png", counter++]];
            NSData *imageData = UIImageJPEGRepresentation([self getImage:photo.referenceURL], 0.5);
//            NSData *imageData = UIImagePNGRepresentation([self getImage:photo.referenceURL]);
//            [mailer addAttachmentData:imageData mimeType:@"image/jpeg" fileName:[NSString stringWithFormat:@"%i", counter]];  
            [mailer addAttachmentData:imageData mimeType:@"image/jpeg" fileName:[NSString stringWithFormat:@"a.jpg"]];  

            counter++;

        }


        NSString *emailBody = [self getEmailBody];

        [mailer setMessageBody:emailBody isHTML:NO];

        [self presentModalViewController:mailer animated:YES];

    }
    else
    {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Failure"
                                                        message:@"Your device doesn't support the composer sheet"
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];

    }

}

и метод, который возвращает UIImage:

#pragma mark - Get Photo from Asset Library
+ (ALAssetsLibrary *)defaultAssetsLibrary {
    static dispatch_once_t pred = 0;
    static ALAssetsLibrary *library = nil;
    dispatch_once(&pred, ^{
        library = [[ALAssetsLibrary alloc] init];
    });
    return library; 
}

- (UIImage *)getImage:(NSString *)URLReference
{

    __block UIImage *xPhoto = nil;

    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
    {
        UIImage *xImage;

        // get the image
        ALAssetRepresentation *rep = [myasset defaultRepresentation];
        CGImageRef iref = [rep fullScreenImage];

        if (iref) {
            xImage = [UIImage imageWithCGImage:iref];
        }

        xPhoto = xImage;

    };


    ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
    {
        NSLog(@"Error fetching photo: %@",[myerror localizedDescription]);
    };


    NSURL *asseturl = [NSURL URLWithString:URLReference];

    // create library and set callbacks
    ALAssetsLibrary *al = [DetailsViewController defaultAssetsLibrary];
    [al assetForURL:asseturl 
        resultBlock:resultblock
       failureBlock:failureblock];   

    return xPhoto;

}

ПРИМЕЧАНИЕ. Этот код выше работает, он просто не прикрепляет изображение.Кроме того, обратите внимание, я могу успешно прикреплять изображения из галереи в моем приложении, пока я уже установил их в UIImageView .Image уже (в основном, я беру указатель на изображение из UIImageView ипередавая его методу addAttachmentData.) Только когда я пытаюсь перебрать Core Data и прикрепить без предварительной установки изображения в UIImageView, у меня возникают проблемы.

Любые советы будут оченьоценил!

Спасибо!Jason

1 Ответ

5 голосов
/ 07 марта 2012

О, теперь я вижу это .. sry.Вы используете асинхронный блок для получения изображения из библиотеки ресурсов.Но сразу после запуска этой операции вы возвращаете xImage.Но асинхронная операция закончится позже.Итак, вы возвращаете ноль.

Вам нужно изменить архитектуру на что-то вроде этого:

В вашем файле .h вам нужны два новых члена:

NSMutableArray* mArrayForImages;
NSInteger mUnfinishedRequests;

Вваш файл .m выглядит следующим образом:

- (void)sendReportReport
{
    // save image count
    mUnfinishedRequests = [fetchedPhotos count];

    // get fetchedPhotos
    [...]

    // first step: load images
    for (NSManagedObject *managedObject in fetchedPhotos )
    {
        [self loadImage:photo.referenceURL];    
    }
}

Измените свой метод getImage на loadImage:

- (void)loadImage:(NSString *)URLReference
{
    NSURL *asseturl = [NSURL URLWithString:URLReference];

    ALAssetsLibraryAssetForURLResultBlock resultblock = ^(ALAsset *myasset)
    {    
        // get the image
        ALAssetRepresentation *rep = [myasset defaultRepresentation];
        CGImageRef iref = [rep fullScreenImage];

        if (iref) {
            [mArrayForImages addObject: [UIImage imageWithCGImage:iref]];
        } else {
            // handle error
        }

        [self performSelectorOnMainThread: @selector(imageRequestFinished)];
    };

    ALAssetsLibraryAccessFailureBlock failureblock  = ^(NSError *myerror)
    {
        NSLog(@"Error fetching photo: %@",[myerror localizedDescription]);

        [self performSelectorOnMainThread: @selector(imageRequestFinished)];
    };


    // create library and set callbacks
    ALAssetsLibrary *al = [DetailsViewController defaultAssetsLibrary];
    [al assetForURL:asseturl 
        resultBlock:resultblock
       failureBlock:failureblock];
}

Создайте новый метод обратного вызова:

- (void) imageRequestFinished
{
    mUnfinishedRequests--;
    if(mUnfinishedRequests <= 0)
    {
       [self sendMail];
    }
}

Идополнительный способ для окончательной отправки почты после получения изображений:

- (void) sendMail
{
    // crate mailcomposer etc
    [...]

    // attach images
    for (UIImage *photo in mArrayForImages )
    {
                NSData *imageData = UIImageJPEGRepresentation(photo, 0.5);
                [mailer addAttachmentData:imageData mimeType:@"image/jpeg" fileName:[NSString stringWithFormat:@"a.jpg"]];
    }

    // send mail
    [...]
}
...