问题
So I'm trying to search for local businesses in Swift using keywords like "bar", or "pizza". I linked the search to a button action so that the locations will pop up on the map within a defined region. However, I can't even get the application to load with user location because I get a nil error.
Here's my AppDelegate:
import UIKit
import CoreLocation
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
var locationManager: CLLocationManager?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
locationManager = CLLocationManager()
locationManager?.requestWhenInUseAuthorization()
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
And here's my ViewController.swift:
import Foundation
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
@IBAction func searchBars(sender: AnyObject) {
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "Bar"
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler({(response: MKLocalSearchResponse!, error: NSError!) in
if error != nil {
println("Error occurred in search: \(error.localizedDescription)")
} else if response.mapItems.count == 0 {
println("No matches found")
for item in response.mapItems as [MKMapItem] {
println("Name = \(item.name)")
println("Phone = \(item.phoneNumber)")
}
}
})
}
func mapView(mapView: MKMapView!, didUpdateUserLocation userLocation: MKUserLocation!) {
mapView.centerCoordinate = userLocation.location.coordinate
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
mapView.showsUserLocation = true
mapView.delegate = self
}
@IBAction func zoomIn(sender: AnyObject) {
let userLocation = mapView.userLocation
let region = MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate, 2000, 2000)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The line that returns the nil error is in my ViewController.swift file under @IBAction func zoomIn with the line: let region = MKCoordinateRegionMakeWithDistance(userLocation.location.coordinate, 2000, 2000). Which gives a nil value for some reason.
回答1:
What you're doing with this line is creating a mapView object which is not instantiated yet.
weak var mapView: MKMapView!
You get the error because you are trying to change showsUserLocation
property to an object which doesn't exist yet, it's nil.
What you need to do, if you created the map in a storyboard, is to remove the weak var line and put a IBOutlet
instead (Ctrl + Click and drag from the storyboard).
回答2:
Many thanks to Skoua for his help. I figured out what was wrong on my own after he helped me with the IBOutlet.
Here's the corrected code.
@IBAction func searchBars(sender: AnyObject) {
matchingItems.removeAll()
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "bar"
request.region = mapView.region
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler({(response: MKLocalSearchResponse!, error: NSError!) in
if error != nil {
println("Error occurred in search: \(error.localizedDescription)")
} else if response.mapItems.count == 0 {
println("No matches found")
//This is where the problem occured
} else {
println("Matches found")
//I needed to insert an else statement for matches being found
for item in response.mapItems as [MKMapItem] {
//This prints the 'matches' into [MKMapItem]
println("Name = \(item.name)")
println("Phone = \(item.phoneNumber)")
self.matchingItems.append(item as MKMapItem)
println("Matching items = \(self.matchingItems.count)")
var annotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
self.mapView.addAnnotation(annotation)
}
}
})
}
来源:https://stackoverflow.com/questions/28707991/swift-mapview-showuserlocation-true-returns-fatal-error-unexpectedly-foun