SlideShare a Scribd company logo
凡走過必留留下痕跡

Apple Map
Swift Girls Part 8

20170904
張筱姍
張筱姍

HsiaoShan Chang
⽬目前最愛寫程式跟織⽑毛線。
⽬目標是開發出⼿手作相關⼯工具或平台讓⼤大家可以快樂
的做⼿手作!
KCCounter-棒針鉤針必備編織計數器
創業歐北共 紛絲專⾴頁
導航/旅遊
臺北好⾏行行-Ubike 屈⾂臣⽒氏 中華航空
建⾝身/運動
Runtastic Nike+ Run Club
使⽤用App期間 取⽤用定位說明:
Privacy - Location When In Use Usage Description
永遠 取⽤用定位說明:
Privacy - Location Always Usage Description
info.plist
設定Usage Description
This app has crashed because it attempted to access privacy-
sensitive data without a usage description. The app's Info.plist
must contain an NSLocationWhenInUseUsageDescription key with a
string value explaining to the user how the app uses this data.
Error
MapKit Framework iOS 8.0+
import MapKit
顯⽰示地圖,標點(Annotation),覆蓋圖(Overlay)
路路線規劃




 OverlayAnnotation
MKMapView
MKPointAnnotation => MKPinAnnotationView
MKPolyline => MKPolylineRenderer
MKPolygone => MKPolygoneRenderer
Model View
MKMapView
delegate: MKMapViewDelegate
showsUserLocation: Bool (預設: false)
func setRegion(_ region:
MKCoordinateRegion, animated: Bool)
func
dequeueReusableAnnotationView(withId
entifier identifier: String) ->
MKAnnotationView?
MKMapViewDelegate
func mapView(_ mapView: MKMapView,
viewFor annotation: MKAnnotation) ->
MKAnnotationView?
func mapView(_ mapView: MKMapView,
rendererFor overlay: MKOverlay) ->
MKOverlayRenderer
MKDirections
init(request: MKDirectionsRequest)
func calculate(completionHandler:
@escaping MKDirectionsHandler)

(MKDirectionsResponse?, Error?) -> Void
func
calculateETA(completionHandler:
@escaping MKETAHandler)

(MKETAResponse?, Error?) -> Void
MKDirectionsRequest
source: MKMapItem
destination: MKMapItem
transportType: MKDirectionsTransportType

any - 任意 (預設值)

walking - 走路路

automobile - 開⾞車車

transit - 交通(只⽀支援ETA calculations)
requestsAlternateRoutes: Bool (預設:false)
CoreLocation Framework
iOS 2.0+
import CoreLocation
使⽤用者定位

地理理編碼(Geocoding)
CLLocationManager
delegate: CLLocationManagerDelegate
desiredAccuracy: CLLocationAccuracy

kCLLocationAccuracyBestForNavigation

kCLLocationAccuracyBest

kCLLocationAccuracyNearestTenMeters

kCLLocationAccuracyHundredMeters (預設值)

kCLLocationAccuracyKilometer

kCLLocationAccuracyThreeKilometers
func startUpdatingLocation()
func stopUpdatingLocation()
CLLocationManagerDelegate
func locationManager(_ manager:
CLLocationManager,
didUpdateLocations locations:
[CLLocation])
func locationManager(_ manager:
CLLocationManager, didFailWithError
error: Error)
CLGeocoder
func geocodeAddressString(_
addressString: String,
completionHandler: @escaping
CLGeocodeCompletionHandler)

([CLPlacemark]?, Error?) -> Void
func reverseGeocodeLocation(_
location: CLLocation,
completionHandler: @escaping
CLGeocodeCompletionHandler)

