ピンを配置しようとすると、マップビュー内に読み込むカスタムアノテーションを取得する際に問題が発生します。
import UIKit
import MapKit
import CoreLocation
class MapViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate{
@IBAction func ReportBtn(sender: AnyObject) {
//MARK: Report Date And Time Details
let ReportTime = NSDate()
let TimeStamp = NSDateFormatter()
TimeStamp.timeStyle = NSDateFormatterStyle.ShortStyle
TimeStamp.dateStyle = NSDateFormatterStyle.ShortStyle
TimeStamp.stringFromDate(ReportTime)
//MARK: Default Point Annotation Begins
let ReportAnnotation = MKPointAnnotation()
ReportAnnotation.title = "Annotation Created"
ReportAnnotation.subtitle = ReportTime.description
ReportAnnotation.coordinate = locationManager.location!.coordinate
mapView(MainMap, viewForAnnotation: ReportAnnotation)
MainMap.addAnnotation(ReportAnnotation)
}
@IBOutlet weak var MainMap: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.startUpdatingLocation()
self.MainMap.showsUserLocation = true
}
//MARK: - Location Delegate Methods
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = locations.last
let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.02, longitudeDelta: 0.02 ))
self.MainMap.setRegion(region, animated: true)
//self.locationManager.stopUpdatingLocation()
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError){
print(error.localizedDescription)
}
//MARK:Custom Annotation Begins Here
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
/*if annotation.isKindOfClass(MKUserLocation){
//emty return, guard wasn't cooperating
}else{
return nil
}*/
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier){
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
else{
let av = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView = av
}
if let annotationView = annotationView {
annotationView.canShowCallout = true
annotationView.image = UIImage(named: "image.png")
}
return annotationView
}
}
ボタンの機能が完璧に機能することを確信しています。上記のダンプされた現在のコードでは、デフォルトの赤いピン注釈が正しい場所に表示されます。ピンをタップすると、指定した説明も問題なく表示されます。 このコードで抱えている唯一の問題は、退屈なデフォルトの赤いピンの代わりに自分の画像を取得できないことです
`MKPointAnnotationをサブクラス化することをお勧めします。
カスタムマップピンを表示するために必要なコードのみを含めました。 templateと考えてください。
概要
ポイント注釈オブジェクトを作成し、CustomPointAnnotation
クラスを使用してカスタム画像名を割り当てます。
MKPointAnnotation
をサブクラス化して画像を設定し、デリゲートプロトコルメソッドviewForAnnotation
に割り当てます。
ポイントアノテーションの座標をタイトルとサブタイトルで設定した後、マップにアノテーションビューを追加します。
ピンをマップ上に表示するために呼び出されるviewForAnnotation
プロトコルメソッドであるMKMapViewDelegate
メソッドを実装します。 viewForAnnotation
プロトコルメソッドは、ピンビューをカスタマイズしてカスタムイメージを割り当てるのに最適な場所です。
ピンの画像名にアクセスするために、特定の識別子の再利用可能な注釈をデキューして返し、カスタムCustomPointAnnotation
クラスに注釈をキャストします。
Assets.xcassets
に新しい画像セットを作成し、それに応じて[email protected]と[email protected]を配置します。
Plistを忘れないでください。
NSLocationAlwaysUsageDescription
およびNSLocationWhenInUseUsageDescription
いつものように、実際のデバイスでテストします。
スウィズル????
// 1
CustomPointAnnotation.Swift
import UIKit
import MapKit
class CustomPointAnnotation: MKPointAnnotation {
var pinCustomImageName:String!
}
// 2
ViewController.Swift
import UIKit
import MapKit
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
@IBOutlet weak var pokemonMap: MKMapView!
let locationManager = CLLocationManager()
var pointAnnotation:CustomPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
override func viewDidLoad() {
super.viewDidLoad()
//Mark: - Authorization
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.startUpdatingLocation()
pokemonMap.delegate = self
pokemonMap.mapType = MKMapType.Standard
pokemonMap.showsUserLocation = true
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
let location = CLLocationCoordinate2D(latitude: 35.689949, longitude: 139.697576)
let center = location
let region = MKCoordinateRegionMake(center, MKCoordinateSpan(latitudeDelta: 0.025, longitudeDelta: 0.025))
pokemonMap.setRegion(region, animated: true)
pointAnnotation = CustomPointAnnotation()
pointAnnotation.pinCustomImageName = "Pokemon Pin"
pointAnnotation.coordinate = location
pointAnnotation.title = "POKéSTOP"
pointAnnotation.subtitle = "Pick up some Poké Balls"
pinAnnotationView = MKPinAnnotationView(annotation: pointAnnotation, reuseIdentifier: "pin")
pokemonMap.addAnnotation(pinAnnotationView.annotation!)
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print(error.localizedDescription)
}
//MARK: - Custom Annotation
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let reuseIdentifier = "pin"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseIdentifier)
annotationView?.canShowCallout = true
} else {
annotationView?.annotation = annotation
}
let customPointAnnotation = annotation as! CustomPointAnnotation
annotationView?.image = UIImage(named: customPointAnnotation.pinCustomImageName)
return annotationView
}
}
対処する必要があるいくつかの問題があります。
まず、MKMapView
が注釈から注釈ビューを表示する方法を理解する必要があります。がある
MKAnnotation
は、地図上の場所のデータを保持します。このデータを作成し、MKMapView
に渡します。将来のある時点で、マップビューが注釈を表示する準備ができたら、デリゲートにコールバックし、MKAnnotationView
のMKAnnotation
を作成するように要求します。デリゲートはビューを作成して返し、マップビューに表示されます。ストーリーボードまたはコードでデリゲートを指定します。 mapView.delegate = self
。
ユーザーの場所の追跡は、次の点で複雑です。
コードは、CLLocationManager.authorizationStatus
を確認し、CLLocationManagerDelegate
メソッドを実装することにより、承認を処理する必要があります。
requestWhenInUseAuthorization
を使用するには、Info.plist
のNSLocationWhenInUseUsageDescription
のエントリが必要です。
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate {
// Instance of location manager.
// This is is created in viewDidLoad() if location services are available.
var locationManager: CLLocationManager?
// Last location made available CoreLocation.
var currentLocation: MKUserLocation? {
didSet {
// Hide the button if no location is available.
button.hidden = (currentLocation == nil)
}
}
// Date formatter for formatting dates in annotations.
// We use a lazy instance so that it is only created when needed.
lazy var formatter: NSDateFormatter = {
let formatter = NSDateFormatter()
formatter.timeStyle = NSDateFormatterStyle.ShortStyle
formatter.dateStyle = NSDateFormatterStyle.ShortStyle
return formatter
}()
@IBOutlet var button: UIButton!
@IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
mapView.delegate = self
// Track the user's location if location services are enabled.
if CLLocationManager.locationServicesEnabled() {
locationManager = CLLocationManager()
locationManager?.delegate = self
locationManager?.desiredAccuracy = kCLLocationAccuracyBest
switch CLLocationManager.authorizationStatus() {
case .AuthorizedAlways, .AuthorizedWhenInUse:
// Location services authorised.
// Start tracking the user.
locationManager?.startUpdatingLocation()
mapView.showsUserLocation = true
default:
// Request access for location services.
// This will call didChangeAuthorizationStatus on completion.
locationManager?.requestWhenInUseAuthorization()
}
}
}
//
// CLLocationManagerDelegate method
// Called by CLLocationManager when access to authorisation changes.
//
func locationManager(manager: CLLocationManager, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
switch status {
case .AuthorizedAlways, .AuthorizedWhenInUse:
// Location services are authorised, track the user.
locationManager?.startUpdatingLocation()
mapView.showsUserLocation = true
case .Denied, .Restricted:
// Location services not authorised, stop tracking the user.
locationManager?.stopUpdatingLocation()
mapView.showsUserLocation = false
currentLocation = nil
default:
// Location services pending authorisation.
// Alert requesting access is visible at this point.
currentLocation = nil
}
}
//
// MKMapViewDelegate method
// Called when MKMapView updates the user's location.
//
func mapView(mapView: MKMapView, didUpdateUserLocation userLocation: MKUserLocation) {
currentLocation = userLocation
}
@IBAction func addButtonTapped(sender: AnyObject) {
guard let coordinate = currentLocation?.coordinate else {
return
}
let reportTime = NSDate()
let formattedTime = formatter.stringFromDate(reportTime)
let annotation = MKPointAnnotation()
annotation.title = "Annotation Created"
annotation.subtitle = formattedTime
annotation.coordinate = coordinate
mapView.addAnnotation(annotation)
}
//
// From Bhoomi's answer.
//
// MKMapViewDelegate method
// Called when the map view needs to display the annotation.
// E.g. If you drag the map so that the annotation goes offscreen, the annotation view will be recycled. When you drag the annotation back on screen this method will be called again to recreate the view for the annotation.
//
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView!.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "smile")
return annotationView
}
}
プロジェクトバンドルまたはAssets.xcassetsのimage.pngを確認します
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation.isKindOfClass(MKUserLocation) else {
return nil
}
let annotationIdentifier = "AnnotationIdentifier"
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
annotationView.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
annotationView!.canShowCallout = true
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "image.png")
return annotationView
}
次のようにしてくださいあなたのために働くかもしれません。
1)注釈ピンのカスタムクラスを作成します。
_class CustomPointAnnotation: MKPointAnnotation {
var imageName: UIImage!
}
_
2)変数を以下のように定義します。
_var locationManager = CLLocationManager()
_
3)viewDidLoad()
の以下のメソッドを呼び出します
_ func checkLocationAuthorizationStatus() {
if CLLocationManager.authorizationStatus() == .AuthorizedAlways {
map.showsUserLocation = false
} else {
locationManager.requestWhenInUseAuthorization()
}
}
_
4)viewWillAppear()
のコードの下に配置
_ self.map.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestAlwaysAuthorization()
locationManager.delegate = self
dispatch_async(dispatch_get_main_queue(),{
self.locationManager.startUpdatingLocation()
})
_
5)最も重要な実装方法は以下です。
_ func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "Location"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView!.canShowCallout = true
}
else {
anView!.annotation = annotation
}
let cpa = annotation as! CustomPointAnnotation
anView!.image = cpa.imageName
return anView
}
_
6)カスタムPINイメージを受け取った場所で以下のコードを実行します
_ let strLat = "YOUR LATITUDE"
let strLon = "YOUR LONGITUDE"
let info = CustomPointAnnotation()
info.coordinate = CLLocationCoordinate2DMake(strLat.toDouble()!,strLon.toDouble()!)
info.imageName = resizedImage
info.title = dict!["locationName"]! as? String
self.map.addAnnotation(info)
_
コードから、MapKitガイドに従って、コードは正しく見えます。私はそれがこの行であると考えていますannotationView.image = UIImage(named: "image.png")
_image.png
_が間違ったイメージ名であるか、コンパイル時にプロジェクトに追加されない可能性はありますか?また、単にfyiで、_.xcassets
_を使用している場合は、_.png
_を追加する必要はありません。
_annotationView.image
_はオプションであるため、イメージUIImage(named: "image.png")
がnilの場合、クラッシュせず、デフォルトのピンイメージをレンダリングするだけです。
これが問題でない場合は、他の人がよりよく理解してあなたを助けることができるように、あなたが取ったデバッグ手順に関する詳細情報を提供してください。乾杯=)