• There was an additional crashing issue: another version of the same problem when an object has gone out of scope in the python context when it is accessed in the objc context.

    I need to re-inforce the understanding that just because a python object like a ui.View is technically placed in a view hierarchy, or otherwise connected to the objc world, the underlying objc instance of a UIView is not in any way holding a strong reference to that python object, and I think vice-versa.

    So creating a local ui.View instance inside a method, and then adding that view to a purely objc view hierarchy, will not preserve the python object after it goes out of scope. So a later attempt to access the python object will segfault.


    import ui import objc_util class X(object): def buttonAction(self, sender): print sender def demoCrash(self, sender): b2 = ui.Button() b2.frame = (0,0,200,50) b2.title = "Crash?" b2.action = self.buttonAction v2 = ui.View() v2.frame = (0,0,200,50) v2.background_color = (1.0,1.0,1.0,1.0) v2.objc_instance.addSubview(b2) v2.present(style="sheet") v = ui.View() v.frame = (0,0,400,400) v.background_color = (1.0,1.0,1.0,1.0) x = X() b = ui.Button() b.title = "Show" b.frame = (0,0,100,30) b.center = (v.width*0.5,v.height*0.5) b.action = x.demoCrash v.add_subview(b) v.present(style="sheet")

    should have been obvious, but my code was more complex and hid what was happening.

  • @cvp yes, that line isn't needed, I just copy-pasta'd this from a chunk of larger code...looks like I forgot to define "pos" too, which is a little complicated: it isn't simply a point in the parent coordinate system. It's a point in reference to the top-left corner of the top view in the view hierarchy which is presenting it.

    I asked about getting that location a while ago, and got some good replies, so the little utility function to get that point is:

    def popoverPoint(pos, sourceView): import objc_util srcobjc = sourceView.objc_instance topobjc = None parent = srcobjc.superview() while parent is not None: topobjc = parent parent = parent.superview() p = srcobjc.convertPoint_toView_(objc_util.CGPoint(*pos), topobjc) return (p.x,p.y)
  • @JonB looks like you're right...I was doing something incorrectly, though now I'm not sure what.

    If I simply take the widget.bounds() and ui.convert_rect() to the ScrollView, I get a valid rectangle in the ScrollView coordinate space. So all good.

  • @shinyformica try this, it is the way omz wrote dialog: using wait_modal and resetting the view just after.

    import ui from objc_util import * class Popover(ui.View): def __init__(self, *args, **kws): ui.View.__init__(self, *args, **kws) self.width = 200 self.height = 50 self.label = ui.Label() self.label.text = "test" self.add_subview(self.label) self.label.x = 0 self.label.y = 0 self.label.width = self.width self.label.height = self.height def will_close(self): print("popover closing") class MyView(ui.View): def __init__(self, *args, **kws): ui.View.__init__(self, *args, **kws) self.popover = None self.button = ui.ButtonItem() self.button.title = "Show Popover" self.button.action = self.showPopover self.right_button_items = (self.button,) def showPopover(self, sender): print("show popover") if self.popover is None: self.popover = Popover() self.popover.present(style="popover", popover_location=(self.width-100,50), hide_title_bar=True) self.popover.wait_modal() self.popover = None def run(): v = MyView() v.present('full_screen') if __name__ == '__main__': run()```
  • @shinyformica, if I understand your requirement right, it is as simple as:

    button.frame = v.bounds button.flex = 'WH'
  • Those are custom attributes not custom arguments. what happens is the view is created, with no input args:


    then, arguments are set:

    v.width =.... v.bc="oooo"

    and so on.
    if you need to take action based on the custom attributes, you need to have those as @property's, to implement a setter.

  • @Webmaster4o , lol does not surprise me. But let's face it a lot of little treasures in Pythonista.
    I wish they could all be documented, but I understand why they are not. It would take a big chunk out of the development time. I can't remember how long I have had Pythonista now, but I am astounded how much it has evolved in that short time.

  • I think that at each touch_began run, you create a new instance of ui.View, without deleting the previous one! Not vital but not the deal, I suppose.

  • See my other reply: make sure your loaded pyui return PanelMorphic as the CustomClass. init gets called on the class of whatever new returns.

Internal error.

Oops! Looks like something went wrong!