MFMailComposeViewController: прикрепление изображений из фотогалереи

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

В принципе, одна из функций моего приложения позволяет пользователю делать фотографии. Когда они делают снимок, я записываю ссылку 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.Изображение уже (в основном, я беру указатель на изображение из UIImageView и передать его addAttachmentData метод.) Это просто, когда я пытаюсь перебрать Core Data и присоединить без предварительной установки изображения в UIImageView что у меня проблема.

Любые советы будут с благодарностью!

Спасибо! Джейсон

1 ответ

Решение

Ох, теперь я вижу это.. 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
    [...]
}
Другие вопросы по тегам