2017-05-22 1 views
4

J'essaie de créer une application de test qui utilise CoreSpotlight pour rendre le contenu consultable dans iOS Spotlight. Actuellement, je l'ai configuré à chaque fois que l'utilisateur appuie sur un bouton de rafraîchissement, il fait une demande de serveur puis deleteAllSearchableItems puis indexSearchableItems (probablement pas le meilleur moyen mais plus facile pour le moment, puisque je suis encore au début des phases de comprendre cela).iOS CoreSpotlight Thumbnail Image de l'URL

Ci-dessous est mon code qui fait cela.

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

Ma prochaine chose que je suis en train de faire est que j'ai un tableau d'images appelées self._images. À l'intérieur de ce tableau est une chaîne vide ("") ou une chaîne d'une URL ("https://mywebsite.com/image.png").

Actuellement, je peux utiliser le code ci-dessous pour définir l'image d'un UIImageView à l'image à cette URL, en utilisant AlamofireImage.

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

Comment puis-je obtenir cette même image dans l'ensemble d'attributs CoreSpotlight?

Je suppose que attributeSet.thumbnailData.af_setImage(withURL: imagedownloadURL) ne fonctionnera pas. Surtout que c'est asynchrone.

Quelle serait la manière la plus simple de l'intégrer? J'ai essayé quelques choses comme pour les boucles et autres, mais le plus gros problème est l'asynchrone et je n'arrive pas à trouver une solution pour le faire car il est asynchrone et j'ai plusieurs éléments.

Merci beaucoup d'avance!

Répondre

2

solution, mais pas le plus simple meilleur ...

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

Edité

Pourquoi ne pas la bonne solution? Pour éviter un problème asynchrone, je viens de tout mettre dans une fermeture asynchrone et de faire le téléchargement de l'image de synchronisation.

MISE À JOUR

Ajouté par défaut Alamofire encaissement, avant de le télécharger d'abord regarder de la maintenant l'image encaissée.

+0

Pouvez-vous s'il vous plaît ajouter un peu plus en détail à votre réponse? Comment fonctionne exactement votre exemple de code? Et pourquoi n'est-ce pas la meilleure solution? Juste globalement plus de détails seraient utiles. –

+0

Ajouté quelques détails .. – Bilal

+0

Ce détail était utile. J'essaie toujours d'envelopper ma tête autour d'async vs sync en termes de Swift. Je vais voter votre réponse maintenant. Je n'attribue pas la prime et je n'accepte pas de réponse jusqu'à ce que la prime soit finie au cas où quelqu'un aurait une meilleure réponse ou quelque chose comme ça. Mais je vais accorder la prime à une question et accepter une réponse après la fin. Merci beaucoup. –

0

Voici une meilleure solution en utilisant thumbnailURL ou thumbnailData, puisque vous avez une des images mises en cache jeter Whetever alamofire, SDWebImage ...

ses performances simple et parfait sage

Pour thumbnailURL il accepte seulement locale chemins:

  1. obtenir le chemin du fichier pour l'image en cache
  2. créer un objet URL à partir du préfixe de chemin de fichier "File: //"

"file: //".pour indiquer qu'il est chemin local

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

Pour thumbnailData:

juste définir le chemin d'URL locale

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

à déboguer et obtenir savoir ce qui se passe tout simplement

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

juste s'il vous plaît noter que je utilise SDWebImage pour obtenir le chemin de l'image en cache, puisque je l'utilise pour mettre en cache les photos disponibles