Hey all you pythonistas, it's been a while.
Super super excited about the new version of Pythonista!
I'm converting the big project we have which was written in python2/pythonista3.3 to be python3/pythonista3.4, and I ran into one major issue: I'm getting crashes if I try to use ObjCBlocks in pythonista3.4 which worked fine in pythonista3.3.
Here's the main example, pulled from a much more complex chunk of code, of a custom sheet presentation controller, which is supposed to be able to call a completion function via a block:
import objc_util
import ui
UIViewController = objc_util.ObjCClass("UIViewController")
UIView = objc_util.ObjCClass("UIView")
UIModalPresentationFormSheet = 2
UIModalTransitionStyleCoverVertical = 0
def getRootUIViewController():
app = objc_util.UIApplication.sharedApplication()
window = app.delegate().window()
if not window: return None
return window.rootViewController()
def getUIViewController(view):
#### If the view is a standard pythonista ui.View, we can
#### try to directly retrieve the view controller
SUIView = objc_util.ObjCClass('SUIView')
SUIViewController = objc_util.ObjCClass('SUIViewController')
UIView = objc_util.ObjCClass('UIView')
UIViewController = objc_util.ObjCClass('UIViewController')
if isinstance(view, ui.View):
viewobj = view.objc_instance
vc = SUIViewController.viewControllerForView_(viewobj)
if vc is not None: return vc
elif isinstance(view, objc_util.ObjCInstance) and \
view.isKindOfClass_(SUIView):
viewobj = view
vc = SUIViewController.viewControllerForView_(viewobj)
if vc is not None: return vc
#### Otherwise we have to search the "responder chain"
#### for the first instance of a UIViewController
elif isinstance(view, objc_util.ObjCInstance) and \
(view.isKindOfClass_(UIView) or
view.isKindOfClass_(UIViewController)):
viewobj = view
viewResponder = viewobj.nextResponder()
try:
while not viewResponder.isKindOfClass_(UIViewController):
viewResponder = viewResponder.nextResponder()
except AttributeError:
return None
return viewResponder
def presentAsSheet(view, sourceView=None, whenPresented=None):
#### create a new modal view controller and set its presentation
#### style to the sheet style, and size it to the content
currentvc = getUIViewController(view)
if currentvc is not None:
currentvc.view = None
sheetController = UIViewController.new().autorelease()
sheetController.view = view.objc_instance
sheetController.modalPresentationStyle = UIModalPresentationFormSheet
sheetController.modalTransitionStyle = \
UIModalTransitionStyleCoverVertical
sheetController.preferredContentSize = \
objc_util.CGSize(view.width, view.height)
#### retrieve the presentation controller for the new modal
#### view controller, bail if that fails for some reason
presentationController = \
sheetController.presentationController()
if presentationController is None:
print("Unable to get presentation controller to present.")
return
#### find the view controller which is presenting the source view,
#### that view controller will present the sheet overlay
if sourceView is not None:
sourcevc = getUIViewController(sourceView)
else:
sourcevc = getRootUIViewController()
if sourcevc is None:
print("Unable to find view controller for source view.")
return
#### create a block to call the presentation completion
_block = None
if whenPresented:
_block = objc_util.ObjCBlock(
whenPresented,
restype=None,
argtypes=[]
)
#### present the view controller containing the content view
#### via the sheet presentation controller
sourcevc.presentViewController_animated_completion_(
sheetController, True, _block)
main = None
def whenPresented():
print("PRESENTATION COMPLETE")
def presentSheet(sender):
print("PRESENT SHEET:", sender)
sheet = ui.View()
sheet.frame = (0,0,300,200)
sheet.background_color = (1.0,1.0,1.0,1.0)
l = ui.Label()
l.text = "Sheet Presented View"
l.text_color = (0,0,0,1.0)
l.alignment = ui.ALIGN_CENTER
l.frame = (0,0,300,200)
sheet.add_subview(l)
#### presenting with a completion function crashes!
presentAsSheet(sheet, main, whenPresented=whenPresented)
#### presenting without completion function works fine...
#presentAsSheet(sheet, main, whenPresented=None)
main = ui.View()
main.background_color = (1.0,1.0,1.0,1.0)
main.frame = (0,0,500,500)
b = ui.Button()
b.frame = (10,10,200,40)
b.title = "Present Sheet"
b.action = presentSheet
main.add_subview(b)
main.present("fullscreen")
I can't get the block to run without a segmentation fault.
presentViewController_animated_completion_(...)
is defined here:
https://developer.apple.com/documentation/uikit/uiviewcontroller/1621380-presentviewcontroller
And it says it has no return and takes no parameters...so I'm not sure where I've gone wrong. Has anyone been successfully using blocks in python3/pythonista3.4?