Can't change marker icon in MapKit - xcode

I did everything on the answer of this link:
Swift different images for Annotation
But the marker icon won't change it just stays the same I tried every way I could find on google but they all give the same result.
This is my code:
import UIKit
import MapKit
class Kaart: UIViewController, MKMapViewDelegate{
#IBOutlet weak var mapView: MKMapView!
let initialLocation = CLLocation(latitude: 52.20614380, longitude: 21.04759094)
let markerLocation = CLLocationCoordinate2D(latitude: 52.20614380, longitude: 21.04759094)
override func viewDidLoad() {
super.viewDidLoad()
UINavigationBar.appearance().translucent = false;
UINavigationBar.appearance().barTintColor = UIColor(red: CGFloat(193.0/255.0), green: 58/255, blue: 44/255, alpha: 1)
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor()]
//Set Default location
centerMapOnLocation(initialLocation)
//Place markers
var info1 = CustomPointAnnotation()
info1.coordinate = CLLocationCoordinate2DMake(42, -84)
info1.title = "Info1"
info1.subtitle = "Subtitle"
info1.imageName = "vlag.png"
mapView.addAnnotation(info1)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
let regionRadius: CLLocationDistance = 1000
func centerMapOnLocation(location: CLLocation) {
let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
regionRadius * 50.0, regionRadius * 50.0)
mapView.setRegion(coordinateRegion, animated: true)
}
func mapView(mapView: MKMapView!, viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if !(annotation is CustomPointAnnotation) {
return nil
}
let reuseId = "test"
var anView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if anView == nil {
anView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
anView.canShowCallout = true
}
else {
anView.annotation = annotation
}
//Set annotation-specific properties **AFTER**
//the view is dequeued or created...
let cpa = annotation as! CustomPointAnnotation
anView.image = UIImage(named:cpa.imageName)
return anView
}
}
class CustomPointAnnotation: MKPointAnnotation {
var imageName: String!
}

Related

Swift 5 & sheetPresentationController passing data

I am learning swift and trying to pass a variable to a sheet but it isn't changing the variable when the sheet pops up, is there a different way to do this?
let bottomSheet = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "bottomSheet")
if let sheet = bottomSheet.sheetPresentationController{
sheet.detents = [.medium()]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 24
sheet.prefersGrabberVisible = true
}
bottomSheet.isEnabled = true
self.present(bottomSheet, animated: true, completion: nil)
And in the bottomSheet view controller I have the variable
var isEnabled: Bool = false
But even though I put true it always shows as false
Try it like this, what you need to do is specify it as a view controller.
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil)
if let bottomSheet = mainStoryboard.instantiateViewController(withIdentifier: "bottomSheet") as? BottomSheetVC{
if let sheet = bottomSheet.sheetPresentationController{
sheet.detents = [.medium()]
sheet.prefersGrabberVisible = true
sheet.preferredCornerRadius = 24
sheet.prefersGrabberVisible = true
}
bottomSheet.isEnabled = true
self.present(bottomSheet, animated: true)
}
sheetPresentationController only work for ios 15 and later, for previously versions you need to set .custom modalPresentationStype
controller.modalPresentationStyle = .pageSheet
if #available(iOS 15.0, *) {
if let sheet = controller.sheetPresentationController {
sheet.detents = [.medium()]
}
} else {
controller.modalPresentationStyle = .custom
controller.transitioningDelegate = self
}
self.present(controller, animated: true, completion: nil)
// MARK: - UIViewControllerTransitioningDelegate
extension CPPdfPreviewVC: UIViewControllerTransitioningDelegate {
func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
PresentationController(presentedViewController: presented, presenting: presenting)
}
and Add Presentation controller as given
class PresentationController: UIPresentationController {
let blurEffectView: UIVisualEffectView!
var tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer()
override init(presentedViewController: UIViewController, presenting presentingViewController: UIViewController?) {
let blurEffect = UIBlurEffect(style: .dark)
blurEffectView = UIVisualEffectView(effect: blurEffect)
super.init(presentedViewController: presentedViewController, presenting: presentingViewController)
tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissController))
blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.blurEffectView.isUserInteractionEnabled = true
self.blurEffectView.addGestureRecognizer(tapGestureRecognizer)
}
override var frameOfPresentedViewInContainerView: CGRect {
CGRect(origin: CGPoint(x: 0, y: self.containerView!.frame.height * 0.4),
size: CGSize(width: self.containerView!.frame.width, height: self.containerView!.frame.height *
0.6))
}
override func presentationTransitionWillBegin() {
self.blurEffectView.alpha = 0
self.containerView?.addSubview(blurEffectView)
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0.7
}, completion: { (UIViewControllerTransitionCoordinatorContext) in })
}
override func dismissalTransitionWillBegin() {
self.presentedViewController.transitionCoordinator?.animate(alongsideTransition: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.alpha = 0
}, completion: { (UIViewControllerTransitionCoordinatorContext) in
self.blurEffectView.removeFromSuperview()
})
}
override func containerViewWillLayoutSubviews() {
super.containerViewWillLayoutSubviews()
presentedView!.roundCorners([.topLeft, .topRight], radius: 22)
}
override func containerViewDidLayoutSubviews() {
super.containerViewDidLayoutSubviews()
presentedView?.frame = frameOfPresentedViewInContainerView
blurEffectView.frame = containerView!.bounds
}
#objc func dismissController(){
self.presentedViewController.dismiss(animated: true, completion: nil)
}
}
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners,
cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
layer.mask = mask
}
}
}

