2016-06-11 20 views
0

MKMapViewを使用するアプリケーションで作業していますが、MySQLからデータを読み込むPHPファイルに基づいてアノテーションを配置したいと考えています。私はiOSプログラミングに熟練しているわけではありませんが、私は学びますし、私にとって起こる問題に頭を下げることはできません。MapViewは関数でインスタンス化されていません

データをMSMutableArrayに取得してNSDirctionaryに変換し、オブジェクトごとにオブジェクトクラスを使用しています。マップ上にピン(注釈)を配置しようとするとエラーが発生するfatal error: unexpectedly found nil while unwrapping an Optional valueデバッグを見て、mapViewがnilであり、アノテーションを配置しようとすると、アノテーションを配置する場所を参照しています。

私は、オブジェクトの作成を行い、viewDidLoad()関数/メソッドでmapView.addAnnotation(オブジェクト)を呼び出すときに注釈を表示することができました。しかし、mapViewをクラス内の別の関数(ViewController)に入れ子にするときはいつでも、それは壊れます。

forwardGeoCodingメソッドは、プレーンテキストで取得したアドレスを座標に変換して、マップ上に正しく配置できるようにします。 setArrayは、MySQL/PHPクラスからデータをフェッチし、(注釈が、同様の内部で行われて悪い名前の標準)私はのMapViewを送信しようとした


  • のViewControllerで利用可能な配列を作るています私はせずにしようとしたのMapViewを呼び出してきた結果
  • ない関数に私は結果
  • せずにSQL検索クラスからそれをやってみました 結果
  • せずに機能self.mapView.addAnnotation(test)内のViewController を形成

ブレークポイント - mapViewコントロールがnilなので、forwardGeocoding関数を呼び出しているところでエラーが発生します。


ViewController.swift

// Created by Tony Langlet on 2016-05-18. 
// Copyright © 2016 Tony Langlet. All rights reserved. 
// 

import UIKit 
import MapKit 
import CoreLocation 

class ViewController: UIViewController, MKMapViewDelegate, HomeModelProtocal { 

    var feedItems: NSArray = NSArray() 
    var selectedLocation : LocationModel = LocationModel() 
    var popViewController : PopUpViewControllerSwift! = PopUpViewControllerSwift(nibName: "PopUpViewController", bundle: nil) 

    @IBOutlet weak var mapView: MKMapView! 

    required init?(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
    } 

    override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) { 
     super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     // Do any additional setup after loading the view, typically from a nib. 

     let deviceItem = UIScreen.mainScreen().traitCollection.userInterfaceIdiom 

     switch (deviceItem) { 
     case .Phone: 
      if UIScreen.mainScreen().scale == 3 { 
       popViewController = PopUpViewControllerSwift(nibName: "PopUpViewController_iPhone6Plus", bundle: nil) 
      } else { 
       popViewController = PopUpViewControllerSwift(nibName: "PopUpViewController_iPhone6", bundle: nil) 
      } 
     case .Pad: 
      popViewController = PopUpViewControllerSwift(nibName: "PopUpViewController_iPad", bundle: nil) 
     case .Unspecified: 
      popViewController = PopUpViewControllerSwift(nibName: "PopUpViewController", bundle: nil) 
     default: 
      popViewController = PopUpViewControllerSwift(nibName: "PopUpViewController", bundle: nil) 
     } 

     mapView.delegate = self 

     let homeModel = HomeModel() 
     homeModel.delegate = self 
     homeModel.downloadItems() 

    } 

    func itemsDownloaded(items: NSArray) { 
     feedItems = items 

     //self.listTableView.reloadData() 
    } 

    func setArray(array: NSMutableArray) { 
     var jsonElement: NSDictionary = NSDictionary() 

     for item in array { 
      jsonElement = item as! NSDictionary 
      let id = jsonElement["id"] as? String 
      let name = jsonElement["name"] as? String 
      let address = jsonElement["address"] as? String 
      let city = jsonElement["city"] as? String 
      let country = jsonElement["country"] as? String 
      let typ = jsonElement["typ"] as? String 
      let lastresult = jsonElement["lastresult"] as? String 

      let myaddress = ("\(address), \(city), \(country)") 
      //print(array) 
      forwardGeocoding(self.mapView, coordAddress: myaddress, id: id!, name: name!, address: address!, typ: typ!, lastresult: last result!) // <-- This is where it breaks. 

     } 
    } 

    func forwardGeocoding(mv: MKMapView, coordAddress: String, id: String, name: String, address: String, typ: String, lastresult: String) { 

     CLGeocoder().geocodeAddressString(coordAddress, completionHandler: { (placemarks, error) in 
      if error != nil { 
       print(error) 
       return 
      } 

      if placemarks?.count > 0 { 
       let placemark = placemarks?[0] 
       let location = placemark?.location 
       let coordinate = location?.coordinate 
       //print("\(name) \n\(address) \n\(typ) \n\(lastresult) \nlat: \(coordinate!.latitude), long: \(coordinate!.longitude)") 

       let test = restObject(id: id, name: name, address: address, coordinate: CLLocationCoordinate2D(latitude: (coordinate!.latitude), longitude: (coordinate!.longitude)), typ: typ, lastresult: lastresult) 


       mv.addAnnotation(test) 

      } 
     }) 
    } 


    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? { 
     let identifier = "restObject" 

     if annotation.isKindOfClass(restObject.self) { 
      if let annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) { 
       annotationView.annotation = annotation 
       return annotationView 
      } else { 
       let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier) 
       annotationView.enabled = true 
       annotationView.canShowCallout = true 

       let btn = UIButton(type: .DetailDisclosure) 
       annotationView.rightCalloutAccessoryView = btn 
       return annotationView 
      } 
     } 

     return nil 
    } 


    func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) { 
     let restaurant = view.annotation as! restObject 
     let name = restaurant.name 
     let address = restaurant.address 
     let typ = restaurant.typ 
     let lastresult = restaurant.lastresult 

     popViewController.title = title 
     popViewController.showInView(self.view, argStatusImg: UIImage(named: "icon-nogood"), argTitle: name, argAddress: address, argType: typ, argLastresult: lastresult, argDate: "2016-01-01", animated: true) 

    } 
} 

