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)
            }
        })

    }

Tuesday, September 30, 2014

CLGeocoder().reverseGeocodeLocation - Show the address of the current location

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


import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

@IBOutlet weak var myAddress: UILabel!

Also include the CoreLocation framework in the project.

2. Edit the info.plist file by adding these two items:


NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription

3. Edit the code as below:


override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        
    }

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
        
        var placemark: CLPlacemark!
        locationManager.stopUpdatingLocation()
        
        CLGeocoder().reverseGeocodeLocation(manager.location, completionHandler: {(placemarks, error)->Void in
            if error == nil && placemarks.count > 0 {
                placemark = placemarks[0] as CLPlacemark

                var addressString : String = ""
                if placemark.ISOcountryCode == "TW" /*Address Format in Chinese*/ {
                    if placemark.country != nil {
                        addressString = placemark.country
                    }
                    if placemark.subAdministrativeArea != nil {
                        addressString = addressString + placemark.subAdministrativeArea + "\n"
                    }
                    if placemark.postalCode != nil {
                        addressString = addressString + placemark.postalCode + " "
                    }
                    if placemark.locality != nil {
                        addressString = addressString + placemark.locality
                    }
                    if placemark.thoroughfare != nil {
                        addressString = addressString + placemark.thoroughfare
                    }
                    if placemark.subThoroughfare != nil {
                        addressString = addressString + placemark.subThoroughfare
                    }
                } else {
                    if placemark.subThoroughfare != nil {
                        addressString = placemark.subThoroughfare + " "
                    }
                    if placemark.thoroughfare != nil {
                        addressString = addressString + placemark.thoroughfare + "\n"
                    }
                    if placemark.postalCode != nil {
                        addressString = addressString + placemark.postalCode + " "
                    }
                    if placemark.locality != nil {
                       addressString = addressString + placemark.locality + "\n"
                    }
                    if placemark.administrativeArea != nil {
                        addressString = addressString + placemark.administrativeArea + " "
                    }
                    if placemark.country != nil {
                        addressString = addressString + placemark.country
                    }
                }
                self.myAddress.text = addressString
            }
        })
        

    }

Saturday, September 27, 2014

MapKit - Show the current location

Update: April 27, 2017 with Xcode 8.3.2 (Swift 3.1).

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

import CoreLocation
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {

@IBOutlet weak var theMap: MKMapView!

2. Edit the info.plist file by adding these two items:

NSLocationWhenInUseUsageDescription
NSLocationAlwaysUsageDescription (Update: This is not essential)

3. Edit the code as below:

Update:
April 27, 2017 with Xcode 8.3.2 (Swift 3.1)

import UIKit
import CoreLocation
import MapKit

class ViewController: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {

    @IBOutlet weak var theMap: MKMapView!
    
    //Declare locationManager here to prevent location access message from disappearance.
    var locationManager : CLLocationManager!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        
        theMap.delegate = self
        theMap.mapType = MKMapType.standard
        theMap.showsUserLocation = true
    }
    
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        if(!locations.isEmpty)
        {
            let myLocation = locations[0] as CLLocation
            
            theMap.setRegion(MKCoordinateRegionMake(myLocation.coordinate, MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)), animated: true)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

}

Original Post:
September 27, 2014 with Xcode 6 (Swift 1)

    var locationManager : CLLocationManager!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        locationManager = CLLocationManager()
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.requestWhenInUseAuthorization()
        locationManager.startUpdatingLocation()
        
        theMap.delegate = self
        theMap.mapType = MKMapType.Standard
        theMap.showsUserLocation = true


    }

    func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
        
        if (!locations.isEmpty)
        {


            let myLocation  = locations[0] as! CLLocation
            


            theMap.setRegion(MKCoordinateRegionMake(CLLocationCoordinate2DMake(myLocation.coordinate.latitude, myLocation.coordinate.longitude), MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01)), animated: true)
        }

    }

Monday, September 22, 2014

MKMapItem - openMapsWithItems - from current location to another location


coordinate -> placemark -> mapitem -> array of mapitems -> openMapsWithItems



****
import MapKit

****

let currentLocation = MKMapItem.mapItemForCurrentLocation()
        
let markTaipei = MKPlacemark(coordinate: CLLocationCoordinate2DMake(25.0305, 121.5360), addressDictionary: nil)
        
let taipei = MKMapItem(placemark: markTaipei)
        
taipei.name = "Taipei Daan Park"
        
let array = NSArray(objects: currentLocation, taipei)
        
let parameter = NSDictionary(object: MKLaunchOptionsDirectionsModeDriving, forKey: MKLaunchOptionsDirectionsModeKey)
        

MKMapItem.openMapsWithItems(array, launchOptions: parameter)

Thursday, September 11, 2014

MKPointAnnotation - Put a pin on a map

import MapKit
import CoreLocation

@IBOutlet weak var myMap: MKMapView!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        var point = MKPointAnnotation()
        
        point.coordinate = CLLocationCoordinate2DMake(25.0305, 121.5360)
        point.title = "Taipei"
        point.subtitle = "Taiwan"
        myMap.addAnnotation(point)
        myMap.centerCoordinate = point.coordinate
        
        //Span of the map
        myMap.setRegion(MKCoordinateRegionMake(point.coordinate, MKCoordinateSpanMake(7,7)), animated: true)
    }

Friday, September 5, 2014

UITableView

Here is how to create a simple table view with Swfit and the storyboard:

1. Drag a table view in the storyboard

2. In the Connections Inspector, link the dataSource and delegate outlets to View Controller.

3. Add UITableViewDelegate and UITableViewDataSource protocols in ViewController.swift

class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource{
....
}

where
UIViewController = super class (before the first protocol)
UITableViewDelegate = first protocol
UITableViewDataSource = second protocol

Note: the warning occurs because cellForRowAtIndexPath and numberOfRowsInSection are required.

4. Add an array to be printed in the table

let myArray = ["AAA", "BBB", "CCC"]

5. Set the number of rows

func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return myArray.count }


6. Set the table content

func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { let cell = UITableViewCell(style: UITableViewCellStyle.Value2, reuseIdentifier: nil) cell.textLabel.text = myArray[indexPath.row] return cell }

**********************
UITableView without using the Storyboard