Saturday, October 25, 2014

NSThread.detachNewThreadSelector

    override func viewDidLoad() {
        super.viewDidLoad()
        
        NSThread.detachNewThreadSelector(Selector("mythread"), toTarget: self, withObject: nil)
        
        println("End viewDidLoad()")
    }

    func mythread() {
        NSThread.sleepForTimeInterval(1.0)
        for var i = 1 ; i <= 5 ; i++ {
            println("\(i)")
        }
    }

==========================
Output:

End viewDidLoad()
1
2
3
4
5

Monday, October 6, 2014

MKDirections - Draw a route from location A to location B

Updated with Xcode 8.0 (Swift 3) on September 19, 2016.
Updated with Xcode 7.3.1 (Swift 2.2) on June 15, 2016.
Updated as a simple tutorial on May 25, 2015.

1. Disable 'Use Auto Layout' in the storyboard file inspector.

2. Drag a MapKit View to the storyboard.



3. Control-drag the MapKit View from the storyboard to ViewController.swift. Name the MapKit 'myMap'.



The result is:

@IBOutlet weak var myMap: MKMapView!

4. Complete the code as below:

Update (September 19, 2016): Xcode 8.0 (Swift 3)


import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var myMap: MKMapView!
    
    var myRoute : MKRoute!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let point1 = MKPointAnnotation()
        let point2 = MKPointAnnotation()
        
        point1.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point1.title = "Taipei"
        point1.subtitle = "Taiwan"
        myMap.addAnnotation(point1)
        
        point2.coordinate = CLLocationCoordinate2DMake(24.9511, 121.2358)
        point2.title = "Chungli"
        point2.subtitle = "Taiwan"
        myMap.addAnnotation(point2)
        myMap.centerCoordinate = point2.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point2.coordinate, MKCoordinateSpanMake(0.7,0.7)), animated: true)
        
        let directionsRequest = MKDirectionsRequest()
        let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point1.coordinate.latitude, point1.coordinate.longitude), addressDictionary: nil)
        let markChungli = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point2.coordinate.latitude, point2.coordinate.longitude), addressDictionary: nil)
        
        directionsRequest.source = MKMapItem(placemark: markChungli)
        directionsRequest.destination = MKMapItem(placemark: markTaipei)
        
        directionsRequest.transportType = MKDirectionsTransportType.automobile
        let directions = MKDirections(request: directionsRequest)
        
        directions.calculate(completionHandler: {
            response, error in
            
            if error == nil {
                self.myRoute = response!.routes[0] as MKRoute
                self.myMap.add(self.myRoute.polyline)
            }
            
        })
    }
    
    func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
        
        let myLineRenderer = MKPolylineRenderer(polyline: myRoute.polyline)
        myLineRenderer.strokeColor = UIColor.red
        myLineRenderer.lineWidth = 3
        return myLineRenderer
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

======

Update (June 15, 2016): Xcode 7.3.1 (Swift 2.2)


import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {
    
    @IBOutlet weak var myMap: MKMapView!
    
    var myRoute : MKRoute!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        let point1 = MKPointAnnotation()
        let point2 = MKPointAnnotation()
        
        point1.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point1.title = "Taipei"
        point1.subtitle = "Taiwan"
        myMap.addAnnotation(point1)
        
        point2.coordinate = CLLocationCoordinate2DMake(24.9511, 121.2358)
        point2.title = "Chungli"
        point2.subtitle = "Taiwan"
        myMap.addAnnotation(point2)
        myMap.centerCoordinate = point2.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point2.coordinate, MKCoordinateSpanMake(0.7,0.7)), animated: true)
        
        let directionsRequest = MKDirectionsRequest()
        let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point1.coordinate.latitude, point1.coordinate.longitude), addressDictionary: nil)
        let markChungli = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point2.coordinate.latitude, point2.coordinate.longitude), addressDictionary: nil)
        
        directionsRequest.source = MKMapItem(placemark: markChungli)
        directionsRequest.destination = MKMapItem(placemark: markTaipei)

        directionsRequest.transportType = MKDirectionsTransportType.Automobile
        let directions = MKDirections(request: directionsRequest)

        directions.calculateDirectionsWithCompletionHandler({
            response, error in
            
            if error == nil {
                self.myRoute = response!.routes[0] as MKRoute
                self.myMap.addOverlay(self.myRoute.polyline)
            }
        
        })
    }
    
    func mapView(mapView: MKMapView, rendererForOverlay overlay: MKOverlay) -> MKOverlayRenderer {
        
        let myLineRenderer = MKPolylineRenderer(polyline: myRoute.polyline)
        myLineRenderer.strokeColor = UIColor.redColor()
        myLineRenderer.lineWidth = 3
        return myLineRenderer
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

======

Previous Post (May 25, 2015):
import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var myMap: MKMapView!
    
    var myRoute : MKRoute?
    
    override func viewDidLoad() {
        super.viewDidLoad()

        var point1 = MKPointAnnotation()
        var point2 = MKPointAnnotation()
        
        point1.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point1.title = "Taipei"
        point1.subtitle = "Taiwan"
        myMap.addAnnotation(point1)
        
        point2.coordinate = CLLocationCoordinate2DMake(24.9511, 121.2358)
        point2.title = "Chungli"
        point2.subtitle = "Taiwan"
        myMap.addAnnotation(point2)
        myMap.centerCoordinate = point2.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point2.coordinate, MKCoordinateSpanMake(0.7,0.7)), animated: true)
        
        var directionsRequest = MKDirectionsRequest()
        let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point1.coordinate.latitude, point1.coordinate.longitude), addressDictionary: nil)
        let markChungli = MKPlacemark(coordinate: CLLocationCoordinate2DMake(point2.coordinate.latitude, point2.coordinate.longitude), addressDictionary: nil)
        
        directionsRequest.setSource(MKMapItem(placemark: markChungli))
        directionsRequest.setDestination(MKMapItem(placemark: markTaipei))
        directionsRequest.transportType = MKDirectionsTransportType.Automobile
        var directions = MKDirections(request: directionsRequest)
        directions.calculateDirectionsWithCompletionHandler { (response:MKDirectionsResponse!, error: NSError!) -> Void in
            if error == nil {
                self.myRoute = response.routes[0] as? MKRoute
                self.myMap.addOverlay(self.myRoute?.polyline)
            }
        }
    }
    
    func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
        
        var myLineRenderer = MKPolylineRenderer(polyline: myRoute?.polyline!)
        myLineRenderer.strokeColor = UIColor.redColor()
        myLineRenderer.lineWidth = 3
        return myLineRenderer
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