HomeModel.swift(PHP/MYSQLからのデータの取得)

// Created by Tony Langlet on 2016-06-10. 
// Copyright © 2016 Tony Langlet. All rights reserved. 
// 

import Foundation 

protocol HomeModelProtocal: class { 
    func itemsDownloaded(items: NSArray) 
} 

class HomeModel: NSObject, NSURLSessionDataDelegate { 

    weak var delegate: HomeModelProtocal! 

    var data : NSMutableData = NSMutableData() 

    let urlPath: String = "path to PHP file" 

    func downloadItems() { 

     let url: NSURL = NSURL(string: urlPath)! 
     var session: NSURLSession! 
     let configuration = NSURLSessionConfiguration.defaultSessionConfiguration() 

     session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil) 

     let task = session.dataTaskWithURL(url) 

     task.resume() 
    } 

    func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) { 
     self.data.appendData(data) 
    } 

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){ 
     if error != nil { 
      print("Failed to download data") 
     } else { 
      print("Data downloaded") 
      var jsonResult: NSMutableArray = NSMutableArray() 

      do { 
       jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray 
      } catch let error as NSError { 
       print(error) 
      } 

      let VC = ViewController() 
      VC.setArray(jsonResult) 

     } 
    } 
} 

restObject.swift(オブジェクトクラス)

// Created by Tony Langlet on 2016-05-18. 
// Copyright © 2016 Tony Langlet. All rights reserved. 
// 


import MapKit 
import UIKit 

class restObject: NSObject, MKAnnotation { 
    var id: String 
    var name: String 
    var address: String 
    var coordinate: CLLocationCoordinate2D 
    var typ: String 
    var lastresult: String 

    init(id: String, name: String, address: String, coordinate: CLLocationCoordinate2D, typ: String, lastresult: String) { 

     self.id = id 
     self.name = name 
     self.address = address 
     self.coordinate = coordinate 
     self.typ = typ 
     self.lastresult = lastresult 

    } 
} 
+0

IBOutletは正しく接続されていますか?地図が画面に表示されていますか? – tbilopavlovic

+0

地図が画面に正しく表示されています。それがクラッシュするまで。 – TonyLanglet

+0

それからmap nilでなく、 'forwardGeocoding'メソッドにブレークポイントを追加し、変数の値をチェックしてください。 – tbilopavlovic

答えて

0

EDIT 2:

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?){ 
    if error != nil { 
     print("Failed to download data") 
    } else { 
     print("Data downloaded") 
     var jsonResult: NSMutableArray = NSMutableArray() 

     do { 
      jsonResult = try NSJSONSerialization.JSONObjectWithData(self.data, options:NSJSONReadingOptions.AllowFragments) as! NSMutableArray 
     } catch let error as NSError { 
      print(error) 
     } 

     //let VC = ViewController() 
     //VC.setArray(jsonResult) 
     // Here you are creating new view controller, it's not same controller which you are seeing on screen, and in this init controllers view is not loaded from xib and that's why mapView is nil 
     delegate?.itemsDownloaded() 

    } 

EDIT:forwardGecodingにブレークポイントを追加し、すべての変数をチェックし、coordinateがnilであるかもしれない、とそこにそれが墜落しました。

override init(nibName nibNameOrNil: String!, bundle nibBundleOrNil: NSBundle!) { 
     super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) 
    } 

このメソッドでxibファイルの名前を渡して、ビューをロードする必要があります。 super.init(nibName: NAME_OF_XIB, bundle: nibBundleOrNil)

+0

私は 'popViewController = PopUpViewControllerSwift(nibName:" PopUpViewController_iPhone6 "、bundle:nil)'をsetArrayメソッドに追加しました。変更がないので、forwardGeocodingのMKMapView引数を削除し、最後に 'self.mapView.addAnnotation(test)'を追加しました。エラーは 'self.mapView.addAnnoation(test)'に移動しました。 – TonyLanglet

+0

MapViewが正しく接続されていますか?コントローラーに? '@IBOutlet weak var mapView:MKMapView!'の左に白い塗りつぶしの円がありますか? – tbilopavlovic

+0

はい、灰色:ish輪郭がそこにあります.http://i17.photobucket.com/albums/b51/Neroz/Skaumlrmavbild%202016-06-12%20kl.%2002.02.59.png – TonyLanglet

関連する問題