在 swift 中将自定义注释图钉图像更新为标准注释图钉
Update custom annotation pin image to standard annotation pin in swift
我想每 60 秒更新一次地图视图并使用自定义 pin/image 进行注释,但想在之前绘制的注释中显示标准图钉 [红色 - 请参阅 Figure 6-1] 图标。我试过像下面的代码但是不能正常工作。使用另一个自定义图像它可以工作,但我无法显示 default/standard 红色图钉到先前的注释。请参阅 "currentLocationHasBeenUpdated" 函数,我在其中尝试向先前的注释显示标准的红色图标。请让我知道我怎样才能做到这一点。谢谢
我的 ViewController :
import UIKit
import MapKit
class FirstTabController: UIViewController, MKMapViewDelegate, DelegateForUpdateCurrentLocation {
@IBOutlet weak var mapView: MKMapView!
var gpsLocations : [[String: AnyObject]]!
var dataManager : DataManager!
var currentAnnotation : MKAnnotation!
//Return CLLocation Coordinate
func getLocationObject(latitude:Double, longitude:Double) -> CLLocationCoordinate2D {
return CLLocationCoordinate2D(
latitude: latitude,
longitude: longitude
)
}
//Create annotation object & return
func createAnnotation(latitude:Double, longitude:Double, locationName:String, territory:String) -> MKPointAnnotation {
let annotation = MKPointAnnotation()
annotation.coordinate = self.getLocationObject(latitude, longitude: longitude)
annotation.title = locationName
annotation.subtitle = territory
return annotation
}
//Create annotaion for current ship position
func createAnnotationForCurrentPosition(location:[String: AnyObject]) -> MKPointAnnotation {
let latitude = (location["latitude"] as? Double)!
let longitude = (location["longitude"] as? Double)!
let name = (location["locationName"] as? String)!
let territory = (location["territory"] as? String)!
return self.createAnnotation(latitude, longitude: longitude, locationName: name, territory: territory)
}
//Set region on map view
func setRegion(location:[String: AnyObject]){
let latitude = (location["latitude"] as? Double)!
let longitude = (location["longitude"] as? Double)!
let location = self.getLocationObject(latitude, longitude: longitude)
//Set zoom span
let span = MKCoordinateSpanMake(0.05, 0.05)
//Create region on map view & show
let region = MKCoordinateRegion(center: location, span: span)
self.mapView.setRegion(region, animated: true)
}
//This function will fire from data manager when current location from API has been updated
func currentLocationHasBeenUpdated(location:[String: AnyObject]){
dispatch_async(dispatch_get_main_queue()){
if self.currentAnnotation != nil {
var currentAnnotationView = self.mapView.viewForAnnotation(self.currentAnnotation)
if currentAnnotationView != nil {
currentAnnotationView.image = nil //this line makes app crash [gave nil to show standard red icon]
// currentAnnotationView.image = UIImage(named:"first") - this line works perfectly with different icon. but i don't want any custom icon except the standard red one
}
}
self.mapView.addAnnotation(self.createAnnotationForCurrentPosition(location))
self.setRegion(location)
}
}
//Update map view by scheduling time if current location is changed yet
func updateMapView() {
self.dataManager.getCurrentLocation()
}
override func viewDidLoad() {
super.viewDidLoad()
//Get gps locations from data manager
self.dataManager = DataManager()
self.dataManager.delegate2 = self
self.dataManager.getCurrentLocation()
//self.mapView.userTrackingMode = MKUserTrackingMode.FollowWithHeading
//Get GPS location by scheduling time
NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("updateMapView"), userInfo: nil, repeats: true)
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer!{
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 2
return polylineRenderer
}
return nil
}
//Make custom annotaion pin if the annotation is of ship's current position
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!{
println("Hello")
self.currentAnnotation = annotation
//Custom annotation view with custom pin icon
let reuseId = "custom"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
annotationView.canShowCallout = true
}
else {
annotationView.annotation = annotation
}
//Set annotation specific properties after the view is dequeued or created...
annotationView.image = UIImage(named:"pinicon")
return annotationView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
以及来自 api
的坐标
import Foundation
extension String {
func toDouble() -> Double? {
return NSNumberFormatter().numberFromString(self)?.doubleValue
}
}
class DataSet{
var settings : Settings!
var getService : GetService!
var currentLocation : [String: AnyObject]!
//Object initialization for API call
init(){
self.settings = Settings()
self.getService = GetService()
}
func getCurrentLocation(callback:([String: AnyObject]) -> ()){
self.getService.apiCallToGet(self.settings.getCoordinates(), callback: {
(response) in
var location = [String: AnyObject]()
for item in response {
if let dictionary = item as? NSDictionary {
if let lat = dictionary["Lat"] as? String {
if lat.toDouble() != nil {
location["latitude"] = lat.toDouble()!
}
}
if let long = dictionary["Long"] as? String {
if long.toDouble() != nil {
location["longitude"] = long.toDouble()!
}
}
if let name = dictionary["Name"] as? String {
location["locationName"] = name
}
if let territory = dictionary["Territory"] as? String {
location["territory"] = territory
}
println(location["latitude"]!)
println(location["longitude"]!)
if self.currentLocation != nil {
if ((self.currentLocation["latitude"] as? Double) != (location["latitude"] as? Double)) && ((self.currentLocation["longitude"] as? Double) != (location["longitude"] as? Double)){
self.currentLocation = location
callback(location)
}
} else {
self.currentLocation = location
callback(location)
}
}
}
})
}
}
我已经通过创建自定义注释 class 解决了我的问题,如下所示 -
import UIKit
import MapKit
var ARROW_ANNOTATION : NSString = "ARROW_ANNOTATION"
var PIN_ANNOTATION : NSString = "PIN_ANNOTATION"
class Annotation: NSObject, MKAnnotation {
var currentLocation: CLLocationCoordinate2D
var _title : String
var subTitle : String
var direction : CLLocationDirection!
var typeOfAnnotation : String!
init(coordinate: CLLocationCoordinate2D, title : String, subTitle : String) {
self.currentLocation = coordinate
self._title = title
self.subTitle = subTitle
}
func getLocation() -> CLLocation {
return CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
}
var coordinate: CLLocationCoordinate2D {
return self.currentLocation
}
var title : String {
return self._title
}
var subtitle : String {
return self.subTitle
}
}
并且在我的 ViewController 文件中 -
override func viewDidLoad() {
super.viewDidLoad()
var annotation1 : Annotation = Annotation(coordinate: location, title: name, subTitle: territory)
annotation.typeOfAnnotation = PIN_ANNOTATION as String
self.mapView.addAnnotation(annotation1)
var annotation2 : Annotation = Annotation(coordinate: location, title: name, subTitle: territory)
annotation.typeOfAnnotation = ARROW_ANNOTATION as String
self.mapView.addAnnotation(annotation2)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!{
let reuseId = "custom"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
var customAnnotationView : MKAnnotationView!
if let _annotation = annotation as? Annotation {
if _annotation.typeOfAnnotation == PIN_ANNOTATION {
customAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
customAnnotationView.canShowCallout = true
//customAnnotationView.draggable = true
} else {
customAnnotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
// 17 - Determine the direction
let arrowImage = UIImage(named:"arrow")!
let direction = _annotation.direction
customAnnotationView.image = self.rotatedImage(arrowImage, byDegreesFromNorth: direction)
customAnnotationView.canShowCallout = true
}
} else {
return nil
}
return customAnnotationView
}
我想每 60 秒更新一次地图视图并使用自定义 pin/image 进行注释,但想在之前绘制的注释中显示标准图钉 [红色 - 请参阅 Figure 6-1] 图标。我试过像下面的代码但是不能正常工作。使用另一个自定义图像它可以工作,但我无法显示 default/standard 红色图钉到先前的注释。请参阅 "currentLocationHasBeenUpdated" 函数,我在其中尝试向先前的注释显示标准的红色图标。请让我知道我怎样才能做到这一点。谢谢
我的 ViewController :
import UIKit
import MapKit
class FirstTabController: UIViewController, MKMapViewDelegate, DelegateForUpdateCurrentLocation {
@IBOutlet weak var mapView: MKMapView!
var gpsLocations : [[String: AnyObject]]!
var dataManager : DataManager!
var currentAnnotation : MKAnnotation!
//Return CLLocation Coordinate
func getLocationObject(latitude:Double, longitude:Double) -> CLLocationCoordinate2D {
return CLLocationCoordinate2D(
latitude: latitude,
longitude: longitude
)
}
//Create annotation object & return
func createAnnotation(latitude:Double, longitude:Double, locationName:String, territory:String) -> MKPointAnnotation {
let annotation = MKPointAnnotation()
annotation.coordinate = self.getLocationObject(latitude, longitude: longitude)
annotation.title = locationName
annotation.subtitle = territory
return annotation
}
//Create annotaion for current ship position
func createAnnotationForCurrentPosition(location:[String: AnyObject]) -> MKPointAnnotation {
let latitude = (location["latitude"] as? Double)!
let longitude = (location["longitude"] as? Double)!
let name = (location["locationName"] as? String)!
let territory = (location["territory"] as? String)!
return self.createAnnotation(latitude, longitude: longitude, locationName: name, territory: territory)
}
//Set region on map view
func setRegion(location:[String: AnyObject]){
let latitude = (location["latitude"] as? Double)!
let longitude = (location["longitude"] as? Double)!
let location = self.getLocationObject(latitude, longitude: longitude)
//Set zoom span
let span = MKCoordinateSpanMake(0.05, 0.05)
//Create region on map view & show
let region = MKCoordinateRegion(center: location, span: span)
self.mapView.setRegion(region, animated: true)
}
//This function will fire from data manager when current location from API has been updated
func currentLocationHasBeenUpdated(location:[String: AnyObject]){
dispatch_async(dispatch_get_main_queue()){
if self.currentAnnotation != nil {
var currentAnnotationView = self.mapView.viewForAnnotation(self.currentAnnotation)
if currentAnnotationView != nil {
currentAnnotationView.image = nil //this line makes app crash [gave nil to show standard red icon]
// currentAnnotationView.image = UIImage(named:"first") - this line works perfectly with different icon. but i don't want any custom icon except the standard red one
}
}
self.mapView.addAnnotation(self.createAnnotationForCurrentPosition(location))
self.setRegion(location)
}
}
//Update map view by scheduling time if current location is changed yet
func updateMapView() {
self.dataManager.getCurrentLocation()
}
override func viewDidLoad() {
super.viewDidLoad()
//Get gps locations from data manager
self.dataManager = DataManager()
self.dataManager.delegate2 = self
self.dataManager.getCurrentLocation()
//self.mapView.userTrackingMode = MKUserTrackingMode.FollowWithHeading
//Get GPS location by scheduling time
NSTimer.scheduledTimerWithTimeInterval(60, target: self, selector: Selector("updateMapView"), userInfo: nil, repeats: true)
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer!{
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 2
return polylineRenderer
}
return nil
}
//Make custom annotaion pin if the annotation is of ship's current position
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!{
println("Hello")
self.currentAnnotation = annotation
//Custom annotation view with custom pin icon
let reuseId = "custom"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
annotationView.canShowCallout = true
}
else {
annotationView.annotation = annotation
}
//Set annotation specific properties after the view is dequeued or created...
annotationView.image = UIImage(named:"pinicon")
return annotationView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
以及来自 api
的坐标import Foundation
extension String {
func toDouble() -> Double? {
return NSNumberFormatter().numberFromString(self)?.doubleValue
}
}
class DataSet{
var settings : Settings!
var getService : GetService!
var currentLocation : [String: AnyObject]!
//Object initialization for API call
init(){
self.settings = Settings()
self.getService = GetService()
}
func getCurrentLocation(callback:([String: AnyObject]) -> ()){
self.getService.apiCallToGet(self.settings.getCoordinates(), callback: {
(response) in
var location = [String: AnyObject]()
for item in response {
if let dictionary = item as? NSDictionary {
if let lat = dictionary["Lat"] as? String {
if lat.toDouble() != nil {
location["latitude"] = lat.toDouble()!
}
}
if let long = dictionary["Long"] as? String {
if long.toDouble() != nil {
location["longitude"] = long.toDouble()!
}
}
if let name = dictionary["Name"] as? String {
location["locationName"] = name
}
if let territory = dictionary["Territory"] as? String {
location["territory"] = territory
}
println(location["latitude"]!)
println(location["longitude"]!)
if self.currentLocation != nil {
if ((self.currentLocation["latitude"] as? Double) != (location["latitude"] as? Double)) && ((self.currentLocation["longitude"] as? Double) != (location["longitude"] as? Double)){
self.currentLocation = location
callback(location)
}
} else {
self.currentLocation = location
callback(location)
}
}
}
})
}
}
我已经通过创建自定义注释 class 解决了我的问题,如下所示 -
import UIKit
import MapKit
var ARROW_ANNOTATION : NSString = "ARROW_ANNOTATION"
var PIN_ANNOTATION : NSString = "PIN_ANNOTATION"
class Annotation: NSObject, MKAnnotation {
var currentLocation: CLLocationCoordinate2D
var _title : String
var subTitle : String
var direction : CLLocationDirection!
var typeOfAnnotation : String!
init(coordinate: CLLocationCoordinate2D, title : String, subTitle : String) {
self.currentLocation = coordinate
self._title = title
self.subTitle = subTitle
}
func getLocation() -> CLLocation {
return CLLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
}
var coordinate: CLLocationCoordinate2D {
return self.currentLocation
}
var title : String {
return self._title
}
var subtitle : String {
return self.subTitle
}
}
并且在我的 ViewController 文件中 -
override func viewDidLoad() {
super.viewDidLoad()
var annotation1 : Annotation = Annotation(coordinate: location, title: name, subTitle: territory)
annotation.typeOfAnnotation = PIN_ANNOTATION as String
self.mapView.addAnnotation(annotation1)
var annotation2 : Annotation = Annotation(coordinate: location, title: name, subTitle: territory)
annotation.typeOfAnnotation = ARROW_ANNOTATION as String
self.mapView.addAnnotation(annotation2)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView!{
let reuseId = "custom"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
var customAnnotationView : MKAnnotationView!
if let _annotation = annotation as? Annotation {
if _annotation.typeOfAnnotation == PIN_ANNOTATION {
customAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
customAnnotationView.canShowCallout = true
//customAnnotationView.draggable = true
} else {
customAnnotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
// 17 - Determine the direction
let arrowImage = UIImage(named:"arrow")!
let direction = _annotation.direction
customAnnotationView.image = self.rotatedImage(arrowImage, byDegreesFromNorth: direction)
customAnnotationView.canShowCallout = true
}
} else {
return nil
}
return customAnnotationView
}