2017-09-16 2 views
0

Ich habe eine harte Zeit mit einem Bild herunterladen. Ich verwende eine Bild-URL von Firebase, um ein JPEG herunterzuladen und das Bild in einem Kartenansicht-Callout zu verwenden. Momentan wird das Callout in der richtigen Größe angezeigt, jedoch ohne Bild oder Untertitel. Es funktioniert perfekt, wenn ich ein Bild-Asset manuell übergebe. Die Bild-URL wird perfekt im newDog-Objekt gespeichert. Wenn ich das Bild debugge und überprüfe, erscheint es im Speicher, sieht aber leer aus.UIImage wird nicht geladen nach URLSession Data Task

Ich denke, vielleicht hat dies etwas mit dem Laden der Callout-Ansichten zu tun, bevor der Bild-Download abgeschlossen ist?

Hier ist meine viewDidLoad:

override func viewDidLoad() { 
    super.viewDidLoad() 

    self.map.mapType = .standard 
    self.map.showsUserLocation = true 
    self.map.userTrackingMode = .follow 
    self.map.delegate = self 
    self.map.mapType = .hybrid 
    let userDogRef = FIRDatabase.database().reference().child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("dogs") 

    userDogRef.observe(.childAdded, with: { (snapshot) in 
     if snapshot.value == nil { 
      print("no new dog found") 
     } else { 
      print("new dog found") 

      let snapshotValue = snapshot.value as! Dictionary<String, String> 
      let dogID = snapshotValue["dogID"]! 

      let dogRef = FIRDatabase.database().reference().child("dogs").child(dogID) 
      dogRef.observeSingleEvent(of: .value, with: { (snap) in 
       print("Found dog data!") 
       let value = snap.value as! Dictionary<String, String> 

       let name = value["name"]! 
       let breed = value["breed"]! 
       let creator = value["creator"]! 
       let score = Int(value["score"]!)! 
       let lat = Double(value["latitude"]!)! 
       let lon = Double(value["longitude"]!)! 
       let url = value["imageURL"]! 
       let location = CLLocationCoordinate2D(latitude: lat, longitude: lon) 

       let newDog = Dog() 
       newDog.name = name 
       newDog.breed = breed 
       newDog.creator = creator 
       newDog.score = score 
       newDog.imageURL = url 
       newDog.location = location 

       let downloadURL = URL(string: newDog.imageURL)! 
       URLSession.shared.dataTask(with: downloadURL, completionHandler: { (data, response, error) in 
        if error != nil { 
         print(error!) 
         return 
        } 
        newDog.picture = UIImage(data: data!)! 
        self.dogs.append(newDog) 
        let annotation = CustomAnnotation(location: newDog.location, title: newDog.name, subtitle: newDog.creator) 
        DispatchQueue.main.async { 
         self.map.addAnnotation(annotation) 
        } 

       }).resume() 
      }) 
     } 
    }) 
} 

Hier ist meine mapview und Annotation Methoden:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { 
    if(annotation is MKUserLocation){ 
     return nil 
    } 

    let ident = "pin" 

    var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: ident) 
    if annotationView == nil { 
     annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: ident) 
     annotationView?.canShowCallout = true 
    } else { 
     annotationView!.annotation = annotation 
    } 
    configureDetailView(annotationView!) 
    return annotationView 
} 

func configureDetailView(_ annotationView: MKAnnotationView) { 
    let width = 300 
    let height = 300 

    let dogPhotoView = UIView() 
    let views = ["dogPhotoView": dogPhotoView] 
    dogPhotoView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[dogPhotoView(\(height))]", options: [], metrics: nil, views: views)) 
    dogPhotoView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[dogPhotoView(\(width))]", options: [], metrics: nil, views: views)) 


    for dog in self.dogs { 
     let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height)) 
     imageView.image = dog.picture 
    } 

    annotationView.detailCalloutAccessoryView = dogPhotoView 
} 

ich eine benutzerdefinierte Annotation-Klasse bin mit. Hier ist das:

class CustomAnnotation: NSObject, MKAnnotation { 
    var coordinate : CLLocationCoordinate2D 
    var title: String? 
    var subtitle: String? 

    init(location: CLLocationCoordinate2D, title: String, subtitle: String) { 
     self.coordinate = location 
     self.title = title 
     self.subtitle = title 
     super.init() 
    } 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
} 

Hier ist ein Foto von meinem Debugger: enter image description here

Antwort

0

Das Problem trat beim Erstellen der Callout-Bildansicht auf. Ich habe ein ImageView erstellt, aber ich habe es nie als Subview seiner Superview hinzugefügt. Was für eine dumme Aufsicht! Hier ist der korrekte Code:

func configureDetailView(_ annotationView: MKAnnotationView) { 
    let width = 300 
    let height = 300 

    let dogPhotoView = UIView() 
    let views = ["dogPhotoView": dogPhotoView] 
    dogPhotoView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[dogPhotoView(\(height))]", options: [], metrics: nil, views: views)) 
    dogPhotoView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[dogPhotoView(\(width))]", options: [], metrics: nil, views: views)) 


    for dog in self.dogs { 
     let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height)) 
     imageView.image = dog.picture 

     DispatchQueue.main.async { 
      dogPhotoView.addSubview(imageView) 
      self.view.layoutIfNeeded() 
     } 

    } 

    annotationView.detailCalloutAccessoryView = dogPhotoView 
} 
0

dataTask asynchron arbeitet. Sie sollten zu Code wechseln, um die Annotation im Beendigungshandler zu erstellen.

URLSession.shared.dataTask(with: downloadURL, completionHandler: { (data, response, error) in 
    if error != nil { 
     print(error!) 
     return 
    } 
    newDog.picture = UIImage(data: data!)! 
    self.dogs.append(newDog) 
    let annotation = CustomAnnotation(location: newDog.location, title: newDog.name, subtitle: newDog.creator) 
    DispatchQueue.main.async { 
     self.map.addAnnotation(annotation) 
    } 

}).resume() 
+0

Ich versuchte dies, aber ich bekomme immer noch das gleiche Ergebnis. Bitte sehen Sie sich meinen bearbeiteten Code an. @vadian –

+1

Bearbeiten Sie den Code, der Vorschläge anwendet, nicht. Es verwirrt andere, die versuchen zu helfen – vadian

+0

Ich weiß das zu schätzen, darüber hatte ich vorher noch nicht nachgedacht. –

0

Verschieben self.map.addAnnotation(annotation) zu URLSession.shared.dataTask Abschluss-Handler. Momentan ist das Bild auf Dog-Objekt eingestellt, nachdem die Karte eine Annotation hinzugefügt hat. Vergessen Sie nicht, den Aufruf von addAnnotation (_ :) mit OperationQueue.main.addOperation zu umbrechen.

Verwandte Themen