omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Mapview help

    Pythonista
    4
    9
    5676
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • shaun-h
      shaun-h last edited by

      If anyone could help that would be great I am trying to implement a mkmapviewdelegate to change the way pins look, now I have based this of @omz map view demo from a while ago.

      Here is the code

      # coding: utf-8
      # This has been derived for mapview example by Ole Zorn @omz url to come soon
      import ui
      import location
      from objc_util import *
      
      MKUserLocation = ObjCClass('MKUserLocation')
      MKAnnotationView = ObjCClass('MKPinAnnotationView')
      MKPointAnnotation = ObjCClass('MKPointAnnotation')
      MKPinAnnotationView = ObjCClass('MKPinAnnotationView')
      
      UIColor = ObjCClass('UIColor')
      def mapView_viewForAnnotation_(self, cmd, mk_mapview, annotation):
      	try:
      		anno = ObjCInstance(annotation)
      		mapView = ObjCInstance(mk_mapview)
      		if anno.isKindOfClass_(MKPointAnnotation):
      			pinView = mapView.dequeueReusableAnnotationViewWithIdentifier_('annoview')
      			if not pinView:
      				pinView = MKPinAnnotationView.alloc().initWithAnnotation_reuseIdentifier_(anno, 'annoview')
      				pinView.canShowCallout = False
      			else:
      				pinView.annotation = anno
      			return pinView
      		return None
      	except Exception as e:
      		print e
      		
      methods = [mapView_viewForAnnotation_]
      protocols = ['MKMapViewDelegate']
      try:
      	MyMapViewDelegate = ObjCClass('MyMapViewDelegate')
      except:
      	MyMapViewDelegate = create_objc_class('MyMapViewDelegate', NSObject, methods=methods, protocols=protocols)
      
      	
      
      class CLLocationCoordinate2D (Structure):
      	_fields_ = [('latitude', c_double), ('longitude', c_double)]
      	
      class MapView (ui.View):
      	@on_main_thread
      	def __init__(self, *args, **kwargs):
      		try:
      			ui.View.__init__(self, *args, **kwargs)
      			MKMapView = ObjCClass('MKMapView')
      			frame = CGRect(CGPoint(0, 0), CGSize(self.width, self.height))
      			self.mk_map_view = MKMapView.alloc().initWithFrame_(frame)
      			flex_width, flex_height = (1<<1), (1<<4)
      			self.mk_map_view.setAutoresizingMask_(flex_width|flex_height)
      			self_objc = ObjCInstance(self)
      			self_objc.addSubview_(self.mk_map_view)
      			self.mk_map_view.release()
      			self.map_delegate = MyMapViewDelegate.alloc().init().autorelease()
      			self.mk_map_view.setDelegate_(self.map_delegate)
      		except Exception as e:
      			print e
      		
      	@on_main_thread
      	def add_pin(self, lat, lon, title, subtitle=None, select=False):
      		'''Add a pin annotation to the map'''
      		MKPointAnnotation = ObjCClass('MKPointAnnotation')
      		coord = CLLocationCoordinate2D(lat, lon)
      		annotation = MKPointAnnotation.alloc().init().autorelease()
      		annotation.setTitle_(title)
      		if subtitle:
      			annotation.setSubtitle_(subtitle)
      		annotation.setCoordinate_(coord, restype=None, argtypes=[CLLocationCoordinate2D])
      		self.mk_map_view.addAnnotation_(annotation)
      		if select:
      			self.mk_map_view.selectAnnotation_animated_(annotation, True)
      	
      	@on_main_thread
      	def remove_all_pins(self):
      		'''Remove all annotations (pins) from the map'''
      		self.mk_map_view.removeAnnotations_(self.mk_map_view.annotations())
      		
      if __name__ == '__main__':
      	m = MapView()
      	location.start_updates()
      	loc = location.get_location()
      	location.stop_updates()
      	m.add_pin(lat = loc['latitude'], lon = loc['longitude'],title='Test')
      	m.mk_map_view.setShowsUserLocation_(False)
      	m.present()
      

      If I change return pinView to return None in mapView_viewForAnnotation_ then it doesn't crash and works happily, any advice would be great.

      Thanks

      1 Reply Last reply Reply Quote 0
      • brumm
        brumm last edited by

                    if not pinView:
                        pinView = MKPinAnnotationView.alloc().initWithAnnotation_reuseIdentifier_(anno, 'annoview')
                        pinView.canShowCallout = False
                        return None
                    else:
                        pinView.annotation = anno
                        return pinView
        

        Don't know if this makes sense (because I don't know anything about objc_util).

        1 Reply Last reply Reply Quote 0
        • shaun-h
          shaun-h last edited by

          Returning None will show the standard annotation view which I don't want to do, as referenced here

          It seems to crash when it tries to use the annotation view that I create, well that is what I think is the problem anyway.

          1 Reply Last reply Reply Quote 0
          • JonB
            JonB last edited by

            Have you tried retain_global(pinView)? That would fix a problem if it is falling out of scope.
            Alternatively, you might need to return pinView.ptr. I forget how callbacks work in objc, and whether that conversion is automatic.

            1 Reply Last reply Reply Quote 0
            • omz
              omz last edited by

              Yes, you need to return raw pointers from ObjC callbacks (as @JonB suggested), returning an ObjCInstance won't work.

              1 Reply Last reply Reply Quote 0
              • shaun-h
                shaun-h last edited by

                Thanks, @JonB & @omz the pinView.ptr seems to be working, I appreciate the help.

                1 Reply Last reply Reply Quote 0
                • shaun-h
                  shaun-h last edited by

                  I have ran in to another problem now. I have changed the code to try and use my own image for the mkannotationview see below

                  # coding: utf-8
                  # This has been derived for mapview example by Ole Zorn @omz url to come soon
                  import ui
                  import location
                  from objc_util import *
                  
                  MKUserLocation = ObjCClass('MKUserLocation')
                  MKAnnotationView = ObjCClass('MKAnnotationView')
                  MKPointAnnotation = ObjCClass('MKPointAnnotation')
                  MKPinAnnotationView = ObjCClass('MKPinAnnotationView')
                  
                  UIColor = ObjCClass('UIColor')
                  UIImage = ObjCClass('UIImage')
                  def mapView_viewForAnnotation_(self, cmd, mk_mapview, annotation):
                  	try:
                  		anno = ObjCInstance(annotation)
                  		mapView = ObjCInstance(mk_mapview)
                  		if anno.isKindOfClass_(MKPointAnnotation):
                  			pinView = mapView.dequeueReusableAnnotationViewWithIdentifier_('annoview')
                  			if not pinView:
                  				pinView = MKAnnotationView.alloc().initWithAnnotation_reuseIdentifier_(anno, 'annoview')
                  				pinView.canShowCallout = False
                  				pinView.image = ui.Image.named('iob:alert_24')
                  			else:
                  				pinView.annotation = anno
                  			return pinView.ptr
                  		return None
                  	except Exception as e:
                  		print 'exception: '
                  		print e
                  		
                  methods = [mapView_viewForAnnotation_]
                  protocols = ['MKMapViewDelegate']
                  try:
                  	MyMapViewDelegate = ObjCClass('MyMapViewDelegate')
                  except:
                  	MyMapViewDelegate = create_objc_class('MyMapViewDelegate', NSObject, methods=methods, protocols=protocols)
                  
                  	
                  
                  class CLLocationCoordinate2D (Structure):
                  	_fields_ = [('latitude', c_double), ('longitude', c_double)]
                  	
                  class MapView (ui.View):
                  	@on_main_thread
                  	def __init__(self, *args, **kwargs):
                  		try:
                  			ui.View.__init__(self, *args, **kwargs)
                  			MKMapView = ObjCClass('MKMapView')
                  			frame = CGRect(CGPoint(0, 0), CGSize(self.width, self.height))
                  			self.mk_map_view = MKMapView.alloc().initWithFrame_(frame)
                  			flex_width, flex_height = (1<<1), (1<<4)
                  			self.mk_map_view.setAutoresizingMask_(flex_width|flex_height)
                  			self_objc = ObjCInstance(self)
                  			self_objc.addSubview_(self.mk_map_view)
                  			self.mk_map_view.release()
                  			self.map_delegate = MyMapViewDelegate.alloc().init().autorelease()
                  			self.mk_map_view.setDelegate_(self.map_delegate)
                  		except Exception as e:
                  			print e
                  		
                  	@on_main_thread
                  	def add_pin(self, lat, lon, title, subtitle=None, select=False):
                  		'''Add a pin annotation to the map'''
                  		MKPointAnnotation = ObjCClass('MKPointAnnotation')
                  		coord = CLLocationCoordinate2D(lat, lon)
                  		annotation = MKPointAnnotation.alloc().init().autorelease()
                  		annotation.setTitle_(title)
                  		if subtitle:
                  			annotation.setSubtitle_(subtitle)
                  		annotation.setCoordinate_(coord, restype=None, argtypes=[CLLocationCoordinate2D])
                  		self.mk_map_view.addAnnotation_(annotation)
                  		if select:
                  			self.mk_map_view.selectAnnotation_animated_(annotation, True)
                  	
                  	@on_main_thread
                  	def remove_all_pins(self):
                  		'''Remove all annotations (pins) from the map'''
                  		self.mk_map_view.removeAnnotations_(self.mk_map_view.annotations())
                  		
                  if __name__ == '__main__':
                  	m = MapView()
                  	location.start_updates()
                  	loc = location.get_location()
                  	location.stop_updates()
                  	m.add_pin(lat = loc['latitude'], lon = loc['longitude'],title='Test')
                  	m.mk_map_view.setShowsUserLocation_(False)
                  	m.present()
                  

                  I get this exception thrown

                  exception:
                  Expected "}" (at char 9), (line:1, col:10)

                  Any help would be appreciated again

                  1 Reply Last reply Reply Quote 0
                  • omz
                    omz last edited by

                    This seems to be a bug in the objc_util module. For some reason, the type encoding for the setImage: method is not what I'd expect, and objc_util isn't able to parse it correctly.

                    I'll have to look into this in more depth, but here's a quick workaround:

                    # Instead of pinView.image = ... use:
                    setImage = pinView.setImage_
                    setImage.encoding = 'v24@0:8@16'
                    setImage(ui.Image.named('iob:alert_24'))
                    
                    1 Reply Last reply Reply Quote 1
                    • shaun-h
                      shaun-h last edited by

                      Thanks @omz that's works a treat, if you didn't know or guessed I tried it pythonista 3 and the same issue exists.

                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post
                      Powered by NodeBB Forums | Contributors