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
}
}
IBOutletは正しく接続されていますか?地図が画面に表示されていますか? – tbilopavlovic
地図が画面に正しく表示されています。それがクラッシュするまで。 – TonyLanglet
それからmap nilでなく、 'forwardGeocoding'メソッドにブレークポイントを追加し、変数の値をチェックしてください。 – tbilopavlovic