2016-01-30 13 views
5

Uso CloudKit nella mia app come metodo per mantenere i dati in remoto. Uno dei miei record ha una proprietà CKAsset che contiene un'immagine. Quando raccolgo i record, mi sono reso conto che ci vuole così tanto tempo per finire la query. Dopo numerosi test, ho concluso che quando si interrogano i record, CloutKit scarica l'intero file Asset con l'oggetto record. Quindi, quando si ottiene l'oggetto dall'oggetto record e si richiede esso fileURL, esso fornisce un URL del percorso file locale e non un tipo HTTP di URL. Questo è un problema per me, perché devi lasciare che l'utente attenda così tanto tempo prima che la query finisca per scaricare l'intero record (con le immagini associate). Proveniente da uno sfondo Parse, Parse utilizzava l'URL HTTP e la query è abbastanza veloce da caricare l'interfaccia utente con gli oggetti durante il caricamento delle immagini asincrone. La mia domanda è, come posso ottenere ciò che Parse fa? Devo limitare le query a scaricare i dati delle risorse e ottenere un collegamento per caricare le immagini in modo asincrono.Ottenere l'URL CKAsset senza scaricare i dati

+0

non c'è url http. Puoi solo ottenere un URL locale. Come la risposta sotto puoi interrogare i dati senza la risorsa. –

risposta

1

Effettuare due chiamate separate per lo stesso record. La prima chiamata dovrebbe recuperare tutti i campi NON-asset che si desidera, e quindi la seconda richiesta dovrebbe recuperare le risorse richieste.

Qualcosa di simile:

let dataQueryOperation = CKQueryOperation(query: CKQuery(predicate: myPredicate) 
dataQueryOperation.desiredKeys = ["name", "age"] // etc 
database.addOperation(dataQueryOperation) 

let imageQueryOperation = CKQueryOperation(query: CKQuery(predicate: myPredicate) 
imageQueryOperation.desiredKeys = ["images"] 
database.addOperation(imageQueryOperation) 

Se necessità, refactoring questo in un metodo in modo da poter facilmente fare un nuovo CKQueryOperation per ogni campo di asset contenenti.

Buona caccia.

0

Come altri hanno già detto, non è possibile ottenere l'url (web) del CKAsset. Quindi le opzioni migliori sono 1. Utilizzare un'operazione di recupero con avanzamento per singolo UIImageView. Ne ho creato uno personalizzato che mostra un progresso all'utente. La cache non è inclusa ma puoi creare una classe e adottare NSCoding e salvare l'intero record nella directory della cache. Qui puoi vedere un recupero su cui ho completato il completamento per inviare la risorsa a dove la chiamo per combinarla con i miei altri dati.

 // only get the asset in this fetch. we have everything else 

Let funzionamento = CKFetchRecordsOperation (recordIDs: [myRecordID])

operation.desiredKeys = ["GameTurnImage"] 
     operation.perRecordProgressBlock = { 
      record,progress in 

      dispatch_async(dispatch_get_main_queue(), { 
       self.progressIndicatorView.progress = CGFloat(progress) 
      }) 

     } 

    operation.perRecordCompletionBlock = { 
     record,recordID,error in 
     if let _ = record{ 
      let asset = record!.valueForKey("GameTurnImage") as? CKAsset 

      if let _ = asset{ 

        let url = asset!.fileURL 
        let imageData = NSData(contentsOfFile: url.path!)! 
       dispatch_async(dispatch_get_main_queue(), { 

        self.image = UIImage(data: imageData) 
        self.progressIndicatorView.reveal() 

       }) 
       completion(asset!) 
      } 
     } 

    } 
    CKContainer.defaultContainer().publicCloudDatabase.addOperation(operation) 

L'altra opzione è quella di memorizzare le immagini su un server AWS o qualcosa di simile e quindi si può usare qualcosa come SDWebImage a fare tutto della cache o del sollevamento pesante e salva una stringa nel CKRecord nell'immagine.

Ho chiesto a più persone su una funzione CKset di esporre un URL. Non conosco JS Api per CloudKit, ma potrebbe esserci un modo per farlo, ma lascerò che gli altri se ne rendano conto.

3

È possibile utilizzare JavaScript di CloudKit per accedere all'url della risorsa. Ecco un esempio;

(Usato Alamofire e SwiftyJSON)

func testRecordRequest() -> Request { 
    let urlString = "https://api.apple-cloudkit.com/database/1/" + Constants.container + "/development/public/records/query?ckAPIToken=" + Constants.cloudKitAPIToken 
    let query = ["recordType": "TestRecord"] 
    return Alamofire.request(.POST, urlString, parameters: ["query": query], encoding: .JSON, headers: nil) 
} 

risposta JSON contiene un "downloadURL" per l'attività.

"downloadURL": "https://cvws.icloud-content.com/B/.../${f}?o=AmVtU..." 

"$ {f}" sembra una variabile, quindi cambialo in qualcosa che ti piace.

let downloadURLString = json["fields"][FieldNames.image]["value"]["downloadURL"].stringValue 
let recordName = json["recordName"].stringValue 
let fileName = recordName + ".jpg" 
let imageURLString = downloadURLString.stringByReplacingOccurrencesOfString("${f}", withString: fileName) 

E ora possiamo usare questa urlString per creare un NSURL e utilizzarlo con qualsiasi soluzione di cache immagine & quali Kingfisher, HanekeSwift etc. (Si potrebbe anche voler salvare il tipo di immagine png/jpg)

+0

Trucco impressionante @anilgoktas, ho un dubbio, qual è la [Keys.image]? – drdrdrdr

+1

@drdrdrdr [Keys.image] -> nome del campo dell'immagine sul tipo di record. Puoi verificarlo sulla dashboard di CloudKit. E 'stato confuso, appena cambiato. Grazie – anilgoktas

+0

@anilgoktas Questa richiesta restituisce "serverErrorCode =" AUTHENTICATION_REQUIRED ";" 'con redirectURL alla pagina web di accesso. Come hai superato questo? –