Looping Videos with XCode ARKit Image Tracking

Hello I'm new into developing and right now I'm working on an AR application which works with image tracking and it should play different videos on different tracked images.
Right now the video stops, how can I loop the video?
Also if the image is not in the camera view, the video continues. Is there a pause function too?
I would be thankful for every hints.
import UIKit
import SceneKit
import ARKit
class ViewController: UIViewController, ARSCNViewDelegate {
#IBOutlet var sceneView: ARSCNView!
override func viewDidLoad() {
super.viewDidLoad()
sceneView.delegate = self
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let configuration = ARImageTrackingConfiguration()
if let trackedImages = ARReferenceImage.referenceImages(inGroupNamed: "AR Resources", bundle: Bundle.main) {
configuration.trackingImages = trackedImages
configuration.maximumNumberOfTrackedImages = 2
}
sceneView.session.run(configuration)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
sceneView.session.pause()
}
func renderer(_ renderer: SCNSceneRenderer, nodeFor anchor: ARAnchor) -> SCNNode? {
let node = SCNNode()
if let imageAnchor = anchor as? ARImageAnchor {
let size = imageAnchor.referenceImage.physicalSize
var videoNode = SKVideoNode()
switch imageAnchor.name {
case "Image1":
videoNode = SKVideoNode(fileNamed: "Image1.mp4")
case "Image2":
videoNode = SKVideoNode(fileNamed: "Image2.mp4")
case "Image3":
videoNode = SKVideoNode(fileNamed: "Image3.mp4")
default:
break
}
videoNode.play()
let videoScene = SKScene(size: CGSize(width: 1280, height: 960))
videoScene.anchorPoint = CGPoint(x: 0.5, y: 0.5)
videoScene.addChild(videoNode)
let plane = SCNPlane(width: size.width, height: size.height)
plane.firstMaterial?.diffuse.contents = videoScene
let planeNode = SCNNode(geometry: plane)
plane.firstMaterial?.isDoubleSided = true
planeNode.eulerAngles.x = .pi / 2
node.addChildNode(planeNode)
return node
}
return nil
}
}

Customise Annotation in MapKit in swiftUI