([CLPlacemark]?, Error?) -> Void
沒有實機 -> 模擬定位
⾃自訂位置:New File > GPX File
1. Product > Scheme > Edit Scheme >
Core Location > Default Location設
定
2. 執⾏行行App時, Console設定定位
3. 執⾏行行Simulator設定: Debug > Location
實作
1. 顯⽰示地圖
2. 標記預設⼤大頭針
3. 標記⾃自訂⼤大頭針
4. 畫線
5. 畫區塊
6. 畫路路線
7. 定位
實作 - 1.顯⽰示地圖
import MapKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet weak var mapView: MKMapView!
//國⽗父紀念念館站
let location1 = CLLocation(latitude: 25.041390, longitude: 121.557434)
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
centerMap(coordinate: location1.coordinate)
}
//以給定的經緯度為中⼼心顯⽰示該範圍內地圖
func centerMap(coordinate: CLLocationCoordinate2D) {
let span = MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005)
let region = MKCoordinateRegionMake(coordinate, span)
mapView.setRegion(region, animated: true)
}
}
實作 - 2.標記預設⼤大頭針-1
//國⽗父紀念念館站
let location1 = CLLocation(latitude: 25.041390, longitude:
121.557434)
let annotation = MKPointAnnotation()
annotation.coordinate = location1.coordinate
annotation.title = "國⽗父紀念念館站"
annotation.subtitle = "捷運站"
mapView.addAnnotation(annotation)
實作 - 2.標記預設⼤大頭針-2
func mapView(_ mapView: MKMapView, viewFor annotation:
MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let id = "PinAnnotationView"
let pin =
mapView.dequeueReusableAnnotationView(withIdentifier: id) as?
MKPinAnnotationView ?? MKPinAnnotationView(annotation:
annotation, reuseIdentifier: id)
pin.annotation = annotation
pin.canShowCallout = true
pin.pinTintColor = MKPinAnnotationView.greenPinColor()
return pin
}
實作 - 3.標記⾃自訂⼤大頭針-1
import UIKit
import MapKit
@objc protocol MyAnnotation: MKAnnotation {
var viewId: String { get }
var img: UIImage { get }
init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D)
}
class BlueAnnotation: NSObject, MyAnnotation {
var viewId = "BlueAnnotationView"
var img = UIImage
var coordinate:CLLocationCoordinate2D //必要
var title: String?
var subtitle: String?
required init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D)
{
self.title = title
self.subtitle = subtitle
self.coordinate = coordinate
super.init()
}
}
MyAnnotation.swift
實作 - 3.標記⾃自訂⼤大頭針-2
//台北101/世貿站
let location2 = CLLocation(latitude: 25.033053, longitude:
121.563192)
let myAnnotation = BlueAnnotation(title: "台北101/世貿站",
subtitle: "捷運", coordinate: location2.coordinate)
mapView.addAnnotation(myAnnotation)
實作 - 3.標記⾃自訂⼤大頭針-3
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let myView = mapView.dequeueReusableAnnotationView(withIdentifier: myAnnotation.viewId)
?? MKAnnotationView(annotation: myAnnotation, reuseIdentifier: myAnnotation.viewId)
myView.image = myAnnotation.img
myView.canShowCallout = true
myView.annotation = myAnnotation
//⾃自定CalloutAccessoryView
let detail = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21))
detail.text = myAnnotation.subtitle ?? ""
detail.numberOfLines = 0
detail.addConstraint(NSLayoutConstraint(item: detail, attribute: .width,
relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1,
constant: 150))
detail.addConstraint(NSLayoutConstraint(item: detail, attribute: .height,
relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1,
constant: 200))
detail.font = detail.font.withSize(10)
myView.detailCalloutAccessoryView = detail
myView.leftCalloutAccessoryView = UIImageView(image: myAnnotation.img))
myView.rightCalloutAccessoryView = UIImageView(image: myAnnotation.img))
return myView
}
實作 - 4.畫線-1
//台北101⼤大樓樓的四點
let point1 = CLLocationCoordinate2D(latitude: 25.032914,
longitude: 121.563411)
let point2 = CLLocationCoordinate2D(latitude: 25.034965,
longitude: 121.563550)
let point3 = CLLocationCoordinate2D(latitude: 25.034955,
longitude: 121.565395)
let point4 = CLLocationCoordinate2D(latitude: 25.032943,
longitude: 121.565352)
let line = [point1, point3]
let polyline = MKPolyline(coordinates: line, count:
line.count)
mapView.add(polyline)
實作 - 4.畫線-2
func mapView(_ mapView: MKMapView, rendererFor overlay:
MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolyline {
let renderer = MKPolylineRenderer(overlay: overlay)
renderer.strokeColor = UIColor.red
renderer.lineWidth = 5
return renderer
}
return MKOverlayRenderer()
}
實作 - 5.畫區塊-1
//台北101⼤大樓樓的四點
let point1 = CLLocationCoordinate2D(latitude: 25.032914,
longitude: 121.563411)
let point2 = CLLocationCoordinate2D(latitude: 25.034965,
longitude: 121.563550)
let point3 = CLLocationCoordinate2D(latitude: 25.034955,
longitude: 121.565395)
let point4 = CLLocationCoordinate2D(latitude: 25.032943,
longitude: 121.565352)
let points = [point1, point2, point3, point4]
let polygon = MKPolygon(coordinates: points, count:
points.count)
mapView.add(polygon)
實作 - 5.畫區塊-2
func mapView(_ mapView: MKMapView, rendererFor overlay:
MKOverlay) -> MKOverlayRenderer {
if overlay is MKPolygon {
let renderer = MKPolygonRenderer(overlay: overlay)
renderer.fillColor =
UIColor.black.withAlphaComponent(0.5)
renderer.strokeColor = UIColor.blue
renderer.lineWidth = 3
return renderer
}
return MKOverlayRenderer()
}
實作 - 6.畫路路線-1
//路路徑規劃
func drawRoute(from source: CLLocation, to destination: CLLocation) {
print("(source)...(destination)")
let sourceMapItem = MKMapItem(placemark: MKPlacemark(coordinate: source.coordinate,
addressDictionary: nil))
let destinationMapItem = MKMapItem(placemark: MKPlacemark(coordinate:
destination.coordinate, addressDictionary: nil))
let directionRequest = MKDirectionsRequest()
directionRequest.source = sourceMapItem
directionRequest.destination = destinationMapItem
directionRequest.requestsAlternateRoutes = true
directionRequest.transportType = .automobile
MKDirections(request: directionRequest).calculate {
(response, error) -> Void in
self.locationManager.stopUpdatingLocation()
if let error = error {
print("Error: (error)")
return
}
guard let response = response else {
return
}
response.routes.forEach {
print("route:($0.name),($0.distance),($0.polyline),($0.transportType)")
self.mapView.add($0.polyline)
}
self.centerMap(coordinate: source.coordinate)
}
}
實作 - 6.畫路路線-2
//國⽗父紀念念館站
let location1 = CLLocation(latitude: 25.041390, longitude:
121.557434)
//台北101/世貿站
let location2 = CLLocation(latitude: 25.033053, longitude:
121.563192)
drawRoute(from: location1, to: location2)
實作 - 6.定位-1
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate,
CLLocationManagerDelegate {
var locationManager: CLLocationManager!
override func viewDidLoad() {
super.viewDidLoad()
mapView.showsUserLocation = true
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
}
}
實作 - 6.定位-2
//取得使⽤用定位權限
switch CLLocationManager.authorizationStatus() {
case .denied, .restricted:
print("App不允許使⽤用定位服務")
case .notDetermined:
//永遠
locationManager.requestAlwaysAuthorization()
//使⽤用App期間
locationManager.requestWhenInUseAuthorization()
default: break
}
實作 - 6.定位-3
@IBAction func getUserLocation(_ sender: Any) {
guard CLLocationManager.locationServicesEnabled() else {
print("裝置無定位服務")
return
}
switch CLLocationManager.authorizationStatus() {
case .denied, .restricted:
print("App不允許使⽤用定位服務")
case .notDetermined:
locationManager.requestWhenInUseAuthorization()
default: break
}
locationManager.startUpdatingLocation()
}
實作 - 6.定位-3
func locationManager(_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]) {
locationManager.stopUpdatingLocation()
if let location = locations.last {
print("緯度:(location.coordinate.latitude) 經度: 
(location.coordinate.longitude)")
centerMap(coordinate: location.coordinate)
}
}
func locationManager(_ manager: CLLocationManager,
didFailWithError error: Error) {
locationManager.stopUpdatingLocation()
print(error)
}
進階實作
搜尋地點

(地理理編碼)
進階實作
從我的位置出發

(路路線規劃)
懶懶⼈人專⽤用: 開啟內建地圖
//使⽤用Map Link
let link = "http://maps.apple.com/ll=(location1.coordinate.latitude),
(location1.coordinate.longitude)&daddr=(location1.coordinate.latitude),
(location1.coordinate.longitude)&dirflg=d"
if let url = URL(string: link) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
}
//使⽤用MKMapItem的openInMaps
let placemark = MKPlacemark(coordinate: location1.coordinate,
addressDictionary: nil)
let mapItem = MKMapItem(placemark: placemark)
mapItem.name = "國⽗父紀念念館站123"
mapItem.phoneNumber = "1234567890"
mapItem.openInMaps(launchOptions: [MKLaunchOptionsDirectionsModeKey :
MKLaunchOptionsDirectionsModeDriving])
Apple URL Scheme Reference - Map Link 官⽅方⽂文件:

