无法在Swift iOS 8扩展中转换UIImage。

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时,它总是返回nil。以下是调试的屏幕截图,可能有所帮助。
更新:这里是接收到的图像的描述:
打印图像的描述:(NSSecureCoding!)图像= (instance_type = Builtin.RawPointer = 0x15d674c0 -> 0x32b6be5c(void *)0x32b6be70:NSURL)
我已经使用Objective C创建了相同的扩展程序,并且它可以工作,但在Swift中不起作用。以下是Objective 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;
    }
}

我尝试在谷歌上搜索了很多内容,但是没有找到任何有用的信息。我甚至尝试了修改代码,但是仍然无法解决问题。以下是修改后的代码:

                    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 仍然为 nil。这是 Swift 的 bug 吗?还是我的 Xcode 应用程序有问题。


你到底为什么要使用异步调度? - Atomix
1
可能会有许多图片可以接收,但现在我只处理一个用于调试的图像,因此当找到图像时我使用了break。因此,如果扩展程序接收到多个图像,我们可以异步地扫描这些图像。 - Sharon Nathaniel
你知道吗?在Swift中,你要分发的闭包和ObjC中的块是不同的。 - Atomix
不,Joe,我想我可能需要更多地研究它。但如果你能解释一下区别以及为什么这段代码不起作用;那将是一点指导。 - Sharon Nathaniel
@JoJoe,即使我改用块来编写代码,imageToSet仍然为nil。我将更新问题,并附上更改后的代码。 - Sharon Nathaniel
抱歉,我犯了一个错误。我误认为你发送的代码是不同的,但实际上它并不是。闭包和块本质上是相同的东西。不幸的是,在你的代码中我找不到任何问题。你应该尝试设置一个断点,逐步执行你的代码,并仔细观察每个变量发生的情况,看看在哪里出现异常。 - Atomix
3个回答

7

问题在于图像不是UIImage,而是NSURL

将代码更改为以下内容:

imageView.image = UIImage(data: NSData(contentsOfURL: image as NSURL)!)!

我会尝试并提供反馈。谢谢! - Sharon Nathaniel
我有一个问题,Objective-C允许你直接从完成块参数中获取图像数据,但Swift只返回296个字节的NSSecureCoding,尝试从中创建图像时会自然地导致nil。Simon,你(Simon)在上面提到的URL方法中有什么好办法吗?我将检查它是否解决我的问题,并在这里发布我的发现。 - Daniel Saidi
是的,它有效,我也曾为此苦苦挣扎。这适用于照片应用程序,我想知道是否可以提供一个来自我的应用程序的照片URL,因为那个照片不是每个人都可以访问的。 - Cristi Băluță
我简直不敢相信这么少的人看到了这个... 这是最新的Xcode iOS操作模板中的一个错误。 - Nick

3

您需要这样做

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

0

获取图像

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

无法将其转换为NSURL,并在以下表达式中获取nil

imageView.image = UIImage(data: NSData(contentsOfURL: image as NSURL)!)!

<UIImage: 0x16ecb410>, {100, 100} - mounika jakkampudi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接