Im try to customise my annotation in MapKit and SwiftUI
From the code below, I search in the map the specific coordinate (coord) and I display with my custom annotation.
1) I'm try to increase the size of the UIimage because to small (see the picture attached)and change the color, any idea how?
2)in the map after the app start it display only the icon, after I tap on the icon the annotation appear, any idea how to display immediately my annotation without tapping?
3)now in the annotation I manage to display title and subtitle, how to display also the coordinate
struct MapView: UIViewRepresentable {
let Mm : MapManager
let coord = CLLocationCoordinate2D(latitude: 52.28792, longitude: 4.73415327)
class Coordinator: NSObject, MKMapViewDelegate {
var parent : MapView
init(_ parent: MapView) {
self.parent = parent
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "TESTING NOTE")
annotationView.canShowCallout = true
annotationView.image = UIImage(systemName: "location.circle")
return annotationView
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> MKMapView {
let view = MKMapView(frame: .zero)
Mm.georeverseCoordinate(coord) { (pin) in
if let pinOK = pin {
view.removeAnnotation(pinOK)
view.mapType = MKMapType.satellite
let span = MKCoordinateSpan(latitudeDelta: 0.04, longitudeDelta: 0.04)
let region = MKCoordinateRegion(center: self.coord, span: span)
view.setRegion(region, animated: true)
view.delegate = context.coordinator
view.addAnnotation(pinOK)
}
}
return view
}
func updateUIView(_ view: MKMapView, context: Context) {
}
}
Map manager
class MapManager: NSObject, CLLocationManagerDelegate {
static let shared = MapManager()
func georeverseCoordinate(_ coord: CLLocationCoordinate2D , closure: #escaping (Pin?) -> Void) {
let location = CLLocation(latitude: coord.latitude, longitude: coord.longitude)
let geocoder = CLGeocoder()
geocoder.reverseGeocodeLocation(location) { (arrayResponse, error) in
if let errorTest = error {
debugPrint(errorTest.localizedDescription)
closure(nil)
return
}
if let arrayPins = arrayResponse {
if let valorePinArray = arrayPins.first {
debugPrint(valorePinArray.locality!)
debugPrint(valorePinArray.isoCountryCode!)
let pin = Pin(title: valorePinArray.locality!, subtitle: valorePinArray.isoCountryCode!, coordinate: valorePinArray.location!.coordinate)
closure(pin)
}
else { closure(nil) }
}
else { closure(nil) }
}
}
}
Pin Model
class Pin:NSObject, MKAnnotation {
var title : String?
var subtitle : String?
var coordinate : CLLocationCoordinate2D
var color: UIColor?
init(title: String?, subtitle: String?, coordinate: CLLocationCoordinate2D) {
self.title = title
self.subtitle = subtitle
self.coordinate = coordinate
}
}
1) - There seems to be a bug that makes it difficult to change the colour of SF Symbols with tintColor and a specific rendering mode but there is a workaround that also allows an easy way to change the size of the symbol.
In mapView:viewFor annotation add the following:
annotationView.canShowCallout = true
annotationView.image = UIImage(systemName: "location.circle")?.withTintColor(.systemGreen, renderingMode: .alwaysOriginal)
let size = CGSize(width: 40, height: 40)
annotationView.image = UIGraphicsImageRenderer(size:size).image {
_ in annotationView.image!.draw(in:CGRect(origin:.zero, size:size))
}
2) - To show the callout as soon as the annotation is added to the map, use selectAnnotation.
view.addAnnotation(pinOK)
view.selectAnnotation(pinOK, animated: true)
3) - The coordinate is available when your annotation is being constructed so you can simply change the init in the Pin class:
init(title: String?, subtitle: String?, coordinate: CLLocationCoordinate2D) {
self.coordinate = coordinate
self.title = "\(coordinate.latitude) : \(coordinate.longitude)"
self.subtitle = subtitle
}

How do I clear pins on a mapview in swift?

