简体   繁体   中英

iOS CoreSpotlight Thumbnail Image from URL

I'm trying to build a test app that uses CoreSpotlight to make content searchable in iOS Spotlight. Currently I have it setup to whenever the user taps a refresh button it makes a server request then deleteAllSearchableItems then indexSearchableItems (probably not the best way but easiest for right now, since I'm still in the beginning phases of figuring this out).

Below is my code that does that.

var searchableItems: [CSSearchableItem] = []
for i in 0 ..< self._ids.count {
    let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)

    attributeSet.title = self._titles[i]
    attributeSet.contentDescription = self._descriptions[i]

    let searchableItem = CSSearchableItem(uniqueIdentifier: self._ids[i], domainIdentifier: "com.domain.appname", attributeSet: attributeSet)

    searchableItems.append(searchableItem)
}

CSSearchableIndex.default().deleteAllSearchableItems(completionHandler: { (error) -> Void in
    CSSearchableIndex.default().indexSearchableItems(searchableItems) { (error) -> Void in
        if error != nil {
            print(error?.localizedDescription ?? "Error")
        }
    }
})

My next thing I'm trying to do is I have an array of images called self._images . Inside of that array is either an empty string ( "" ) or a string of a URL ( "https://mywebsite.com/image.png" ).

Currently I can use the code below to set the image of a UIImageView to the image at that URL, using AlamofireImage .

if (self._images[0] != "") {
    myImageView.af_setImage(withURL: URL(string: self._images[0])!)
}

How can I get that same image into the CoreSpotlight attributeSet?

I'm assuming attributeSet.thumbnailData.af_setImage(withURL: imagedownloadURL) won't work. Especially since it's async.

What would be the easiest way to integrate this?

I've tried a few things such as for loops and such but the biggest problem is the async and I can't seem to figure out a solution to do this since it's async and I have multiple items.

Thank you so much in advance!

Easiest solution but not the best one...

DispatchQueue.global(qos: .userInitiated).async {
    var searchableItems: [CSSearchableItem] = []
    for i in 0 ..< self._ids.count {
        let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeItem as String)
        attributeSet.title = self._titles[i]
        attributeSet.contentDescription = self._descriptions[i]
        let searchableItem = CSSearchableItem(uniqueIdentifier: self._ids[i], domainIdentifier: "com.domain.appname", attributeSet: attributeSet)

        if let imageUrl = URL(string: self._images[i]) {
            let urlRequest = URLRequest.init(url: imageUrl)
            if let cashedImage = UIImageView.af_sharedImageDownloader.imageCache?.image(for: urlRequest, withIdentifier: nil) {
                if let data = UIImageJPEGRepresentation(cashedImage, 1.0) {
                    attributeSet.thumbnailData = data
                }
            } else {
                if let data = NSData.init(contentsOf: imageUrl) {
                    attributeSet.thumbnailData = data as Data
                    if let image = UIImage.init(data: data as Data) {
                        let urlRequest = URLRequest.init(url: imageUrl)
                        UIImageView.af_sharedImageDownloader.imageCache?.add(image, for: urlRequest, withIdentifier: nil)
                    }
                }
            }
        }
        searchableItems.append(searchableItem)
    }

    CSSearchableIndex.default().deleteAllSearchableItems(completionHandler: { (error) -> Void in
        CSSearchableIndex.default().indexSearchableItems(searchableItems) { (error) -> Void in
            if error != nil {
                print(error?.localizedDescription ?? "Error")
            }
        }
    })
}

Edited

Why not the good solution? To avoid async issue, I have just put everything in one async closure and doing the sync image downloading.

UPDATE

Added default Alamofire cashing, before downloading it first look's for the cashed image now.

Here is a better solution using thumbnailURL or thumbnailData, since you have a cached images throw whetever alamofire, SDWebImage ...

it's simple and perfect performance wise

For thumbnailURL it accept only local paths:

  1. get the file path for the cached image
  2. create a URL object from the file path prefix with "file://"

"file://" . to indicate it's local path

    if let path = SDImageCache.shared().defaultCachePath(forKey: item.url_thumbnail), let url = URL(string: "file://\(path)") {
        attributeSet.thumbnailURL = url
    }

For thumbnailData :

just assign the local url path

attributeSet.thumbnailData = try? Data(contentsOf: url)

to debug and getting know what is going on simply just

 do {
     attributeSet.thumbnailData = try Data(contentsOf: url)
 }catch (let error as NSError){
      print(error)
 }

just please note I am using SDWebImage to get the cached image's path, since I am using it to cache the photos

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM