2016年3月6日 星期日

iOS筆記:Swift練習(4)

Use MapKit

預設是沒有導入MapKit的, 如果需要使用的話, 可以從以下畫面將框架打開. Xcode會自動的將專案設定為啟動Mapkit.

再來就是要在專案的ViewController中加入 import MapKit.
enter image description here

Geocoder類別

Mapkit提供這個類別讓我們可以將文字地址轉換成經緯度. 另外也可以將經緯度轉換為一般的地址.

let geoCoder = CLGeocoder()
        geoCoder.geocodeAddressString("524 Ct St, Brooklyn, NY 11231", completionHandler: { placemarks, error in

            //地址的處理
        })

geocodeAddressString 接收的值沒有指定格式, 地址被解析之後會回傳一個地標物件的陣列. 回傳的物件的數字是依照你提供的地址資料來決定. 提供的越詳細回傳的結果就越準確. 如果標示的不夠準確可能會得到多個地標物件.

有了placemark物件就可以用以下方式取得地址了:

let coordinate = placemark.location.coordinate

completionHandler: { }是前面向Geocoding請求完成後要執行的程式碼.

地圖上加上大頭針

一般要加入一個標準的大頭針以及標示需要透過MKAnnotation的以下方法.
利用showAnnotations來放置大頭針.

// Add annotation
let annotation = MKPointAnnotation()
annotation.title = self.restaurant.name
annotation.coordinate = location.coordinate

// Display the annotation
self.mapView.showAnnotations([annotation], animated: true)
self.mapView.selectAnnotation(annotation, animated: true)

在大頭針旁加上圖像

如果要在大頭針旁加上圖像的縮圖就需要使用MapKit的MKMapViewDelegate中一個可選的func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?

  1. 加入Delegate:
class MapViewController: UIViewController, MKMapViewDelegate
  1. 在viewDidLoad中, 定義mapView的代理
mapView.delegate = self
  1. 實作 func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        let identifier = "MyPin"

        if annotation.isKindOfClass(MKUserLocation) {
            return nil
        }

        // Reuse the annotation if possible
        var annotationView:MKPinAnnotationView? = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier) as? MKPinAnnotationView

        if annotationView == nil {
            annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            annotationView?.canShowCallout = true
        }

        let leftIconView = UIImageView(frame: CGRectMake(0, 0, 53, 53))
        leftIconView.image = UIImage(named: restaurant.image)
        annotationView?.leftCalloutAccessoryView = leftIconView

        // Pin color customization
        annotationView?.pinTintColor = UIColor.orangeColor()

        return annotationView
    }

dequeueReusableAnnotationViewWithIdentifier 用來查看是否有任何沒有在使用的view可以使用, 有的話就轉換為MKPinAnnotationView

如果沒有的話就透過實體化的方式建立一個新的view

一些其他Map的自訂

a. 顏色:

annotationView?.pinTintColor = UIColor.orangeColor()

b. 客製化:

// Map customization
mapView.showsCompass = true //顯示器右上角會顯示指南針
mapView.showsScale = true   //顯示比例 
mapView.showsTraffic = true //顯示交通流量大的點

UIImagePickerController

UIKit提供這個方便的API用來從照片庫載入照片, 另外也支援一個可以拍照的相機介面.

此為當Cell被選取後會被呼叫. 這裡的條件式是想讓我們只從照片庫中提取照片.
接著呼叫presentViewController來帶出PhotoLibrary

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        if indexPath.row == 0 {
            if UIImagePickerController.isSourceTypeAvailable(.PhotoLibrary) {
                let imagePicker = UIImagePickerController()
                imagePicker.allowsEditing = false
                imagePicker.sourceType = .PhotoLibrary

                self.presentViewController(imagePicker, animated: true, completion: nil)
            }
        }

        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }

使用UIImagePickerController Delegate

需要透過Delegate才能將選取的照片傳回呼叫的ImageView.

  1. 如果想跟Image Picker互動, 首先要先新增兩個Delegate
    UIImagePickerControllerDelegate, UINavigationControllerDelegate

  2. 當使用者從照片庫挑選後, 下面這個方法會被呼叫.
    通過實行這個方法, 可以從方法的參數中取得被選取的照片.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        <#code#>
    }

Ex.

func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
        imageView.image = info[UIImagePickerControllerOriginalImage] as? UIImage
        imageView.contentMode = UIViewContentMode.ScaleAspectFill
        imageView.clipsToBounds = true

        dismissViewControllerAnimated(true, completion: nil)
    }
  1. 別忘記要讓 delegate = self

Auto layout in code

利用NSLayoutConstraint的API來加入約束條件.

let leadingConstraint = NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: imageView.superview, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
        leadingConstraint.active = true

        let trailingConstraint = NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: imageView.superview, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
        trailingConstraint.active = true

        let topConstraint = NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: imageView.superview, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
        topConstraint.active = true

        let bottomConstraint = NSLayoutConstraint(item: imageView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: imageView.superview, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
        bottomConstraint.active = true

預設約束條件在實體化後不會啟動, 必須設定active為true才行!

沒有留言:

張貼留言