Невозможно преобразовать UIImage в быстрое расширение iOS 8

У меня странная проблема, я пытаюсь создать расширение действия, которое будет сканировать штрих-код с предоставленного изображения. Вот код.

override func viewDidLoad() {
    super.viewDidLoad()

    // Get the item[s] we're handling from the extension context.

    // For example, look for an image and place it into an image view.
    // Replace this with something appropriate for the type[s] your extension supports.
    var imageFound = false
    for item: AnyObject in self.extensionContext!.inputItems {
        let inputItem = item as NSExtensionItem
        for provider: AnyObject in inputItem.attachments! {
            let itemProvider = provider as NSItemProvider
            if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as NSString) {
                // This is an image. We'll load it, then place it in our image view.
                weak var weakImageView = self.imageView
                itemProvider.loadItemForTypeIdentifier(kUTTypeImage as NSString, options: nil, completionHandler: { (image, error) in
                    if image != nil {
                        dispatch_async(dispatch_get_main_queue(),{
                            if let imageView = weakImageView {
                                var imageToSet: UIImage? = image as? UIImage
                                imageView.image = image as? UIImage
                            }

                            self.imageToScan = self.imageView.image
                            self.scanFromImage(self.imageToScan!)
                        })
                    }
                })

                imageFound = true
                break
            }
        }

        if (imageFound) {
            // We only handle one image, so stop looking for more.
            break
        }
    }
}

Теперь, когда я пытаюсь получить UIImage, я всегда получаю nil, тогда как на изображении я вижу, что изображение получено. Но когда я пытаюсь получить UIImage из этого изображения, он всегда возвращает ноль. Вот снимок экрана отладки, который может помочь

imageToSet«Консоль» Полный снимок

Обновление: вот описание изображения, полученного как:

Вывод описания изображения: (NSSecureCoding!) image = (instance_type = Builtin.RawPointer = 0x15d674c0 -> 0x32b6be5c (void *)0x32b6be70: NSURL)

Я создал такое же расширение, используя цель C, и оно работает, но не быстро. Вот объективный код C:

- (void)viewDidLoad {
[super viewDidLoad];

// Get the item[s] we're handling from the extension context.

// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
BOOL imageFound = NO;
for (NSExtensionItem *item in self.extensionContext.inputItems) {
    for (NSItemProvider *itemProvider in item.attachments) {
        if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeImage]) {
            // This is an image. We'll load it, then place it in our image view.
            __weak UIImageView *imageView = self.imageView;
            [itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeImage options:nil completionHandler:^(UIImage *image, NSError *error) {
                if(image) {
                     dispatch_async(dispatch_get_main_queue(), ^{
                        [imageView setImage:image];
                        imageToScan = image;
                        [self scanImage:imageToScan];
                    });
                }
            }];

            imageFound = YES;
            break;
        }
    }

    if (imageFound) {
        // We only handle one image, so stop looking for more.
        break;
    }
}

}

Я пытался много искать в Google, но ничего не нашел. Я даже пробовал измененный код, но он не работает, вот измененный код:

                    itemProvider.loadItemForTypeIdentifier(kUTTypeImage as NSString, options: nil, completionHandler: { (image, error) in
                    if image != nil {
                        NSOperationQueue.mainQueue().addOperationWithBlock {
                            if let imageView = weakImageView {
                                var imageToSet: UIImage? = image as? UIImage
                                imageView.image = image as? UIImage
                            }

                            self.imageToScan = self.imageView.image
                            self.scanFromImage(self.imageToScan)
                        }
                    }
                })

Обновление: я заметил одну вещь; если я создаю новый проект и добавляю к нему расширение действия, автоматически генерируется тот же код, за исключением нескольких строк, которые я добавил в блок. В этом случае даже без изменения одной строки автоматически сгенерированного кода imageView.image равен нулю. Это ошибка в Swift?? Или какая-то ошибка с моим приложением Xcode.