Part of my app contains a mapview which searches automatically based on a keyword. I added a textbox and search button to my mapview, but I noticed the pins do not clear from the previous search. How do I clear the map of all pins before the new search?
import UIKit
import MapKit
import CoreLocation
import iAd
class MapClass: UIViewController, CLLocationManagerDelegate, UISearchBarDelegate, ADBannerViewDelegate {
var searchController:UISearchController!
var annotation:MKAnnotation!
var localSearchRequest:MKLocalSearchRequest!
var localSearch:MKLocalSearch!
var localSearchResponse:MKLocalSearchResponse!
var error:NSError!
var pointAnnotation:MKPointAnnotation!
var pinAnnotationView:MKPinAnnotationView!
var holidayKeyWord = NSString()
#IBOutlet var mapSearchTextbox: UITextField!
#IBOutlet weak var mapView: MKMapView!
#IBOutlet var adBannerView: ADBannerView!
var locationManager: CLLocationManager!
let searchRadius: CLLocationDistance = 2000
override func viewDidLoad() {
super.viewDidLoad()
holidayKeyWord = "Restaurant"
println(holidayKeyWord)
mapSearchTextbox.text = holidayKeyWord as String
self.canDisplayBannerAds = true
self.adBannerView?.delegate = self
self.adBannerView?.hidden = false
if (CLLocationManager.locationServicesEnabled())
{
locationManager = CLLocationManager()
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
}
#IBAction func mapSearchButton(sender: UIButton) {
//clear pins
var holidayKeyWord = mapSearchTextbox.text
if (CLLocationManager.locationServicesEnabled())
{
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = holidayKeyWord as String
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler {
(response: MKLocalSearchResponse!, error: NSError!) in
for item in response.mapItems as! [MKMapItem] {
println(item.name)
self.addPinToMapView(item.name, latitude: item.placemark.location.coordinate.latitude, longitude: item.placemark.location.coordinate.longitude)
}
}
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//replace spaces with dashes in wikiDate string
if (segue.identifier == "amazonToWeb") {
var wikiDate = "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Ddigital-text&field-keywords=\(holidayKeyWord)"
var DestViewController : WebBrowser = segue.destinationViewController as! WebBrowser
DestViewController.wikiDate = wikiDate
}
if (segue.identifier == "searchToWeb") {
var wikiDate = "http://www.bing.com"
var DestViewController : WebBrowser = segue.destinationViewController as! WebBrowser
DestViewController.wikiDate = wikiDate
}
if (segue.identifier == "ebayToWeb") {
var wikiDate = "http://search.ebay.com/\(holidayKeyWord)"
var DestViewController : WebBrowser = segue.destinationViewController as! WebBrowser
DestViewController.wikiDate = wikiDate
}
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
let location = locations.last as! CLLocation
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
self.mapView.setRegion(region, animated: true)
var latitude: Double = location.coordinate.latitude
var longitude: Double = location.coordinate.longitude
let initialLocation = CLLocation(latitude: latitude, longitude: longitude)
// 1
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = holidayKeyWord as String
// 2
let span = MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1)
request.region = MKCoordinateRegion(center: initialLocation.coordinate, span: span)
// 3
let search = MKLocalSearch(request: request)
search.startWithCompletionHandler {
(response: MKLocalSearchResponse!, error: NSError!) in
for item in response.mapItems as! [MKMapItem] {
println(item.name)
//println("Latitude = \(item.placemark.location.coordinate.latitude)")
//println("Longitude = \(item.placemark.location.coordinate.longitude)")
self.addPinToMapView(item.name, latitude: item.placemark.location.coordinate.latitude, longitude: item.placemark.location.coordinate.longitude)
}
}
locationManager.stopUpdatingLocation()
let coordinateRegion = MKCoordinateRegionMakeWithDistance(initialLocation.coordinate, searchRadius * 2.0, searchRadius * 2.0)
mapView.setRegion(coordinateRegion, animated: true)
}
func addPinToMapView(title: String, latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let annotation = MyAnnotation(coordinate: location, title: title)
mapView.addAnnotation(annotation)
}
func removePinFromMapView(title: String, latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
let location = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let annotation = MyAnnotation(coordinate: location, title: title)
mapView.removeAnnotation(annotation)
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
{
println("Error: " + error.localizedDescription)
}
Iterate through your annotations and delete them one by one like this:
if let annotations = self.mapView.annotations {
for _annotation in annotations {
if let annotation = _annotation as? MKAnnotation
{
self.mapView.removeAnnotation(annotation)
}
}
}
There is a short way of doing #ezcoding's answer.
mapView.removeAnnotations(mapView.annotations)
You are adding the pins by saying addAnnotation. To remove them, just reverse that: say removeAnnotation.
[self.mapView removeAnnotations:mapView.annotations];
For Swift 3.0
func removeAllAnnotations() {
for annotation in self.mapView.annotations {
self.mapView.removeAnnotation(annotation)
}
}

Swift Ios 8 MKPolylineRenderer to trace location

Hi so i am having trouble with trying to create this MKPolyline for my ios 8 app. This is suppose to trace the users's location and draw a line where ever it goes. I have been looking at tutorials online and they are using ios 7 or 6. Any help would be great. Thank in advance .
import UIKit
import MapKit
import CoreLocation
class SecondViewController: UIViewController , CLLocationManagerDelegate , MKMapViewDelegate{
#IBOutlet weak var map: MKMapView!
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
var currentLocation = CLLocation()
self.locationManager.delegate = self
self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
self.locationManager.requestWhenInUseAuthorization()
self.locationManager.startUpdatingLocation()
var pinLocation : CLLocationCoordinate2D = CLLocationCoordinate2DMake(locationManager.location.coordinate.latitude , locationManager.location.coordinate.longitude)
var objectAnnotation = MKPointAnnotation()
objectAnnotation.coordinate = pinLocation
objectAnnotation.title = "Current Location"
self.map.addAnnotation(objectAnnotation)
}
func addPolyLineToMap(locations: [CLLocation!])
{
var coordinates = locations.map({ (location: CLLocation!) -> CLLocationCoordinate2D in
return location.coordinate
})
var geodesic = MKGeodesicPolyline(coordinates: &coordinates[0], count: 2)
map.addOverlay(geodesic , level: MKOverlayLevel.AboveRoads )
}
func mapView(mapView: MKMapView!, rendererForOverlay overlay: MKOverlay!) -> MKOverlayRenderer! {
if overlay is MKPolyline {
var polylineRenderer = MKPolylineRenderer(overlay: overlay)
polylineRenderer.strokeColor = UIColor.blueColor()
polylineRenderer.lineWidth = 4
return polylineRenderer
}
return nil
}
func locationManager(manager: CLLocationManager!, didFailWithError error: NSError!)
{
println("Error: " + error.localizedDescription)
}
func locationManager(manager: CLLocationManager!, didUpdateLocations locations: [AnyObject]!) {
//centering location
let location = locations.last as CLLocation
let center = CLLocationCoordinate2D(latitude: location.coordinate.latitude, longitude: location.coordinate.longitude)
let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.01, longitudeDelta: 0.01))
var latDelta:CLLocationDegrees = 0.01
var longDelta:CLLocationDegrees = 0.01
var theSpan:MKCoordinateSpan = MKCoordinateSpanMake(latDelta, longDelta)
`var pointLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude , location.coordinate.longitude)
map.setRegion(region, animated: true)
addPolyLineToMap(location)
}
}

Resources