https://developer.apple.com/library/content/featuredarticles/iPhoneURLScheme_Reference/
MapLinks/MapLinks.html#//apple_ref/doc/uid/TP40007899-CH5-SW1
Homework
完成

7個實作+2個進階實作



try 路路線規劃改為輸入起點,終點


More Related Content

What's hot

R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...Revolution Analytics
 
Mashup caravan android-talks
Mashup caravan android-talksMashup caravan android-talks
Mashup caravan android-talkshonjo2
 
[shaderx7] 4.1 Practical Cascaded Shadow Maps
[shaderx7] 4.1 Practical Cascaded Shadow Maps[shaderx7] 4.1 Practical Cascaded Shadow Maps
[shaderx7] 4.1 Practical Cascaded Shadow Maps종빈 오
 
Getting Oriented with MapKit: Everything you need to get started with the new...
Getting Oriented with MapKit: Everything you need to get started with the new...Getting Oriented with MapKit: Everything you need to get started with the new...
Getting Oriented with MapKit: Everything you need to get started with the new...
John Wilker
 
Program implementation and testing
Program implementation and testingProgram implementation and testing
Program implementation and testing
abukky52
 

What's hot (6)

R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
R + Hadoop = Big Data Analytics. How Revolution Analytics' RHadoop Project Al...
 
Mashup caravan android-talks
Mashup caravan android-talksMashup caravan android-talks
Mashup caravan android-talks
 
[shaderx7] 4.1 Practical Cascaded Shadow Maps
[shaderx7] 4.1 Practical Cascaded Shadow Maps[shaderx7] 4.1 Practical Cascaded Shadow Maps
[shaderx7] 4.1 Practical Cascaded Shadow Maps
 
Iphone course 2
Iphone course 2Iphone course 2
Iphone course 2
 
Getting Oriented with MapKit: Everything you need to get started with the new...
Getting Oriented with MapKit: Everything you need to get started with the new...Getting Oriented with MapKit: Everything you need to get started with the new...
Getting Oriented with MapKit: Everything you need to get started with the new...
 
Program implementation and testing
Program implementation and testingProgram implementation and testing
Program implementation and testing
 

Similar to SwiftGirl20170904 - Apple Map

Standford 2015 week9
Standford 2015 week9Standford 2015 week9
Standford 2015 week9
彼得潘 Pan
 
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Chris Adamson
 
Enhance your world with ARKit. UA Mobile 2017.
Enhance your world with ARKit. UA Mobile 2017.Enhance your world with ARKit. UA Mobile 2017.
Enhance your world with ARKit. UA Mobile 2017.
UA Mobile
 
I os developers_meetup_4_sessionon_locationservices
I os developers_meetup_4_sessionon_locationservicesI os developers_meetup_4_sessionon_locationservices
I os developers_meetup_4_sessionon_locationservices
Mahboob Nur
 
Paris Master Class 2011 - 04 Shadow Maps
Paris Master Class 2011 - 04 Shadow MapsParis Master Class 2011 - 04 Shadow Maps
Paris Master Class 2011 - 04 Shadow Maps
Wolfgang Engel
 
Swift - One step forward from Obj-C
Swift -  One step forward from Obj-CSwift -  One step forward from Obj-C
Swift - One step forward from Obj-C
Nissan Tsafrir
 
Average- An android project
Average- An android projectAverage- An android project
Average- An android projectIpsit Dash
 
OSCON july 2011
OSCON july 2011OSCON july 2011
OSCON july 2011chelm
 
Geometry Shader-based Bump Mapping Setup
Geometry Shader-based Bump Mapping SetupGeometry Shader-based Bump Mapping Setup
Geometry Shader-based Bump Mapping Setup
Mark Kilgard
 
You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
名辰 洪
 
RedisConf17 - Distributed Java Map Structures and Services with Redisson
RedisConf17 - Distributed Java Map Structures and Services with RedissonRedisConf17 - Distributed Java Map Structures and Services with Redisson
RedisConf17 - Distributed Java Map Structures and Services with Redisson
Redis Labs
 
RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)
Tracy Lee
 
HTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHexHTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHex
Tadayasu Sasada
 
Mining Geo-referenced Data: Location-based Services and the Sharing Economy
Mining Geo-referenced Data: Location-based Services and the Sharing EconomyMining Geo-referenced Data: Location-based Services and the Sharing Economy
Mining Geo-referenced Data: Location-based Services and the Sharing Economy
tnoulas
 
IOS 8 Indoor Location
IOS 8 Indoor LocationIOS 8 Indoor Location
IOS 8 Indoor Location
Ludovic Privat
 
Computer Science Presentation for various MATLAB toolboxes
Computer Science Presentation for various MATLAB toolboxesComputer Science Presentation for various MATLAB toolboxes
Computer Science Presentation for various MATLAB toolboxes
ThinHunh47
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
Visual Engineering
 
Oracle APEX migration to 5.1 - Our experience
Oracle APEX migration to 5.1 - Our experienceOracle APEX migration to 5.1 - Our experience
Oracle APEX migration to 5.1 - Our experience
Lino Schildenfeld
 

Similar to SwiftGirl20170904 - Apple Map (20)

Standford 2015 week9
Standford 2015 week9Standford 2015 week9
Standford 2015 week9
 
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
Core Location and Map Kit: Bringing Your Own Maps [Voices That Matter: iPhone...
 
Enhance your world with ARKit. UA Mobile 2017.
Enhance your world with ARKit. UA Mobile 2017.Enhance your world with ARKit. UA Mobile 2017.
Enhance your world with ARKit. UA Mobile 2017.
 
Map kit
Map kitMap kit
Map kit
 
I os developers_meetup_4_sessionon_locationservices
I os developers_meetup_4_sessionon_locationservicesI os developers_meetup_4_sessionon_locationservices
I os developers_meetup_4_sessionon_locationservices
 
Paris Master Class 2011 - 04 Shadow Maps
Paris Master Class 2011 - 04 Shadow MapsParis Master Class 2011 - 04 Shadow Maps
Paris Master Class 2011 - 04 Shadow Maps
 
Map kit light
Map kit lightMap kit light
Map kit light
 
Swift - One step forward from Obj-C
Swift -  One step forward from Obj-CSwift -  One step forward from Obj-C
Swift - One step forward from Obj-C
 
Average- An android project
Average- An android projectAverage- An android project
Average- An android project
 
OSCON july 2011
OSCON july 2011OSCON july 2011
OSCON july 2011
 
Geometry Shader-based Bump Mapping Setup
Geometry Shader-based Bump Mapping SetupGeometry Shader-based Bump Mapping Setup
Geometry Shader-based Bump Mapping Setup
 
You will learn RxJS in 2017
You will learn RxJS in 2017You will learn RxJS in 2017
You will learn RxJS in 2017
 
RedisConf17 - Distributed Java Map Structures and Services with Redisson
RedisConf17 - Distributed Java Map Structures and Services with RedissonRedisConf17 - Distributed Java Map Structures and Services with Redisson
RedisConf17 - Distributed Java Map Structures and Services with Redisson
 
RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)RxJS Operators - Real World Use Cases (FULL VERSION)
RxJS Operators - Real World Use Cases (FULL VERSION)
 
HTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHexHTML5勉強会#23_GeoHex
HTML5勉強会#23_GeoHex
 
Mining Geo-referenced Data: Location-based Services and the Sharing Economy
Mining Geo-referenced Data: Location-based Services and the Sharing EconomyMining Geo-referenced Data: Location-based Services and the Sharing Economy
Mining Geo-referenced Data: Location-based Services and the Sharing Economy
 
IOS 8 Indoor Location
IOS 8 Indoor LocationIOS 8 Indoor Location
IOS 8 Indoor Location
 
Computer Science Presentation for various MATLAB toolboxes
Computer Science Presentation for various MATLAB toolboxesComputer Science Presentation for various MATLAB toolboxes
Computer Science Presentation for various MATLAB toolboxes
 
Workshop 25: React Native - Components
Workshop 25: React Native - ComponentsWorkshop 25: React Native - Components
Workshop 25: React Native - Components
 
Oracle APEX migration to 5.1 - Our experience
Oracle APEX migration to 5.1 - Our experienceOracle APEX migration to 5.1 - Our experience
Oracle APEX migration to 5.1 - Our experience
 

Recently uploaded

Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Globus
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
Globus
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Yara Milbes
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
Shane Coughlan
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
timtebeek1
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
Safe Software
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
Boni García
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
ShamsuddeenMuhammadA
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
rickgrimesss22
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
NYGGS Automation Suite
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
takuyayamamoto1800
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
wottaspaceseo
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
Ortus Solutions, Corp
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Globus
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
Fermin Galan
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
abdulrafaychaudhry
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Globus
 

Recently uploaded (20)

Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
Climate Science Flows: Enabling Petabyte-Scale Climate Analysis with the Eart...
 
First Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User EndpointsFirst Steps with Globus Compute Multi-User Endpoints
First Steps with Globus Compute Multi-User Endpoints
 
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi ArabiaTop 7 Unique WhatsApp API Benefits | Saudi Arabia
Top 7 Unique WhatsApp API Benefits | Saudi Arabia
 
Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024Globus Compute wth IRI Workflows - GlobusWorld 2024
Globus Compute wth IRI Workflows - GlobusWorld 2024
 
openEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain SecurityopenEuler Case Study - The Journey to Supply Chain Security
openEuler Case Study - The Journey to Supply Chain Security
 
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdfAutomated software refactoring with OpenRewrite and Generative AI.pptx.pdf
Automated software refactoring with OpenRewrite and Generative AI.pptx.pdf
 
Essentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FMEEssentials of Automations: The Art of Triggers and Actions in FME
Essentials of Automations: The Art of Triggers and Actions in FME
 
Vitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume MontevideoVitthal Shirke Microservices Resume Montevideo
Vitthal Shirke Microservices Resume Montevideo
 
APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)APIs for Browser Automation (MoT Meetup 2024)
APIs for Browser Automation (MoT Meetup 2024)
 
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptxText-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
Text-Summarization-of-Breaking-News-Using-Fine-tuning-BART-Model.pptx
 
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptxTop Features to Include in Your Winzo Clone App for Business Growth (4).pptx
Top Features to Include in Your Winzo Clone App for Business Growth (4).pptx
 
Enterprise Resource Planning System in Telangana
Enterprise Resource Planning System in TelanganaEnterprise Resource Planning System in Telangana
Enterprise Resource Planning System in Telangana
 
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoamOpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
OpenFOAM solver for Helmholtz equation, helmholtzFoam / helmholtzBubbleFoam
 
How Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptxHow Recreation Management Software Can Streamline Your Operations.pptx
How Recreation Management Software Can Streamline Your Operations.pptx
 
BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024BoxLang: Review our Visionary Licenses of 2024
BoxLang: Review our Visionary Licenses of 2024
 
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data AnalysisProviding Globus Services to Users of JASMIN for Environmental Data Analysis
Providing Globus Services to Users of JASMIN for Environmental Data Analysis
 
Prosigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology SolutionsProsigns: Transforming Business with Tailored Technology Solutions
Prosigns: Transforming Business with Tailored Technology Solutions
 
Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604Orion Context Broker introduction 20240604
Orion Context Broker introduction 20240604
 
Lecture 1 Introduction to games development
Lecture 1 Introduction to games developmentLecture 1 Introduction to games development
Lecture 1 Introduction to games development
 
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
Exploring Innovations in Data Repository Solutions - Insights from the U.S. G...
 

SwiftGirl20170904 - Apple Map

  • 5. 使⽤用App期間 取⽤用定位說明: Privacy - Location When In Use Usage Description 永遠 取⽤用定位說明: Privacy - Location Always Usage Description info.plist 設定Usage Description This app has crashed because it attempted to access privacy- sensitive data without a usage description. The app's Info.plist must contain an NSLocationWhenInUseUsageDescription key with a string value explaining to the user how the app uses this data. Error
  • 6. MapKit Framework iOS 8.0+ import MapKit 顯⽰示地圖,標點(Annotation),覆蓋圖(Overlay) 路路線規劃
 
 
 OverlayAnnotation
  • 7. MKMapView MKPointAnnotation => MKPinAnnotationView MKPolyline => MKPolylineRenderer MKPolygone => MKPolygoneRenderer Model View
  • 8. MKMapView delegate: MKMapViewDelegate showsUserLocation: Bool (預設: false) func setRegion(_ region: MKCoordinateRegion, animated: Bool) func dequeueReusableAnnotationView(withId entifier identifier: String) -> MKAnnotationView?
  • 9. MKMapViewDelegate func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer
  • 10. MKDirections init(request: MKDirectionsRequest) func calculate(completionHandler: @escaping MKDirectionsHandler)
 (MKDirectionsResponse?, Error?) -> Void func calculateETA(completionHandler: @escaping MKETAHandler)
 (MKETAResponse?, Error?) -> Void
  • 11. MKDirectionsRequest source: MKMapItem destination: MKMapItem transportType: MKDirectionsTransportType
 any - 任意 (預設值)
 walking - 走路路
 automobile - 開⾞車車
 transit - 交通(只⽀支援ETA calculations) requestsAlternateRoutes: Bool (預設:false)
  • 12. CoreLocation Framework iOS 2.0+ import CoreLocation 使⽤用者定位
 地理理編碼(Geocoding)
  • 14. CLLocationManagerDelegate func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) func locationManager(_ manager: CLLocationManager, didFailWithError error: Error)
  • 15. CLGeocoder func geocodeAddressString(_ addressString: String, completionHandler: @escaping CLGeocodeCompletionHandler)
 ([CLPlacemark]?, Error?) -> Void func reverseGeocodeLocation(_ location: CLLocation, completionHandler: @escaping CLGeocodeCompletionHandler)
 ([CLPlacemark]?, Error?) -> Void
  • 16. 沒有實機 -> 模擬定位 ⾃自訂位置:New File > GPX File 1. Product > Scheme > Edit Scheme > Core Location > Default Location設 定 2. 執⾏行行App時, Console設定定位 3. 執⾏行行Simulator設定: Debug > Location
  • 17. 實作 1. 顯⽰示地圖 2. 標記預設⼤大頭針 3. 標記⾃自訂⼤大頭針 4. 畫線 5. 畫區塊 6. 畫路路線 7. 定位
  • 18. 實作 - 1.顯⽰示地圖 import MapKit class ViewController: UIViewController, MKMapViewDelegate { @IBOutlet weak var mapView: MKMapView! //國⽗父紀念念館站 let location1 = CLLocation(latitude: 25.041390, longitude: 121.557434) override func viewDidLoad() { super.viewDidLoad() mapView.delegate = self centerMap(coordinate: location1.coordinate) } //以給定的經緯度為中⼼心顯⽰示該範圍內地圖 func centerMap(coordinate: CLLocationCoordinate2D) { let span = MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005) let region = MKCoordinateRegionMake(coordinate, span) mapView.setRegion(region, animated: true) } }
  • 19. 實作 - 2.標記預設⼤大頭針-1 //國⽗父紀念念館站 let location1 = CLLocation(latitude: 25.041390, longitude: 121.557434) let annotation = MKPointAnnotation() annotation.coordinate = location1.coordinate annotation.title = "國⽗父紀念念館站" annotation.subtitle = "捷運站" mapView.addAnnotation(annotation)
  • 20. 實作 - 2.標記預設⼤大頭針-2 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { if annotation is MKUserLocation { return nil } let id = "PinAnnotationView" let pin = mapView.dequeueReusableAnnotationView(withIdentifier: id) as? MKPinAnnotationView ?? MKPinAnnotationView(annotation: annotation, reuseIdentifier: id) pin.annotation = annotation pin.canShowCallout = true pin.pinTintColor = MKPinAnnotationView.greenPinColor() return pin }
  • 21. 實作 - 3.標記⾃自訂⼤大頭針-1 import UIKit import MapKit @objc protocol MyAnnotation: MKAnnotation { var viewId: String { get } var img: UIImage { get } init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D) } class BlueAnnotation: NSObject, MyAnnotation { var viewId = "BlueAnnotationView" var img = UIImage var coordinate:CLLocationCoordinate2D //必要 var title: String? var subtitle: String? required init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D) { self.title = title self.subtitle = subtitle self.coordinate = coordinate super.init() } } MyAnnotation.swift
  • 22. 實作 - 3.標記⾃自訂⼤大頭針-2 //台北101/世貿站 let location2 = CLLocation(latitude: 25.033053, longitude: 121.563192) let myAnnotation = BlueAnnotation(title: "台北101/世貿站", subtitle: "捷運", coordinate: location2.coordinate) mapView.addAnnotation(myAnnotation)
  • 23. 實作 - 3.標記⾃自訂⼤大頭針-3 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { let myView = mapView.dequeueReusableAnnotationView(withIdentifier: myAnnotation.viewId) ?? MKAnnotationView(annotation: myAnnotation, reuseIdentifier: myAnnotation.viewId) myView.image = myAnnotation.img myView.canShowCallout = true myView.annotation = myAnnotation //⾃自定CalloutAccessoryView let detail = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21)) detail.text = myAnnotation.subtitle ?? "" detail.numberOfLines = 0 detail.addConstraint(NSLayoutConstraint(item: detail, attribute: .width, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 150)) detail.addConstraint(NSLayoutConstraint(item: detail, attribute: .height, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200)) detail.font = detail.font.withSize(10) myView.detailCalloutAccessoryView = detail myView.leftCalloutAccessoryView = UIImageView(image: myAnnotation.img)) myView.rightCalloutAccessoryView = UIImageView(image: myAnnotation.img)) return myView }
  • 24. 實作 - 4.畫線-1 //台北101⼤大樓樓的四點 let point1 = CLLocationCoordinate2D(latitude: 25.032914, longitude: 121.563411) let point2 = CLLocationCoordinate2D(latitude: 25.034965, longitude: 121.563550) let point3 = CLLocationCoordinate2D(latitude: 25.034955, longitude: 121.565395) let point4 = CLLocationCoordinate2D(latitude: 25.032943, longitude: 121.565352) let line = [point1, point3] let polyline = MKPolyline(coordinates: line, count: line.count) mapView.add(polyline)
  • 25. 實作 - 4.畫線-2 func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { if overlay is MKPolyline { let renderer = MKPolylineRenderer(overlay: overlay) renderer.strokeColor = UIColor.red renderer.lineWidth = 5 return renderer } return MKOverlayRenderer() }
  • 26. 實作 - 5.畫區塊-1 //台北101⼤大樓樓的四點 let point1 = CLLocationCoordinate2D(latitude: 25.032914, longitude: 121.563411) let point2 = CLLocationCoordinate2D(latitude: 25.034965, longitude: 121.563550) let point3 = CLLocationCoordinate2D(latitude: 25.034955, longitude: 121.565395) let point4 = CLLocationCoordinate2D(latitude: 25.032943, longitude: 121.565352) let points = [point1, point2, point3, point4] let polygon = MKPolygon(coordinates: points, count: points.count) mapView.add(polygon)
  • 27. 實作 - 5.畫區塊-2 func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { if overlay is MKPolygon { let renderer = MKPolygonRenderer(overlay: overlay) renderer.fillColor = UIColor.black.withAlphaComponent(0.5) renderer.strokeColor = UIColor.blue renderer.lineWidth = 3 return renderer } return MKOverlayRenderer() }
  • 28. 實作 - 6.畫路路線-1 //路路徑規劃 func drawRoute(from source: CLLocation, to destination: CLLocation) { print("(source)...(destination)") let sourceMapItem = MKMapItem(placemark: MKPlacemark(coordinate: source.coordinate, addressDictionary: nil)) let destinationMapItem = MKMapItem(placemark: MKPlacemark(coordinate: destination.coordinate, addressDictionary: nil)) let directionRequest = MKDirectionsRequest() directionRequest.source = sourceMapItem directionRequest.destination = destinationMapItem directionRequest.requestsAlternateRoutes = true directionRequest.transportType = .automobile MKDirections(request: directionRequest).calculate { (response, error) -> Void in self.locationManager.stopUpdatingLocation() if let error = error { print("Error: (error)") return } guard let response = response else { return } response.routes.forEach { print("route:($0.name),($0.distance),($0.polyline),($0.transportType)") self.mapView.add($0.polyline) } self.centerMap(coordinate: source.coordinate) } }
  • 29. 實作 - 6.畫路路線-2 //國⽗父紀念念館站 let location1 = CLLocation(latitude: 25.041390, longitude: 121.557434) //台北101/世貿站 let location2 = CLLocation(latitude: 25.033053, longitude: 121.563192) drawRoute(from: location1, to: location2)
  • 30. 實作 - 6.定位-1 import MapKit import CoreLocation class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate { var locationManager: CLLocationManager! override func viewDidLoad() { super.viewDidLoad() mapView.showsUserLocation = true locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest } }
  • 31. 實作 - 6.定位-2 //取得使⽤用定位權限 switch CLLocationManager.authorizationStatus() { case .denied, .restricted: print("App不允許使⽤用定位服務") case .notDetermined: //永遠 locationManager.requestAlwaysAuthorization() //使⽤用App期間 locationManager.requestWhenInUseAuthorization() default: break }
  • 32. 實作 - 6.定位-3 @IBAction func getUserLocation(_ sender: Any) { guard CLLocationManager.locationServicesEnabled() else { print("裝置無定位服務") return } switch CLLocationManager.authorizationStatus() { case .denied, .restricted: print("App不允許使⽤用定位服務") case .notDetermined: locationManager.requestWhenInUseAuthorization() default: break } locationManager.startUpdatingLocation() }
  • 33. 實作 - 6.定位-3 func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { locationManager.stopUpdatingLocation() if let location = locations.last { print("緯度:(location.coordinate.latitude) 經度: (location.coordinate.longitude)") centerMap(coordinate: location.coordinate) } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { locationManager.stopUpdatingLocation() print(error) }
  • 36. 懶懶⼈人專⽤用: 開啟內建地圖 //使⽤用Map Link let link = "http://maps.apple.com/ll=(location1.coordinate.latitude), (location1.coordinate.longitude)&daddr=(location1.coordinate.latitude), (location1.coordinate.longitude)&dirflg=d" if let url = URL(string: link) { UIApplication.shared.open(url, options: [:], completionHandler: nil) } //使⽤用MKMapItem的openInMaps let placemark = MKPlacemark(coordinate: location1.coordinate, addressDictionary: nil) let mapItem = MKMapItem(placemark: placemark) mapItem.name = "國⽗父紀念念館站123" mapItem.phoneNumber = "1234567890" mapItem.openInMaps(launchOptions: [MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving]) Apple URL Scheme Reference - Map Link 官⽅方⽂文件:
 https://developer.apple.com/library/content/featuredarticles/iPhoneURLScheme_Reference/ MapLinks/MapLinks.html#//apple_ref/doc/uid/TP40007899-CH5-SW1

Editor's Notes

  1. 大家好 今天的主題是Apple Map, 就是介紹Apple地圖的基本概念跟應用
  2. 自介, 我叫張筱姍, 大家叫我筱姍就可以了, 因為我很喜歡織毛線, 我目前主要是在開發一些跟織毛線.手作相關的app. 目前已經上架app的只有一個,叫KCCounter, 是編織用的計數器. 因為每天都一個人在家做, 怕會偷懶, 所以我跟我一個好朋友建了這個創業歐北共粉絲團, 每週五會發一篇文章, 記錄一下自己每週做了什麼事情,
  3. 這裡舉例幾個有用到地圖的App. 臺北好行用地圖顯示Ubike站點位置, 屈臣氏顯示門市位置, 華航顯示飛機航線
  4. Runtastic, Nike+ Run Club, 這種運動類的App就是用地圖記錄跑步路線
  5. 跟上次介紹的相機照片一樣, 使用者位置也算是一種私密資料, 要用這個資料, 一樣也要在專案的info.plist裡面,設定相關的Privacy Usage Description. Apple把定位分成兩種方式, 一種是使用App期間取用Location When In Use,就是你有在用App的時後才會去做定位, 這種會跳出像左邊的視窗, 另一種是永遠取用Location Always, 即使App目前正在背景執行也一直再做定位,這種則會跳出像右邊的視窗, 如果沒設定的錯誤訊息是像下面這樣
  6. 我們要用Apple地圖就是要用Mapkit這個Framework 她主要就是可以顯示地圖、標點、覆蓋圖(Overlay), 還有路線規劃的功能
  7. MKMapView就是用來顯示地圖的類別. 那在MapView上面可以顯示Annotation(標點),或是Overlay(覆蓋圖). Apple有提供幾個基本的類別, 讓我們可以直接使用, 下面列3種, MKPointAnnotation就是預設的Annotation, MKPolyline是線條的Overlay, MKPolygone是多邊形的Overlay. 左邊這些是Model, 用來存資料, 像Annotation有座標. 名稱..等資料. 右邊這些是對應的View, 用來定義畫面, 像Annotation的圖片,Polyline的線條顏色
  8. MapView程式的部分 他有2個比較重要的property, ㄧ個是delegate. delegate要用MKMapViewDelegate, 另一個是showsUserLocation, 如果有用定位的話, 這個值要設true才會在地圖上顯示使用者位置, function部分, setRegion是用來指定mapview要顯示的地圖範圍是哪裡, 另外一個function是dequeueReusableAnnotationView, 這個是要把AnnotationView的物件重複使用, 來維持比較好的效能.
  9. 再來講MKMapViewDelegate. 他主要有2個function可以實作. viewForAnnotation跟rendererForOverlay 這2個分別就是讓你設定每個annotation跟每個Overlay顯示在地圖上的樣式
  10. MKDirections就是可以幫我們做路線規劃的class Apple有2種路線規劃的func,沒有eta的是只有找路線.有eta的不只找路線還包含預估時間
  11. 再來講MKDirectionsRequest 主要是要設定起點跟終點.transporttye是行進方式有分4種, any - 任意,walking - 走路 ,automobile - 開車,transit - 交通(只支援ETA calculations), 其中預設值是any. requestsAlternateRoutes, 這個設false的話是說一次只會找出ㄧ條路線,如果設true, 就會規劃多個不同的路線
  12. CoreLocation Framework主要是讓我們可以做定位跟地理編碼Geocoding, Geocoding就是把地址跟經緯度轉換的一種服務
  13. CoreLocation Framework裡面主要是用CLLocationManager來做定位的服務, 他有2個比較重要的property, ㄧ個是delegate. delegate要設CLLocationManagerDelegate, 另一個是desiredAccuracy是指精確度, 有6種, 由上到下是照精確度最高到最低順序排. 預設值是HundredMeters這個, 下面2個function部分, 第一個是開始定位, 第一個是停止定位.
  14. 再來講這個CLLocationManagerDelegate. 他主要有2個function可以實作. didUpdateLocations跟didFailWithError, 第一個didUpdateLocations就是當你開啟定位以後,手機每次抓到使用者的位置之後會執行這裡的程式.那didFailWithError就是如果定位失敗的時後會執行這裡
  15. corelocation裡的CLGeocoder是用來處理地理編碼的class geocodeAddressString就是用地址查出他的經緯度, reverseGeocodeLocation是用經緯度座標查出地址, 這2個都是非同步去執行, 要用CLGeocodeCompletionHandler去處理查詢完成以後的動作, 如果查詢成功CompletionHandler裡面會有一個CLPlacemark的陣列存放查詢到的結果.
  16. 如果是用模擬器要測試定位的功能.有3種方法可以設定假的位置. Demo..
  17. 實作練習的部分, 我分成7項....Demo
  18. //國父紀念館站 let location1 = CLLocation(latitude: 25.041390, longitude: 121.557434) //台北101/世貿站 let location2 = CLLocation(latitude: 25.033053, longitude: 121.563192) //台北101大樓的四點 let point1 = CLLocationCoordinate2D(latitude: 25.032914, longitude: 121.563411) let point2 = CLLocationCoordinate2D(latitude: 25.034965, longitude: 121.563550) let point3 = CLLocationCoordinate2D(latitude: 25.034955, longitude: 121.565395) let point4 = CLLocationCoordinate2D(latitude: 25.032943, longitude: 121.565352) //以給定的經緯度為中心顯示該範圍內地圖 func centerMap(coordinate: CLLocationCoordinate2D) { let span = MKCoordinateSpan(latitudeDelta: 0.005, longitudeDelta: 0.005) let region = MKCoordinateRegionMake(coordinate, span) mapView.setRegion(region, animated: true) }
  19. let annotation = MKPointAnnotation() annotation.coordinate = location1.coordinate annotation.title = "國父紀念館站" annotation.subtitle = "捷運站" mapView.addAnnotation(annotation)
  20. func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? { if annotation is MKUserLocation { return nil } let id = "PinAnnotationView" let pin = mapView.dequeueReusableAnnotationView(withIdentifier: id) as? MKPinAnnotationView ?? MKPinAnnotationView(annotation: annotation, reuseIdentifier: id) pin.annotation = annotation pin.canShowCallout = true pin.pinTintColor = MKPinAnnotationView.greenPinColor() return pin }
  21. import UIKit import MapKit @objc protocol MyAnnotation: MKAnnotation { var viewId: String { get } var img: UIImage { get } init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D) } class BlueAnnotation: NSObject, MyAnnotation { var viewId = "BlueAnnotationView" var img = UIImage var coordinate:CLLocationCoordinate2D //必要 var title: String? var subtitle: String? required init(title: String, subtitle: String, coordinate: CLLocationCoordinate2D) { self.title = title self.subtitle = subtitle self.coordinate = coordinate super.init() } }
  22. let myAnnotation = BlueAnnotation(title: "台北101/世貿站", subtitle: "捷運", coordinate: location2.coordinate) mapView.addAnnotation(myAnnotation)
  23. guard let myAnnotation = annotation as? MyAnnotation else { let id = "PinAnnotationView" let pin = mapView.dequeueReusableAnnotationView(withIdentifier: id) as? MKPinAnnotationView ?? MKPinAnnotationView(annotation: annotation, reuseIdentifier: id) pin.annotation = annotation pin.canShowCallout = true pin.pinTintColor = MKPinAnnotationView.greenPinColor() return pin } let myView = mapView.dequeueReusableAnnotationView(withIdentifier: myAnnotation.viewId) ?? MKAnnotationView(annotation: myAnnotation, reuseIdentifier: myAnnotation.viewId) myView.image = myAnnotation.img myView.canShowCallout = true myView.annotation = myAnnotation //自定CalloutAccessoryView let detail = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 21)) detail.text = myAnnotation.subtitle ?? "" detail.numberOfLines = 0 detail.addConstraint(NSLayoutConstraint(item: detail, attribute: .width, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 150)) detail.addConstraint(NSLayoutConstraint(item: detail, attribute: .height, relatedBy: .lessThanOrEqual, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 200)) detail.font = detail.font.withSize(10) myView.detailCalloutAccessoryView = detail myView.leftCalloutAccessoryView = UIImageView(image: myAnnotation.img) myView.rightCalloutAccessoryView = UIImageView(image: myAnnotation.img) return myView
  24. let line = [point1, point3] let polyline = MKPolyline(coordinates: line, count: line.count) mapView.add(polyline)
  25. func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer { if overlay is MKPolyline { let renderer = MKPolylineRenderer(overlay: overlay) renderer.strokeColor = UIColor.red renderer.lineWidth = 5 return renderer } return MKOverlayRenderer() }
  26. let points = [point1, point2, point3, point4] let polygon = MKPolygon(coordinates: points, count: points.count) mapView.add(polygon)
  27. if overlay is MKPolygon { let renderer = MKPolygonRenderer(overlay: overlay) renderer.fillColor = UIColor.black.withAlphaComponent(0.5) renderer.strokeColor = UIColor.blue renderer.lineWidth = 3 return renderer }
  28. //路徑規劃 func drawRoute(from source: CLLocation, to destination: CLLocation) { print("\(source)...\(destination)") let sourceMapItem = MKMapItem(placemark: MKPlacemark(coordinate: source.coordinate, addressDictionary: nil)) let destinationMapItem = MKMapItem(placemark: MKPlacemark(coordinate: destination.coordinate, addressDictionary: nil)) let directionRequest = MKDirectionsRequest() directionRequest.source = sourceMapItem directionRequest.destination = destinationMapItem directionRequest.requestsAlternateRoutes = true directionRequest.transportType = .automobile MKDirections(request: directionRequest).calculate { (response, error) -> Void in self.locationManager.stopUpdatingLocation() if let error = error { print("Error: \(error)") return } guard let response = response else { return } response.routes.forEach { print("route:\($0.name),\($0.distance),\($0.polyline),\($0.transportType)") self.mapView.add($0.polyline) } self.centerMap(coordinate: source.coordinate) } }
  29. drawRoute(from: location1, to: location2)
  30. var locationManager: CLLocationManager! mapView.showsUserLocation = true locationManager = CLLocationManager() locationManager.delegate = self locationManager.desiredAccuracy = kCLLocationAccuracyBest
  31. //取得使用定位權限 switch CLLocationManager.authorizationStatus() { case .denied, .restricted: print("App不允許使用定位服務") case .notDetermined: //永遠 // locationManager.requestAlwaysAuthorization() //使用App期間 locationManager.requestWhenInUseAuthorization() default: break }
  32. guard CLLocationManager.locationServicesEnabled() else { print("裝置無定位服務") return } switch CLLocationManager.authorizationStatus() { case .denied, .restricted: print("App不允許使用定位服務") case .notDetermined: locationManager.requestWhenInUseAuthorization() default: break } locationManager.startUpdatingLocation()
  33. func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) { locationManager.stopUpdatingLocation() if let location = locations.last { print("緯度:\(location.coordinate.latitude) 經度: \(location.coordinate.longitude)") centerMap(coordinate: location.coordinate) } } func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) { locationManager.stopUpdatingLocation() print(error) }