person Sharon Nathaniel    schedule 17.09.2014    source источник
comment
С какой стати вы используете асинхронную отправку?   -  person Atomix    schedule 17.09.2014
comment
Может быть много изображений, которые мы можем получить, сейчас я обрабатываю только одно изображение для отладки, поэтому я использовал разрыв, когда изображение найдено. Поэтому, если расширение получает более одного изображения, мы можем сканировать эти изображения асинхронно.   -  person Sharon Nathaniel    schedule 17.09.2014
comment
Знаете ли вы, что закрытие, которое вы отправляете в Swift, отличается от блока в ObjC?   -  person Atomix    schedule 17.09.2014
comment
Нет, Джо, я думаю, что мне, возможно, придется изучить это больше. Но если вы можете объяснить, в чем разница и почему этот код не работает; это было бы небольшим руководством.   -  person Sharon Nathaniel    schedule 17.09.2014
comment
@JoJoe, даже если я изменю свой код на использование блока, imageToSet по-прежнему равен нулю. Я обновляю вопрос с измененным кодом.   -  person Sharon Nathaniel    schedule 17.09.2014
comment
Жаль, что я сделал ошибку. Я думал, что код, который вы отправляете, был другим, но это не так. Замыкания и блоки — это, по сути, одно и то же. К сожалению, я ничего не могу найти в вашем коде. Вы должны попытаться установить точку останова и пройтись по коду, внимательно наблюдая за тем, что происходит с каждой переменной, и видеть, где она ведет себя странно.   -  person Atomix    schedule 17.09.2014


Ответы (3)


дело в том, что картинка не UIImage, а NSURL.

Измените код на этот:

imageView.image = UIImage(data: NSData(contentsOfURL: image as NSURL)!)!
person d.lebedev    schedule 06.11.2014
comment
Я попробую это и оставлю отзыв. Спасибо! - person Sharon Nathaniel; 10.11.2014
comment
У меня есть проблема, когда Objective-C позволяет вам получать данные изображения непосредственно из параметров блока завершения, но где Swift просто возвращает NSSecureCoding из 296 байтов, что (естественно) приводит к нулю при попытке создать изображение из него. Вам (Саймону) повезло с описанным выше URL-подходом? Я проверю, решит ли это мою проблему, и опубликую свои выводы здесь. - person Daniel Saidi; 12.11.2014
comment
Да, это работает, я тоже боролся с этим. Это относится к приложению для фотографий, мне интересно, дает ли URL-адрес для фотографии из моего собственного приложения, так как к нему не могут получить доступ все. - person Cristi Băluță; 25.11.2014
comment
Я не могу поверить, как мало людей видели это... Это ошибка в последнем шаблоне действий Xcode для iOS. - person Nick; 29.12.2014

Вам нужно сделать так

    if let strongImageView = weakImageView {

                   if let imageURL = image as? NSURL{

                 strongImageView.image = UIImage(data:NSData(contentsOfURL: imageURL)!)

                    }else{

                      strongImageView.image = image as? UIImage
                    }

                }

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

override func viewDidLoad() {
super.viewDidLoad()


// Get the item[s] we're handling from the extension context.

// For example, look for an image and place it into an image view.
// Replace this with something appropriate for the type[s] your extension supports.
var imageFound = false
for item: AnyObject in self.extensionContext!.inputItems {
    let inputItem = item as! NSExtensionItem
    for provider: AnyObject in inputItem.attachments! {
        let itemProvider = provider as! NSItemProvider
        if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
            // This is an image. We'll load it, then place it in our image view.
            weak var weakImageView = self.imageView
            itemProvider.loadItemForTypeIdentifier(kUTTypeImage as String, options: nil, completionHandler: { (image, error) in
                NSOperationQueue.mainQueue().addOperationWithBlock {


                if let strongImageView = weakImageView {

                       if let imageURL = image as? NSURL{

                     strongImageView.image = UIImage(data:NSData(contentsOfURL: imageURL)!)

                        }else{

                          strongImageView.image = image as? UIImage
                        }

                    }


                }
            })

            imageFound = true
            break
        }
    }

    if (imageFound) {
        // We only handle one image, so stop looking for more.
        break
    }
}
}
person Sanju    schedule 24.02.2016

Получение изображения как

<UIImage: 0x16ecb410>, {100, 100}

Его нельзя привести к типу NSURL и получить nil в следующем выражении.

imageView.image = UIImage(data: NSData(contentsOfURL: image as NSURL)!)!
person mounika jakkampudi    schedule 29.04.2015
comment
‹UIImage: 0x16ecb410›, {100, 100} - person mounika jakkampudi; 29.04.2015