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.
HomeKit
-
This is the first time I am trying objc_util so not sure if I am doing something wrong. I am trying to access my HomeKit setup and am starting with the following
from objc_util import *
load_framework('HomeKit')
HMHomeManager = ObjCClass('HMHomeManager')
homemanager = HMHomeManager.alloc().init()This is based on the objective c call:
self.homeManager = [[HMHomeManager alloc] init];My code crashes Pythonista but removing init() does not. I am sure someone will say "then just remove it" but it appears in looking at other objc_util examples that it is expected to be called. Running without init does let me get the primary home but no rooms - the big "but" is I have not coded the delegate methods which appears to be useful.
Anyhow at this point was wondering if anyone has done anything with HomeKit that they could share. Also wondering about the init() issue.
Thanks
-
Not working with HomeKit yet, but always a good idea to enable @dgelessus’ faulthandler - you see what the ObjC exception was that caused the crash, and might get some idea how to fix it.
Also, did you share a full ”working” example? Are you sure it crashes on the init line?
-
Thanks for the reply, will take a look at the fault handler.
My code is pretty much all I have at this point (I had a few lines after to get room info but commented that out to track down the crash). In the code I posted it will crash with init and not when it is removed - not the entire line just removing .init()
-
So I tried to add the delegate and added the fault handler. With the init removed it crashes when assigning the delegate.
Here is my code:
from __future__ import absolute_import, division, print_function from objc_util import * from pythonista_startup.enable_faulthandler import run load_framework('HomeKit') def homeManagerDidUpdateHomes(self, cmd): print('homeManagerDidUpdateHomes') methods = [homeManagerDidUpdateHomes] protocols = ['HMHomeManagerDelegate'] MyHMHomeManagerDelegate = create_objc_class('MyHMHomeManagerDelegate',NSObject,methods=methods,protocols=protocols) def main(): print('Start of script') # run enable faulthandler run() myHMHomeManagerDelegate = MyHMHomeManagerDelegate.alloc() HMHomeManager = ObjCClass('HMHomeManager') homemanager = HMHomeManager.alloc() homemanager.setDelegate(myHMHomeManagerDelegate) print('End of script') if __name__ == '__main__': main()
NOTE: The objc delegate method is:
- (void)homeManagerDidUpdateHomes:(HMHomeManager *)manager;
When I tried to define the python delegate method as def homeManagerDidUpdateHomes(self, cmd,manager): I got an error that the method was only expecting 2 parameters but found 3.
Back to the code... as mentioned I first ran with the line to set the delegate which crashed so I then commented out the set delegate line to let it complete successfully. The fault handler outputted the following:
Start of script
Enabling fault handler and Objective-C exception handler...
Pythonista quit abnormally last time.
For details, see the following log file: faultlog-2018-02-19-14-36-24.txt
Setting fault handler.
Done enabling fault handler and Objective-C exception handler.
End of scriptThe contents of the fault log
Fatal Python error: Segmentation fault
Current thread 0x000000016f72b000 (most recent call first):
File "/var/containers/Bundle/Application/31989ED7-8359-46ED-90D1-AA84E7A73FA8/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 897 in call
File "/var/containers/Bundle/Application/31989ED7-8359-46ED-90D1-AA84E7A73FA8/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 803 in call
File "/private/var/mobile/Containers/Shared/AppGroup/0ED4DCFF-B233-4C51-A9EF-89FAA67A9C87/Pythonista3/Documents/Test01/HomeKit03.py", line 21 in main
File "/private/var/mobile/Containers/Shared/AppGroup/0ED4DCFF-B233-4C51-A9EF-89FAA67A9C87/Pythonista3/Documents/Test01/HomeKit03.py", line 25 in <module>Here is the fault log when using alloc().init()
Fatal Python error: Aborted
Thread 0x000000016b577000 (most recent call first):
I also tried .delegate = instead of setDelegate which crashed with the following log
Fatal Python error: Segmentation fault
Current thread 0x000000016f8a3000 (most recent call first):
File "/var/containers/Bundle/Application/31989ED7-8359-46ED-90D1-AA84E7A73FA8/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 897 in call
File "/var/containers/Bundle/Application/31989ED7-8359-46ED-90D1-AA84E7A73FA8/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/objc_util.py", line 650 in setattr
File "/private/var/mobile/Containers/Shared/AppGroup/0ED4DCFF-B233-4C51-A9EF-89FAA67A9C87/Pythonista3/Documents/Test01/HomeKit03.py", line 22 in main
File "/private/var/mobile/Containers/Shared/AppGroup/0ED4DCFF-B233-4C51-A9EF-89FAA67A9C87/Pythonista3/Documents/Test01/HomeKit03.py", line 26 in <module>Thanks for the help.
-
I suspect your issue is that the delegate and maybe the manager gets destroyed at the end of main(). retain, or return them and retain them in the callers scope.
from __future__ import absolute_import, division, print_function from objc_util import * from pythonista_startup.enable_faulthandler import run load_framework('HomeKit') def homeManagerDidUpdateHomes_(self,sel,manager): print(ObjCInstance(self)) print('homeManagerDidUpdateHomes') methods = [homeManagerDidUpdateHomes_] protocols = ['HMHomeManagerDelegate'] MyHMHomeManagerDelegate = create_objc_class('MyHMHomeManagerDelegate',NSObject,methods=methods,protocols=protocols) def main(): print('Start of script') # run enable faulthandler run() #every alloc must have an init, or initWith... #, or can use .new() instead of .alloc().init() myHMHomeManagerDelegate = MyHMHomeManagerDelegate.alloc().init() HMHomeManager = ObjCClass('HMHomeManager') homemanager = HMHomeManager.alloc().init() homemanager.setDelegate(myHMHomeManagerDelegate) # homemanager and delegate must be retained, or returned, # otherwise python object gets destroyed return homemanager,myHMHomeManagerDelegate #alternatively #retain_global(myHMHomeManagerDelegate) #retain_global(homemanager) print('End of script') if __name__ == '__main__': homemanager,myHMHomeManagerDelegate = main()
i dont have anything to test with, but this doesnt crash, and you can call the delegate manually...
edit: also, i think the proper delegate method is
homeManagerDidUpdateHomes_manager_
which takes homes, and manager args.
edit: nope.. the original was right
edit again...homeManagerDidUpdateHomes_
you were missing the underscore. You have to replace colons with underscore for methods that take arguments. This did get called automatically -
Thanks for looking into this and the reply. I pasted your code into a new script file and unfortunately it is crashing pythonista at the alloc init again. If I take off the init it crashes when setting the delegate as before. I am using a different iOS device than yesterday but I appear to be having the same issue. I am running iOS 11.2.5 on the device I am trying it on now if that matters.
-
Which init is crashing? The delegate or the manager?
You can't skip init, you don't really have an objc object until you run init. Alternatively, try new() instead of alloc ().init().Did you get a pop-up allowing homekit access? Check settings app. I think homekit requires an entitlement but don't know whether that was always enforced, or if pythonista has that entitlement. I'm on a os9.4 device.
-
The delegate is created first and the init on it causes a crash. If I comment that line or remove the init then the HMHomeManager causes the crash with the init. Also tried new() with the same result.
I did not get a popup asking for HomeKit access. I just checked in Xcode and HomeKit is a capability that needs turned on for the app (pythonista in this case as you mention). Ultimately it has to be set on the app id (Xcode will do this or can be done in the developer portal for the app id).
Will send a support email asking about this.
Thanks
-
I'm not sure which version of iOS started enforcing the entitlement. Again, it works for me. Creating the delegate should not require the entitlement, since it does jnot do anything. Try creating just the delegate, and using alloc().init(). Then try again without specifying the protocol. If that still crashes, try without the method.
Can you also try one of the objc examples that use a custom delegate class? Just to ensure objc_util is really working...
-
Oh, also use the debug=True flag in your create_objc_class. Your code could fail because the class name might not be unique. Not sure.
-
Also, I'm on the beta, which might have different entitlements... @omz?
-
I tried a different sample app that uses alloc init and delegates and it works. Heard back from Ole and Pythonista is not a HomeKit app and it does appear it will become one. I am guessing that is why it is crashing. Thanks for the help.
My use case is to provide a different UI and organization for HomeKit triggers based on how I am using it. I know how to develop apps in Swift and could go that route but I believe the free developer account apps are only signed for 7 days. This will not be a frequently used app and I could go that route (having to deploy it from Xcode each time I need to run it after 7 days from last run). Pythonista would have filled the need perfectly if it was HomeKit capable.
-
i would have expected entitlement problems to show up in faulthandler as such. also, i cannot believe you need an entitlement to create a custom delegate class.
Id like to suggest a custom settrace() so we can find exactly where the crash occurs (it probably is in the objc_util call somewhere, but it would be interesting to see exactly which line. I think you said your were getting segfault, which sounds like a different problem.
-
@JonB, do you think there is still a solution to be found, even if Pythonista app is not HomeKit-enabled?
-
It is not obvious that the entitlement is the problem -- also, I am not sure it is enforced on app, versus just in Xcode, since the example works for me. Maybe it is enforced in later ios versions, or not enforced on the testflight version... do you get the same crash mikael?
-
@JonB, I am on 11.2.6 and get a crash with ”Fatal Python error: Aborted” at HomeManager init, delegate init is fine.