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.


    Presenting ViewController

    Pythonista
    objcutil objc
    6
    47
    29631
    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.
    • JonB
      JonB last edited by

      I think your best option is to grab the view controller of a presented ui.View, and add your new controllers view as a subview, and there are a fw other methods to make sure the childcontroller is set up right. Here is a method to grab the currently presented view controller:

      # coding: utf-8
      from objc_util import *
      def get_view_controller(uiview):
         if isinstance(uiview,ui.View):
            viewobj=ObjCInstance(uiview)
         elif isa(uiview,'ObjCInstance') and uiview.isKindOfClass_(ObjCClass('UIView')):
            viewobj=uiview
         viewResponder=viewobj.nextResponder()
         try:
            while not viewResponder.isKindOfClass_(ObjCClass('UIViewController')):
               viewResponder=viewResponder.nextResponder()
            except AttributeError:
               return None #if view is not being presented for example
         return viewResponder
      

      note this only works if the ui.View is being presented at the time.
      complete example might look like

      root_view_controller= get_view_controller(root)
      someothercontroller.view().setFrame_(ObjCInstance(root).bounds())
      ObjCInstance(root).addSubview_(someothercontroller.view())
      root_view_controller.addChildViewVontroller(someothercontroller)
      someothercontroller.didMoveToParentViewController_(root_view_controller)
      

      you may also need to do some cleanup when the view is closed, but not sure...

      1 Reply Last reply Reply Quote 1
      • filippocld
        filippocld last edited by

        Ok, i was trying to do this without any help but i'm stuck.
        I basically have this code

        from objc_util import *
        from time import sleep
        #import objutil
        
        ObjCClass('NSBundle').bundleWithPath_('/System/Library/Frameworks/ReplayKit.framework').load()
        
        recorder=ObjCClass('RPScreenRecorder')
        preview=ObjCClass('RPPreviewViewController')
        sharedrecorder=recorder.sharedRecorder()
        sharedrecorder.startRecordingWithMicrophoneEnabled_handler_(False,None)#(false,none)
        
        print 'Recording:' + str(sharedrecorder.isRecording())
        print 'Microphone Enabled:' + str(sharedrecorder.isMicrophoneEnabled())
        sleep(3)
        #Some cool things...
        
        #Stopping the recording and saving
        print 'Stopping...'
        sharedrecorder.stopRecordingWithHandler_(preview)
        app = ObjCClass('UIApplication').sharedApplication()
        rootvc=app.keyWindow().rootViewController()
        rootvc.presentViewController_animated_completion_(preview, True, None)
        

        That "implements" a iOS 9 API (ReplayKit) and records the screen for a certain time (3 secs in this case) and then it has to present the preview view controller. But the app crashes.

        Can someone help me (again)?
        Thanks in advance
        Filippo

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

          The problem is, you pass a view controller class to stopRecordingWithHandler_, but it expects a block... With the current beta, it's pretty difficult to make this work at all (blocks aren't really supported), but I can show you an example when the new build is up on TestFlight (probably later today). As it happens, I've been experimenting with exactly this API as well...

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

            Thanks, waiting for it :-)

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

              Okay, here's a minimal example that shows how you can use RPScreenRecorder – as I said, it'll only work with the latest build (#160023), so please install that first.

              Note to others who might be reading this: You also need to have the iOS 9 beta installed for this to work.

              from objc_util import *
              import time
              
              NSBundle = ObjCClass('NSBundle')
              replaykit = NSBundle.bundleWithPath_('/System/Library/Frameworks/ReplayKit.framework')
              replaykit.load()
              
              RPScreenRecorder = ObjCClass('RPScreenRecorder')
              
              def stop_callback(_cmd, _vc):
              	vc = ObjCInstance(_vc)
              	rootvc = UIApplication.sharedApplication().keyWindow().rootViewController()
              	vc.popoverPresentationController().setSourceView_(rootvc.view())
              	rootvc.presentViewController_animated_completion_(vc, True, None)
              
              stop_handler = ObjCBlock(stop_callback, restype=None, argtypes=[c_void_p, c_void_p])
              
              recorder = RPScreenRecorder.sharedRecorder()
              
              @on_main_thread
              def start_recording():
              	recorder.startRecordingWithMicrophoneEnabled_handler_(False, None)
              
              @on_main_thread
              def stop_recording():
              	recorder.stopRecordingWithHandler_(stop_handler)
              
              start_recording()
              time.sleep(5)
              stop_recording()
              
              1 Reply Last reply Reply Quote 0
              • filippocld
                filippocld last edited by

                Thanks.
                What is @on_main_thread for?

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

                  What is @on_main_thread for?

                  I think it's not strictly necessary here, but most things that have to do with UI need to be called from the main thread.

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

                    It crashes :-( i copied exactly what you wrote and crashes 😱

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

                      Hmm. What kind of device do you have? Could be that it doesn't work on 32 bit...

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

                        Ipad air 2, it is 64 bit. I noticed removing on main thread crashes the app after the recording and before the presentation, leaving it crashes when start_recording() is called

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

                          Okay, no idea what might be causing the crash then, sorry. :/

                          It doesn't crash here at all, but I've noticed that the resulting videos contain strange artifacts (looks like tearing), not sure if that's related somehow.

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

                            Ok, will try to solve it by me :-/
                            If you find something that could cause crashes tell me

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

                              I'm near to the solution.
                              I removed @on_main_thread (that crashes many scripts i already worked on and worked with previous beta) and i tried to experiment with ObjCBlocks, always with a crash. So downloaded the example in the docs about the blocks. Guess what? It Crashes! The crash definitely has to do with blocks

                              Hope this helps solving the bug,
                              Filippo

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

                                I'll do some more testing. It might have to do with different build settings in the TestFlight version vs. my local development build – after all, the code I posted definitely works here, and I don't think hardware differences are responsible for this (iPad Air 1 vs. 2 aren't that different).

                                I think this particular use case is possible to do without blocks (using a delegate instead), but it would still be nice if I could get those to work reliably.

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

                                  Thanks :-)
                                  Did some (more and more) testing with the example file and found that maybe the line 14 (where the handler is called) is responsible for the crash

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

                                    I can run the example block code (sorting function) from the documentation. My device is also a iPad Air 2.

                                    The RPScreenRecorder did NOT run but it was due to a different error. The replaykit was not created successfully. The bundleWithPath_ method returned a None for me.

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

                                      Your error is there because you have iOS 8. ReplayKit is a framework of iOS 9.

                                      Dunno about the example, maybe is some iOS 9 bug

                                      @omz I was wrong, the line that crashes the app is line 14, where you call the handler. Anyway @on_main_thread crashes too for me. Remember i am on iPad Air 2 WiFi iOS 9 beta 5

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

                                        Ok, @omz in the meantime can you show me how to do with delegates, please? :-)
                                        Would be much appreciated

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

                                          @filippocld said:

                                          Ok, @omz in the meantime can you show me how to do with delegates, please? :-)
                                          Would be much appreciated

                                          Turns out that I was wrong about that. It's not possible to do this without blocks.

                                          I don't really have any idea why this doesn't work for you, to be honest. I installed the latest beta directly from TestFlight (the exact same build you have) on an iPad Air 1 that has iOS 9 beta 5 installed, and it works just fine. I just can't think of a reason why it wouldn't work on an iPad Air 2 right now.

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

                                            Do you have a way to see my crash logs and maybe understand the problem?
                                            I mean, it happens everytime i call an handler in every function, it shouldn't be so difficult.

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