• 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.

    e.g.:

    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 true enough...double conversion isn't necessary, was just writing fast...here's a simplified version:

    def popoverPoint(topView, sourceView, pos): import objc_util x,y = pos srcobjc = sourceView.objc_instance topobjc = topView.objc_instance p = srcobjc.convertPoint_toView_(objc_util.CGPoint(x,y), topobjc.superview()) return (p.x,p.y)

    This is a popup to display a list of options to the user, so the popover has a TableView subview, and tapping an item in that view dismisses the popover. Working nicely now that it shows up where expected.

  • 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.

Internal error.

Oops! Looks like something went wrong!