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
-
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 likeroot_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...
-
Ok, i was trying to do this without any help but i'm stuck.
I basically have this codefrom 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 -
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... -
Thanks, waiting for it :-)
-
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()
-
Thanks.
What is @on_main_thread for? -
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.
-
It crashes :-( i copied exactly what you wrote and crashes 😱
-
Hmm. What kind of device do you have? Could be that it doesn't work on 32 bit...
-
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
-
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.
-
Ok, will try to solve it by me :-/
If you find something that could cause crashes tell me -
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 blocksHope this helps solving the bug,
Filippo -
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.
-
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 -
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. Thereplaykit
was not created successfully. ThebundleWithPath_
method returned aNone
for me. -
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
-
Ok, @omz in the meantime can you show me how to do with delegates, please? :-)
Would be much appreciated -
@filippocld said:
Ok, @omz in the meantime can you show me how to do with delegates, please? :-)
Would be much appreciatedTurns 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.
-
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.