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.


    Crashing pythonista on pushing view

    Pythonista
    3
    7
    4403
    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

      Now I just want to say I don't think this is a bug in pythonista.

      I have a much larger "app" I'm working on in pythonista but for the problem I'm having I created a basic example so it isn't very nice code.

      With that out of the way here is my example.

      import ui
      import time
      class source (object):
      	def __init__(self):
      		self.selectcb = None
      	def tableview_number_of_rows(self, tv, s):
      		return 1
      	def tableview_cell_for_row(self, tv, s, r):
      		cell = ui.TableViewCell()
      		cell.text_label.text = 'DoubleTap'
      		return cell
      	def tableview_did_select(self, tv, s, r):
      		self.selectcb()
      		time.sleep(1)
      		
      view = ui.TableView()
      
      s = source()
      
      nav = ui.NavigationView(view)
      w,h = ui.get_screen_size()
      v2 = ui.View(frame=(0,0,w,h))
      @ui.in_background
      def cb():
      	time.sleep(1)
      	nav.push_view(v2)
      	time.sleep(1)
      s.selectcb = cb
      view.data_source = s
      view.delegate = s
      nav.present()
      

      My problem is when I double tab the row it calls the call back to add the view to the navigation controller. Not sure this the best way to do it. I have put the sleeps in as in the other script I'm working on I do some processing before I push the view on, so I am simulating that with sleeps.

      So if I double tap on the row and wait like 5 seconds after the view is pushed it crashes pythonista.

      Anyway I know what the error is as I have the fault handler and exception catching script on so it produces this.

      Fatal Python error: Aborted

      Thread 0x000000016e247000 (most recent call first):


      Objective-C exception details:

      UIViewControllerHierarchyInconsistency: A view can only be associated with at most one view controller at a time! View <SUITableView_PY3: 0x1371a3000; baseClass = UITableView; frame = (0 64; 414 672); clipsToBounds = YES; gestureRecognizers = <NSArray: 0x138aac4e0>; layer = <CALayer: 0x13b35a520>; contentOffset: {0, 0}; contentSize: {414, 336}> is associated with <SUINavigationViewContentViewController_PY3: 0x13b4c31f0>. Clear this association before associating this view with <SUINavigationViewContentViewController_PY3: 0x1393bedf0>.

      I have left the stack trace out. Now so I can see the issue but I don't know how to get around this from occurring. It appears to only happen when I have decorated the function to push the view on the navigation view in a ui.in_background

      Any thoughts are appreciated.

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

        I should mention, my intention isn't for the row to be double tapped but as there could be a pause before the view gets pushed, the user might tap the row again.

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

          time.sleep isn't really compatible with ui. Instead, use ui.delay??

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

            @ccc The reason I had the sleeps in was to pause the code. In the other code where I had the problem it doesn't use them, so haven't really tried to change that example.

            What I did do though in my other code I needed console.alert in those methods which required me to have ui.inbackground otherwise it locked up (from memory anyway it was a while since I wrote that bit). Anyway my work around that seems to be working is to write another function that just shows the alert and decorate that with ui.in_background and remove it from the function that does the pushing of the view and call the alert function.

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

              You might try protecting the push with a

              if v2.navigation_view:
                 ...
              

              What is happening is you are selecting the row twice by double tapping (select is a single tap action). This calls your cb() twice in quick succession.

              You might also use on_main_thread for the call to push_view, and wrap the call in a try/except.

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

                By the way, it is very confusing if the user presses a button, then some long time later the view changes. If you have lots of heavy computation to populate the view, instead of waiting until it is ready, try to push an empty view first, fill it with a ui.ActivityIndicator, THEN call a long background computation to fill it in with content. This prevents the user from mashing rows in the tableview trying to get something to happen.

                Or, if you are not sure whether you will push the view until doing the long computation, "disarm" the table as soon as the user selects a row, and "rearm" it when computation is done. This would be done in the tableview_did_select, assuming your source has a new armed attribute.

                def tableview_did_select(self, tv, s, r):
                    if self.armed:
                    	self.armed=False
                    	self.selectcb()
                    	time.sleep(1)
                

                then, in cb(), you would rearm the view.data_source after the long computation.

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

                  Thanks @JonB I will add the activity indicator on click and the nav check on the view, just to make sure it doesn't occur again.

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