• @cbanta, what is the exception? Install the fault handler to find out.

  • @dgelessus said:

    Ah, that's an auto-generated header from a class dump or something like that. I was looking at the "real" headers from the iOS SDK, which use vector types. (The iOS SDK headers aren't available online, the closest thing you can see is Apple's online documentation for GKAgent2D.position.) I'm guessing that during compilation some "magic" happens to properties/methods that use vector types, and the result is what you see in the class dump header. You could try using the methods position_ and setPosition__ (note the extra underscores), which according to the class dump header use structs instead of vector types.

    Thank you very much, using the methods with underscore solved the problem!

  • As far as I know, apps can only load libraries that are a part of iOS or that came with the app. This is based on the code signature, and not on the framework location. (For example, you can copy one of Pythonista's internal frameworks and load the copy without any issues using ctypes.) It's not possible to load frameworks that were signed for a different app. (For example you cannot copy a Pythonista framework to Editorial, even though both apps are from the same developer.) Frameworks that you compiled yourself using Xcode cannot be loaded either, even if you sign them with a development certificate. (The exception to that is @omz himself when using a dev build on Pythonista, because that is also signed with the dev cert. I remember there was a conversation about that on Twitter a while back, where omz could load a dev-cert-signed framework, but others couldn't.)

  • Thanks for those suggestions, learning about threading was very helpful.

    Apparently, the while loop was working the whole time! I feel very silly now. It didn't appear to be working because it always updated the decibel level to be -120 (which is unusual because -160 is typically silence). It is my hypothesis that Apple restricts widgets in certain ways like recording (which is odd because I've used taptic feedback in a widget before). (Ex: the Shazam app has a widget, but it has to open the app to work.) Anyway, my new problem will be figuring out if it's possible to collect and analyze the recording elsewhere and pass that information to the widget through some sort of callback url.

  • Thanks :)

  • Thank you! Yes it does work!
    On the 7 Plus I'm able to access all 4 cameras this way. This is what I get and it works perfect:

    "<AVCaptureFigVideoDevice: 0x12db72c40 [Back Camera][com.apple.avfoundation.avcapturedevice.built-in_video:0]>",
    "<AVCaptureFigVideoDevice: 0x12dbeb240 [Front Camera][com.apple.avfoundation.avcapturedevice.built-in_video:1]>",
    "<AVCaptureFigVideoDevice: 0x12dbe1b20 [Back Telephoto Camera][com.apple.avfoundation.avcapturedevice.built-in_video:2]>",
    "<AVCaptureFigVideoDevice: 0x12dbe6bf0 [Back iSight Duo Camera][com.apple.avfoundation.avcapturedevice.built-in_video:3]>"

  • https://github.com/jsbain/objc_hacks with a "c" on the objc

  • @cvp , thanks for replying. I also had a wick go with launcher. Also no luck. It's ok. Not a big deal. Just a nice to have 🙄😬

  • @lukaskollmer I would be very surprised if this API isn't shut down for third-party apps in one of the next iOS updates. While it is a private API, and you wouldn't get through app review calling it directly, there are obviously lots of ways you could get around those checks...

  • Thanks, i didn't think about ui. The @ProfSpaceCadet example was goot but was a bit overkill for now.Currently I am experimenting with the ui method. :-)

  • objc_util should usually be smart enough to figure this out automatically. If you attempt to call _doSomethingWithParam_, it will first try to translate that to :doSomethingWithParameter:, but if that method doesn't exist (which is very likely), it'll try all permutations of underscores and colons for replacing the underscores in the method name, and it should eventually arrive at _doSomethingWithParameter: (in this case, there are only 4 possible permutations).

    There could theoretically be cases where both _doSomethingWithParameter and :doSomethingWithParameter: are valid methods (unlikely, but possible) – in those cases, you could construct an ObjCInstanceMethod manually like this: ObjCInstanceMethod(some_obj, '_doSomethingWithParameter:'). This would also be slightly faster because there's no guessing involved to figure out the correct selector.

    Long story short, calling _addActionWithTitle_image_style_handler_ should "just work".

  • That's weird. I wrote and tested the script on my iPad. Did you run the exact script in the linked post? Should be the second script that doesn't crash.

    Here is the code, if you don't care to guess.


    # coding: utf-8 from objc_util import * import ctypes import ui SUIViewController = ObjCClass('SUIViewController') UIAlertController = ObjCClass('UIAlertController') UIAlertAction = ObjCClass('UIAlertAction') def ok_pressed(sender): print 'OK pressed', ObjCInstance(sender), dir(ObjCInstance(sender)) alert = UIAlertController.alertControllerWithTitle_message_preferredStyle_(ns('My Alert'), ns('My Message'), 0) alert_action_block = ObjCBlock(ok_pressed, None, [c_void_p]) default_action = UIAlertAction.actionWithTitle_style_handler_(ns('OK'), 0, alert_action_block) alert.addAction_(default_action) ##rvc.presentModalViewController_animated_(alert, True) ## Stop Crashes retain_global(alert_action_block) def button_tapped(sender): super_view = sender.superview super_view_pntr = ObjCInstance(super_view) vc = SUIViewController.viewControllerForView_(super_view_pntr) vc.presentModalViewController_animated_(alert, True) view = ui.View(frame=(0,0,500,500)) view.name = 'Demo' view.background_color = 'white' button = ui.Button(title='Tap me!') button.center = (view.width * 0.5, view.height * 0.5) button.flex = 'LRTB' button.action = button_tapped view.add_subview(button) view.present('sheet')
  • Jon - thanks, you set me on the right track -- the app I want to paste into (MarginNote) accepts rich text only if it's formatted as an Apple Web Archive type. Here's how I ultimately got it to work for Python 2.7, thanks to this guide on coercing HTML into an archive type:

    from objc_util import * import os import base64 theDefinition = '<html><head></head><body>''<font size="5">' + '<b>Hello</b> <i>world!2</i>' + '</font></body></html>' theData = base64.encodestring(theDefinition) theData = str(theData) theArchive = """<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>WebMainResource</key> <dict> <key>WebResourceData</key> <data> """ + theData + """ </data> <key>WebResourceFrameName</key> <string></string> <key>WebResourceMIMEType</key> <string>text/html</string> <key>WebResourceTextEncodingName</key> <string>UTF-8</string> <key>WebResourceURL</key> <string>about:blank</string> </dict> </dict> </plist>""" thePasteBoard = ObjCClass('UIPasteboard') thePasteBoard = thePasteBoard.generalPasteboard() theType = "Apple Web Archive pasteboard type" thePasteBoard.setValue_forPasteboardType_(theArchive,theType)
  • I have updated the GitHub repo to represent the current work. I have more or less temporariely resolved the issue by calling reload(GLKit.view) in main.py how ever this is really only a temporary fix. I will look into some of the methods that omz uses to retain the globals/delegate methods.

  • if you change the retainme line so that it is stored in a built in package, it will ensure it does not get gc'd when rerunning. As is, when you click play again, it results in a crash, because the objc object still exists, but the callback doesn't.

    ui._retain_me = tabBar_didSelectItem_
  • This could be a great potential use case for In App Purchases in the future ;)

  • Wow. That's really neat. Good job!

  • Thanks @omz The pattern seems reasonable to follow.

Internal error.

Oops! Looks like something went wrong!