5. The result:




Saturday, October 4, 2014

mapView(_:viewForAnnotation:)- pinColor - Change the pin color on the map

Update April 11, 2016:
Draw the map and pin programmatically in Swift 2.2 with Xcode 7.3.

import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let point = MKPointAnnotation()
        point.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point.title = "Taipei"
        point.subtitle = "Taiwan"
        
        let myMap = MKMapView(frame: CGRectMake(0,20, view.frame.width, view.frame.height-20))

        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
            
            dispatch_async(dispatch_get_main_queue()) {
                myMap.addAnnotation(point)
                print("addAnnotation")
            }
        }

        myMap.centerCoordinate = point.coordinate
        myMap.delegate = self
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(myMap.centerCoordinate, MKCoordinateSpanMake(0.2,0.2)), animated: true)
        
        view.addSubview(myMap)
        print("addSubview(myMap)")
    }
    
    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        
        let annotationView = MKPinAnnotationView()
        annotationView.pinTintColor = UIColor.orangeColor()
        
        print("Pin Color Set")
        
        return annotationView
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Result:

Debug Console:

addSubview(myMap)
addAnnotation
Pin Color Set

Simulator:



=======

Original post October 4, 2014:

import UIKit
import CoreLocation
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {

    @IBOutlet weak var myMap: MKMapView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        var point = MKPointAnnotation()
        self.myMap.delegate = self
        
        point.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point.title = "Taipei"
        point.subtitle = "Taiwan"
        myMap.addAnnotation(point)
        myMap.centerCoordinate = point.coordinate
        myMap.selectAnnotation(point, animated: true)
        
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point.coordinate, MKCoordinateSpanMake(0.2,0.2)), animated: true)
        println("Span of the map")
    }                                                                                                                                                            


    func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
        
        if (annotation.isKindOfClass(MKUserLocation)){
            return nil
        }
        var myPin = mapView.dequeueReusableAnnotationViewWithIdentifier("MyIdentifier") as? MKPinAnnotationView
        if myPin != nil {
            return myPin
        }
        
        myPin = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "MyIdentifier")
        myPin?.pinColor = .Green
        return myPin
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

Wednesday, October 1, 2014

CLGeocoder().geocodeAddressString - Show the input address on the map

1. Add the mapkit and a UITextField in the storyboard and edit the code as below:

import MapKit
import CoreLocation
import AddressBookUI

@IBOutlet weak var theMap: MKMapView!

class ViewController: UIViewController, CLLocationManagerDelegate {

Also include the MapKit and CoreLocation frameworks in the project.


2. Control-drag the text field to the Swift file and set:

Connection: Action
Name: addressInput
Type: UITextField
Event: Did End On Exit
Arguments: Sender

and click "connect."

3. Edit the code as below:

    @IBAction func addressInput(sender: UITextField) {
        var placemark: CLPlacemark!
        
        CLGeocoder().geocodeAddressString(sender.text, completionHandler: {(placemarks, error)->Void in
            if error == nil {
                
                placemark = placemarks[0] as CLPlacemark
                
                self.theMap.setRegion(MKCoordinateRegionMake(CLLocationCoordinate2DMake (placemark.location.coordinate.latitude, placemark.location.coordinate.longitude), MKCoordinateSpanMake(0.002, 0.002)), animated: true)
            }
        })

    }