omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular
    1. Home
    2. blmacbeth

    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.


    • Profile
    • Following 0
    • Followers 1
    • Topics 12
    • Posts 65
    • Best 15
    • Controversial 0
    • Groups 0

    blmacbeth

    @blmacbeth

    24
    Reputation
    1590
    Profile views
    65
    Posts
    1
    Followers
    0
    Following
    Joined Last Online

    blmacbeth Unfollow Follow

    Best posts made by blmacbeth

    • RE: Drop Shadow behind ui.view()

      I have been playing around with objc_util again and came up with this piece of code you might find applicable to your code above:

      # coding: utf-8
      from objc_util import *
      import ui
      
      UIColor = ObjCClass('UIColor')
      
      view = ui.View(frame=(0,0,500,500))
      box  = ui.View(frame=(0,0,100,100))
      
      view.background_color = 'white'
      box.background_color = 'red'
      box.center = view.center
      
      view.add_subview(box)
      
      box_pntr = ObjCInstance(box)
      ## Note: this allows for shadows to be drawn
      box_pntr.layer().setMasksToBounds_(False)
      box_pntr.layer().setCornerRadius_(6)
      ## Note: CGColor is needed in order for this to work
      box_pntr.layer().setBorderColor_(UIColor.cyanColor().CGColor())
      box_pntr.layer().setBorderWidth_(3)
      box_pntr.layer().setShadowRadius_(10)
      box_pntr.layer().setShadowOffset_(CGSize(0,0))
      box_pntr.layer().setShadowOpacity_(1.0)
      
      view.present('sheet')
      

      Hope you find this useful.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • [Share Code] TabBar

      Here is a work-in-progress of a UITabBar. It sometimes crashes…

      # coding: utf-8
      from objc_util import *
      import ctypes
      import weakref
      import ui
      
      _tab_bar_delegate_cache = weakref.WeakValueDictionary()
      _retain_me = None ## stops from crashing
      
      try:
      	BLMTabBarDelegate = ObjCClass('BLMTabBarDelegate')
      except ValueError:
      	@ctypes.CFUNCTYPE(None, c_void_p, c_void_p, c_void_p, c_void_p)
      	def tabBar_didSelectItem_(self, cmd, tab_bar, tab_bar_item):
      		tab_bar = _tab_bar_delegate_cache[self].tab_bar_ref()
      		if tab_bar:
      			tab_bar._notify_did_select_item()
      	
       	_retain_me = tabBar_didSelectItem_ ## stop garbage collection 
      	NSObject = ObjCClass('NSObject')
      	class_ptr = c.objc_allocateClassPair(NSObject.ptr, 'BLMTabBarDelegate', 0)
      	selector = sel('tabBar:didSelectItem:')
      	c.class_addMethod(class_ptr, selector, tabBar_didSelectItem_, 'v0@0:0@0@0')
      	c.objc_registerClassPair(class_ptr)
      	BLMTabBarDelegate = ObjCClass('BLMTabBarDelegate')
      
      UITabBar     = ObjCClass('UITabBar')
      UITabBarItem = ObjCClass('UITabBarItem')
      
      class TabBar (ui.View):
      	@on_main_thread
      	def __init__(self, *args, **kwargs):
      		super(TabBar, self).__init__(*args, **kwargs)
      		frame = CGRect(CGPoint(0, 0), CGSize(self.width, self.height))
      		self.tab_bar = UITabBar.alloc().initWithFrame_(frame).autorelease()
      		flex_width, flex_height = (1<<1), (1<<4)
      		self.tab_bar.setAutoresizingMask_(flex_width|flex_height)
      		self_objc = ObjCInstance(self)
      		self_objc.addSubview_(self.tab_bar)
      		self.item_changed_action = None
      		self.tab_bar_delegate = BLMTabBarDelegate.new().autorelease()
      		self.tab_bar.setDelegate_(self.tab_bar_delegate)
      		self.tab_bar_delegate.tab_bar_ref = weakref.ref(self)
      		_tab_bar_delegate_cache[self.tab_bar_delegate.ptr] = self.tab_bar_delegate
      	
      		
      	@property
      	@on_main_thread
      	def items(self):
      		return self.tab_bar.items()
      	
      	@items.setter
      	@on_main_thread
      	def items(self, items):
      		self.tab_bar.setItems_animated_(items, True)
      		
      	@property
      	@on_main_thread
      	def selected_item(self):
      		return self.tab_bar.selectedItem()
      	
      	@property
      	@on_main_thread
      	def delegate(self):
      		return self.delegate()
      	
      	@delegate.setter
      	@on_main_thread
      	def delegate(self, delegate):
      		self.tab_bar.setDelegate_(delegate)
      		
      	def _notify_did_select_item(self):
      		if callable(self.item_changed_action):
      			self.item_changed_action(self)
      	
      
      
      tab_bar_item_1 = UITabBarItem.alloc().initWithTabBarSystemItem_tag_(0,0).autorelease()
      
      tab_bar_item_2 = UITabBarItem.alloc().initWithTabBarSystemItem_tag_(1,1).autorelease()
      
      def tab_bar_item_changed(sender):
      	print sender.selected_item.description()
      
      root = ui.View(frame=(0,0,500,500))
      tab_bar = TabBar(frame=(0,451,500,49))
      tab_bar.items = [tab_bar_item_1, tab_bar_item_2]
      tab_bar.item_changed_action = tab_bar_item_changed
      root.add_subview(tab_bar)
      root.present('sheet')
      
      

      Let me know what you think,
      B

      EDIT added code to prevent crashes

      posted in Pythonista
      blmacbeth
      blmacbeth
    • [Suggestion] Location Context Manager

      I was playing around with the location module the other day and was wondering about how it deals with scripts closing without manually turning off location tracking. So I made a context Manager for the location module

      import location
      
      
      class LocationManager (object):
          def __enter__(self):
              location.start_updates()
      
          def __exit__(self):
              location.stop_updates()
      

      You can use it like so:

      with LocationManager():
          # Do stuff that requires `location` here...
          ...
      

      Now, this may be completely unnecessary, but I have found it useful for applications where constant location updates are not needed (e.g. get my location every 15 minutes or set my initial location for some one off script).

      @omz also think this may be a good feature for the built-in location module to adopt (if possible). So we can have both location.start(stop)_updates() or with location: ....

      Let me know what y'all think (criticism is welcome).

      B.

      EDIT
      A bit less verbose code with the help of @ccc on contexlib

      import contexlib
      import location
      
      @contexlib.contexmanager
      def location_enabled():
          location.start_updates()
          yield
          location.stop_updates()
      

      the use case is still the same.

      with location_enabled():
          # Do location stuff here...
          ...
      
      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: Drop Shadow behind ui.view()

      Ask and he shall receive. It's not perfect, yet. There are some clipping problems I can't figure out.

      # coding: utf-8
      from objc_util import *
      import ui
      
      UIColor = ObjCClass('UIColor')
      
      def Color(red=0, green=0, blue=0, alpha=1):
      	return UIColor.colorWithRed_green_blue_alpha_(red, green, blue, alpha)
      
      class ShadowView (ui.View):
      	def __init__(self, *args, **kwargs):
      		super(ShadowView, self).__init__()
      		self.pntr = ObjCInstance(self)
      		self.pntr.layer().setMasksToBounds_(False) ## Go ahead and do this.
      		
      	@property 
      	def corner_radius(self):
      		return self.pntr.layer().cornerRadius()
      		
      	@corner_radius.setter
      	def corner_radius(self, val):
      		self.pntr.layer().setCornerRadius_(val)
      		
      	@property
      	def border_color(self):
      		return self.pntr.layer().borderColor()
      		
      	@border_color.setter
      	def border_color(self, color):
      		self.pntr.layer().setBorderColor_(Color(*color).CGColor())
      		
      	@property
      	def border_width(self):
      		return self.pntr.layer().borderWidth()
      		
      	@border_width.setter
      	def border_width(self, val):
      		self.pntr.layer().setBorderWidth_(val)
      		
      	@property 
      	def opacity(self):
      		return self.pntr.layer().opacity()
      		
      	@opacity.setter
      	def opacity(self, val):
      		self.pntr.layer().setOpacity_(value)
      		
      	@property 
      	def hidden(swlf):
      		return self.pntr.layer().hidden()
      		
      	@hidden.setter
      	def hidden(self, val):
      		self.pntr.layer().setHidden_(val)
      		
      	@property 
      	def masks_to_bounds(self):
      		return self.pntr.layer().masksToBounds()
      		
      	@masks_to_bounds.setter
      	def masks_to_bounds(self, val):
      		self.pntr.layer().setMasksToBounds_(val)
      		
      	@property 
      	def mask(self):
      		return self.pntr.layer().mask()
      		
      	@mask.setter
      	def mask(self, new_mask):
      		self.pntr.layer().setMask_(new_mask)
      		
      	@property
      	def double_sided(self):
      		return self.pntr.layer().doubleSided()
      		
      	@double_sided.setter
      	def double_sided(self, val):
      		self.pntr.layer().setDoubleSided_(val)
      		
      	@property
      	def shadow_opacity(self):
      		return self.pntr.layer().shadowOpacity()
      		
      	@shadow_opacity.setter
      	def shadow_opacity(self, val):
      		self.pntr.layer().setShadowOpacity_(val)
      		
      	@property
      	def shadow_radius(self):
      		return self.pntr.layer().shadowRadius()
      		
      	@shadow_radius.setter
      	def shadow_radius(self, val):
      		self.pntr.layer().setShadowRadius_(val)
      		
      	@property
      	def shadow_offset(self):
      		return self.pntr.layer().shadowOffset()
      		
      	@shadow_offset.setter
      	def shadow_offset(self, offset):
      		## offset should be a tuple, but I'll take a CGSize
      		if isinstance(offset, CGSize):
      			self.pntr.layer().setShadowOffset_(offset)
      		elif isinstance(offset, tuple):
      			self.pntr.layer().setShadowOffset_(CGSize(*offset))
      		else:
      			raise TypeError("Cannot use type %s. Use CGSize or tuple" % type(offset))
      			
      	@property
      	def shadow_color(self):
      		return self.pntr.layer().shadowColor()
      		
      	@shadow_color.setter
      	def shadow_color(self, color):
      		if isinstance(color, UIColor.CGColor()):
      			self.pntr.layer().setShadowColor_(color)
      		elif isinstance(color, tuple) and len(color) == 4:
      			self.pntr.layer().setShadowColor_(Color(*color).CGColor())
      		else:
      			raise ValueError('Cannot use type %s. Use UIColor or tuple' % type(color))
      			
      		@property
      		def shadow_path(self):
      			return self.pntr.layer().shadowPath()
      			
      		@shadow_path.setter
      		def shadow_path(self, path):
      			self.pntr.layer().setShadowPath_(path)
      			
      		@property
      		def style(self):
      			return self.pntr.layer().style()
      			
      		@style.setter
      		def style(self, style):
      			self.pntr.layer().setStyle_(style)
      			
      if __name__ == '__main__':	
      	view = ui.View(frame=(0,0,500,500))
      	box  = ShadowView(frame=(0,0,100,100))
      	
      	view.background_color = 'white'
      	box.background_color = 'red'
      	box.center = view.center
      	
      	view.add_subview(box)
      	
      	box.masks_to_bounds = False
      	box.corner_radius = 6.
      	box.border_color = (0,1,0)
      	box.border_width = 6
      	box.shadow_radius = 10
      	box.shadow_offset = (0,0)
      	box.shadow_opacity = 1
      	
      	view.present('sheet')
      

      I tested most of it, but there may still be some funny-ness.

      B.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: [Share Code] UIAlertController

      Replying so people see this. I found a way to stop the crashing and (fun stuff) found out how to get the custom view controller that is created with each view. This allows you to use the view controller's methods to present oth view controllers!

      # coding: utf-8
      from objc_util import *
      import ctypes
      import ui
      
      SUIViewController = ObjCClass('SUIViewController')
      UIAlertController = ObjCClass('UIAlertController')
      UIAlertAction     = ObjCClass('UIAlertAction')
      
      def ok_pressed(sender):
      	print 'OK pressed'
      
      alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_(ns('My Alert'), ns('My Message'), 1)
      alert_action_block = ObjCBlock(ok_pressed, None, [c_void_p])
      default_action = UIAlertAction.actionWithTitle_style_handler_(ns('OK'), 0, None)
      alert.addAction_(default_action)
      ##rvc.presentModalViewController_animated_(alert, True)
      
      ## Stop Crashes
      retain_global(alert_action_block)
      
      def button_tapped(sender):
      	super_view = sender.superview
      	super_view_pntr = ObjCInstance(super_view)
      	vc = SUIViewController.viewControllerForView_(super_view_pntr)
      	vc.presentModalViewController_animated_(alert, True)
      	
      view = ui.View(frame=(0,0,500,500))
      view.name = 'Demo'
      view.background_color = 'white'
      button = ui.Button(title='Tap me!')
      button.center = (view.width * 0.5, view.height * 0.5)
      button.flex = 'LRTB'
      button.action = button_tapped
      view.add_subview(button)
      view.present('sheet')
      

      Hope you find this useful,
      B

      posted in Pythonista
      blmacbeth
      blmacbeth
    • [Share Code] UIAlertController

      I know Pythonista already has this with the console module, but I think it is a decent look at how to work with other UIViewControllers. This is very raw and needs to be cleaned up… maybe I'll make it into a class. Any way, here is the code

      
      # coding: utf-8
      from objc_util import *
      import ui
      
      UIAlertController = ObjCClass('UIAlertController')
      UIAlertAction     = ObjCClass('UIAlertAction')
      
      def ok_pressed(sender):
      	print 'OK pressed'
      
      app = UIApplication.sharedApplication()
      win = app.keyWindow()
      rvc = win.rootViewController()
      ## this was all setup for thealert view
      
      alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_(ns('My Alert'), ns('My Message'), 1)
      alert_action_block = ObjCBlock(ok_pressed, None, [c_void_p])
      default_action = UIAlertAction.actionWithTitle_style_handler_(ns('OK'), 0, alert_action_block)
      alert.addAction_(default_action)
      rvc.presentViewController_animated_completion_(alert, True, None)
      
      

      Let me know what you think,
      B

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: Custom keyboard support

      @omz I would very much like that keyboard app, if you ever get back around to it.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: MySQL Client

      @Tizzy it is good practice to not do statement = 'SELECT * FROM ' + table_name' or even statement = 'SELECT * FROM ' + %s' % table_name as this can cause security issues with SQL injection. Most database packages (read: modules) will have something along the lines of

      statement = '''
      SELECT *
      FROM ?
      '''
      with db.connect as conn:
          result = conn.execute(statement, (table_name,))
      

      This is a more secure way of accessing batabases. The other way is good enough for person projects, but keep that in mind or little Bobby Tables will make your life awful as a DBA.

      B.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: UI gaussian blur

      Noticed some bugs in the above code, so here are my fixes to make it work (in Pythonista3, at least).

      # coding: utf-8
      
      import ui
      from objc_util import *
      
      class BlurView (ui.View):
          def __init__(self, style=1, *args, **kwargs):
              ui.View.__init__(self, **kwargs)
              self._style = style
              self.effect_view = None
              self.setup_effect_view()
          
          @on_main_thread
          def setup_effect_view(self):
              if self.effect_view is not None:
                  self.effect_view.removeFromSuperview()
              UIVisualEffectView = ObjCClass('UIVisualEffectView')
              UIVibrancyEffect = ObjCClass('UIVibrancyEffect')
              UIBlurEffect = ObjCClass('UIBlurEffect')
              UILabel = ObjCClass('UILabel')
              # Brooks patch for Rect not having a 'slice' 
              bounds = self.bounds.as_tuple()
              frame = (bounds[:2], bounds[2:])
              self.effect_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
              effect = UIBlurEffect.effectWithStyle_(self._style)
              self.effect_view.effect = effect
              self.effect_view.setAutoresizingMask_(18)
              ObjCInstance(self).addSubview_(self.effect_view)
              vibrancy_effect = UIVibrancyEffect.effectForBlurEffect_(effect)
              self.vibrancy_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
              self.vibrancy_view.effect = vibrancy_effect
              self.effect_view.contentView().addSubview_(self.vibrancy_view)
              
          @property
          def style(self):
              return self._style
          
          @style.setter
          def style(self, value):
              if value != self._style:
                  self._style = value
                  self.setup_effect_view()
          
          # Brooks fix @on_mains_thread to @on_main_thread
          @on_main_thread
          def add_vibrant_label(self, label):
              self.vibrancy_view.contentView().addSubview_(ObjCInstance(label))
      
      def main():
          image_view = ui.ImageView(frame=(0, 0, 320, 320))
          image_view.image = ui.Image.named('test:Mandrill')
          blur_view = BlurView(style=2, frame=image_view.bounds.inset(40, 40))
          image_view.add_subview(blur_view)
          label = ui.Label(frame=blur_view.bounds)
          label.text = 'Hello World'
          label.font = ('HelveticaNeue', 40)
          label.alignment = ui.ALIGN_CENTER
          blur_view.add_vibrant_label(label)
          image_view.present('sheet')
      
      main()
      

      The biggest problem was that the ui.Rect() object does not have the ability to use slices. This was fixed with the ui.Rect().as_tuple() function. The second problem was just a typo.

      B

      posted in Pythonista
      blmacbeth
      blmacbeth
    • WebView bug

      In both the latest betas (Pythonista2 and Pythonista3) when running web_view.eval_js('alert(document.title)'), the alert is unable to be dismissed.

      Test code:

      import ui
      web_view = ui.WebView(frame=(0,0,500,500))
      web_view.present('sheet')
      web_view.load_url('https://www.google.com')
      web_view.eval_js('alert(document.title)')
      
      posted in Pythonista
      blmacbeth
      blmacbeth

    Latest posts made by blmacbeth

    • [Suggestion] Location Context Manager

      I was playing around with the location module the other day and was wondering about how it deals with scripts closing without manually turning off location tracking. So I made a context Manager for the location module

      import location
      
      
      class LocationManager (object):
          def __enter__(self):
              location.start_updates()
      
          def __exit__(self):
              location.stop_updates()
      

      You can use it like so:

      with LocationManager():
          # Do stuff that requires `location` here...
          ...
      

      Now, this may be completely unnecessary, but I have found it useful for applications where constant location updates are not needed (e.g. get my location every 15 minutes or set my initial location for some one off script).

      @omz also think this may be a good feature for the built-in location module to adopt (if possible). So we can have both location.start(stop)_updates() or with location: ....

      Let me know what y'all think (criticism is welcome).

      B.

      EDIT
      A bit less verbose code with the help of @ccc on contexlib

      import contexlib
      import location
      
      @contexlib.contexmanager
      def location_enabled():
          location.start_updates()
          yield
          location.stop_updates()
      

      the use case is still the same.

      with location_enabled():
          # Do location stuff here...
          ...
      
      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: Using the Dropbox Module

      @bistrot Add the #! python2 she-bang at the top of the script to tell it to use the (possibly) nom-default python 2.7 interpreter.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: Mysterious Crash

      @omz and @Cethric thanks for the help. It seems to work.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • Mysterious Crash

      I have a script where I'm trying to get the system attributes; eventually this will gather memory information. I have isolated the crash to this line of code:

      from ctypes import POINTER
      from objc_util import ObjCClass, ObjCInstance, c, c_void_p
      
      
      NSHomeDirectory = c.NSHomeDirectory
      NSHomeDirectory.restype = c_void_p
      NSHomeDirectory.argtype = []
      
      NSFileManager = ObjCClass('NSFileManager')
      
      LP_c_void_p = POINTER(c_void_p)
      
      def get_system_attributes():
      	file_manager = NSFileManager.defaultManager()
      	error = LP_c_void_p()
      	attributes = file_manager.attributesOfFileSystemForPath_error_(
      		ObjCInstance(
      			NSHomeDirectory()
      		).cString(),
      		error
      	)
      	return attributes
      
      get_system_attributes()
      

      attributesOfFileSystemForPath_error_ takes a string and an error pointer. It crashes when it gets to the error inside that function. I think it crashes due to an NSError object being created. Any ideas on how to stop the crash?

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: Accessing the LED flashlight

      @Phuket2 quoted from the Apple developer forums:

      Retina Flash
      iPhone 6s and 6s Plus contain a custom display chip that allows the retina display to briefly flash 3 times brighter than its usual maximum illuminance. No new API was added to support this feature. Since iOS 4, AVCaptureDevice has supported the -hasFlash, -isFlashModeSupported: and -flashMode properties. The iPhone 6s and 6s Plus front-facing cameras are the first front-facing iOS cameras to respond YES to the -hasFlash property. By setting the front-facing camera's flashMode to AVCaptureFlashModeOn or AVCaptureFlashModeAuto, the retina flash fires when a still image is captured (see AVCaptureStillImageOutput’s captureStillImageAsynchronouslyFromConnection:completionHandler:), just as the True Tone flash fires for rear-facing camera stills.

      Hope this. Only works on 6s, 6s+, and SE.
      B.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: MySQL Client

      @Tizzy sorry for not explaining myself better. @dgelessus is correct about the ? being the important part.

      I checked MySQL and it has its own syntax for variable arguments that just so happens to be %s. Shame on them…

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: MySQL Client

      @Tizzy it is good practice to not do statement = 'SELECT * FROM ' + table_name' or even statement = 'SELECT * FROM ' + %s' % table_name as this can cause security issues with SQL injection. Most database packages (read: modules) will have something along the lines of

      statement = '''
      SELECT *
      FROM ?
      '''
      with db.connect as conn:
          result = conn.execute(statement, (table_name,))
      

      This is a more secure way of accessing batabases. The other way is good enough for person projects, but keep that in mind or little Bobby Tables will make your life awful as a DBA.

      B.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: [Bug] objc_util and dir()

      @omz said:

      Btw, you can just pass a prefix to ObjCClass.get_names() instead of doing the filtering yourself (in the current beta, it would have to be a byte string though).

      Did not know that…

      posted in Pythonista
      blmacbeth
      blmacbeth
    • [Bug] objc_util and dir()

      Hey @omz, I got back in to playing around with objc_util and found this:

      >>> dir(OMJavaScriptSyntaxHighlighter)
      Traceback (most recent call last):
        File "<string>", line 1, in <module>
        File "/var/mobile/Containers/Bundle/Application/61407674-7331-47C2-B308-BDB7BBE52166/Pythonista3.app/Frameworks/PythonistaKit3.framework/pylib/site-packages/objc_util.py", line 380, in __dir__
          py_method_name = sel_name.replace(':', '_')
      TypeError: a bytes-like object is required, not 'str'
      

      This error come from the way Python3.* encodes ASCII vs Unicode strings. When you run the following:

      om_classes = [cls for cls in ObjCClass.get_names() if cls.startswith(b'OM')]
      for cls in om_classes:
          print(cls)
      

      You get the following (truncated for brevity):

      b'OMAutoresizingMaskView'
      b'OMBarButton'
      b'OMBarButtonItem'
      b'OMBaseSyntaxHighlighter'
      b'OMBasicPythonCompletionProvider'
      b'OMBasicPythonCompletionProviderTokenizedLine'
      b'OMButtonFieldSpecifier'
      b'OMCSSSyntaxHighlighter'
      b'OMCaretView'
      b'OMCheckCell'
      b'OMCheckFieldSpecifier'
      …
      b'OMUIWidgetViewScrollView'
      b'OMUIWidgetViewSegmentedControl'
      b'OMUIWidgetViewSlider'
      b'OMUIWidgetViewStickyNote'
      b'OMUIWidgetViewSwitch'
      b'OMUIWidgetViewTableView'
      b'OMUIWidgetViewTextField'
      b'OMUIWidgetViewTextView'
      b'OMUIWidgetViewWebView'
      

      Notice the b before the string. So, when you want to run string operations, which are now encoded as UTF-8, it throws a TypeError because ASCII is (for whatever reason) a byte-like object, not a string.

      To fix this you can have .get_names() return strings, or add the b prefix to the strings in replace() method in objc_util.

      posted in Pythonista
      blmacbeth
      blmacbeth
    • RE: UI gaussian blur

      Noticed some bugs in the above code, so here are my fixes to make it work (in Pythonista3, at least).

      # coding: utf-8
      
      import ui
      from objc_util import *
      
      class BlurView (ui.View):
          def __init__(self, style=1, *args, **kwargs):
              ui.View.__init__(self, **kwargs)
              self._style = style
              self.effect_view = None
              self.setup_effect_view()
          
          @on_main_thread
          def setup_effect_view(self):
              if self.effect_view is not None:
                  self.effect_view.removeFromSuperview()
              UIVisualEffectView = ObjCClass('UIVisualEffectView')
              UIVibrancyEffect = ObjCClass('UIVibrancyEffect')
              UIBlurEffect = ObjCClass('UIBlurEffect')
              UILabel = ObjCClass('UILabel')
              # Brooks patch for Rect not having a 'slice' 
              bounds = self.bounds.as_tuple()
              frame = (bounds[:2], bounds[2:])
              self.effect_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
              effect = UIBlurEffect.effectWithStyle_(self._style)
              self.effect_view.effect = effect
              self.effect_view.setAutoresizingMask_(18)
              ObjCInstance(self).addSubview_(self.effect_view)
              vibrancy_effect = UIVibrancyEffect.effectForBlurEffect_(effect)
              self.vibrancy_view = UIVisualEffectView.alloc().initWithFrame_(frame).autorelease()
              self.vibrancy_view.effect = vibrancy_effect
              self.effect_view.contentView().addSubview_(self.vibrancy_view)
              
          @property
          def style(self):
              return self._style
          
          @style.setter
          def style(self, value):
              if value != self._style:
                  self._style = value
                  self.setup_effect_view()
          
          # Brooks fix @on_mains_thread to @on_main_thread
          @on_main_thread
          def add_vibrant_label(self, label):
              self.vibrancy_view.contentView().addSubview_(ObjCInstance(label))
      
      def main():
          image_view = ui.ImageView(frame=(0, 0, 320, 320))
          image_view.image = ui.Image.named('test:Mandrill')
          blur_view = BlurView(style=2, frame=image_view.bounds.inset(40, 40))
          image_view.add_subview(blur_view)
          label = ui.Label(frame=blur_view.bounds)
          label.text = 'Hello World'
          label.font = ('HelveticaNeue', 40)
          label.alignment = ui.ALIGN_CENTER
          blur_view.add_vibrant_label(label)
          image_view.present('sheet')
      
      main()
      

      The biggest problem was that the ui.Rect() object does not have the ability to use slices. This was fixed with the ui.Rect().as_tuple() function. The second problem was just a typo.

      B

      posted in Pythonista
      blmacbeth
      blmacbeth