-
Notifications
You must be signed in to change notification settings - Fork 48
Implements Objective C delegate support #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The delegate support is achieved by a objc_delegate() function that converts a Python object to the corresponded Objective C delegate instance. A list of protocols intended to conform are also passed to the objc_delegate() function. The objc_delegate() dynamically creates a new Objective C class inherited by NSObject, then adds desired protocols methods and instantiates the instance. The instance is converted to Python object before returned so it can be passed to other MetaObjcClass methods that requires delegate instance. In order to achieve dynamic implementation of protocol methods. A `delegate_register` dict is added to remember the class name and corresponded Python object. So the dynamic function can dispatch the call to real Python object's method. However, currently registered delegates won't get released. Still looking for a way to free unused objects. This commit also adds an example at exampls/delegate.py. However, because the protocol method will be called asynchronously. I needs to write the example as a simple Kivy app so the execution won't quit before the protocol instance gets called. There may be a simpler way to implement a event loop but I failed. There is another problem about dynamically creating an Objective C class. That is, we need to use the objc_getProtocol() runtime function to find interested protocol methods (for signature and types). However, it seems not all protocols can be found through this function. More information about this issue can be found here: http://goo.gl/zA116F Signed-off-by: Olli Wang <olliwang@ollix.com>
|
Hi, We think that the syntax you're using might be too difficult to use, and can be better. Let's decide which one would be the best: https://gist.github.com/tito/8753609 I personnally prefer the solution 4, as it will not conflict with possible similar method, and it's kind-of explicit about the protocol used in the implementation. What do you think ? |
|
By the way, the solution 3 can be easilly implemented with: class ObjcDelegate(object):
def __new__(cls, *args):
instance = super(ObjcDelegate, cls).__new__(cls)
return objc_delegate(instance, cls.__protocols__)
|
|
The third solution looks pretty good. I've considered something like this but it makes code a bit complicated when figuring out how to implement delegate support from scratch. As the implementation has done. It's nice to adopt this syntax. :) |
|
Has the decision been made? Should I implement the solution or you will take care of it? |
|
I'm in favor of 4 too, explicit being better than implicit, i though more people would add their opinion, maybe give it a few days? :) Anyway, it's great already that you made it work, making the syntax better is obviously the second step :). If you are willing, you can implement the solution you see fit, if not, it's likely it'll be done soon anyway :) |
|
I see. I was just wondering if I have to implement the solution. If you will, that would be pretty awesome. :) |
|
Tell us if you do :) |
|
I think solution 3 is more conform to the Objective C style. Declares protocols once, and simply adds implementation for protocol methods. Usually methods for the same protocol are put together with a comment says the following methods are implementation for some protocol. I'm okay with solution 4. But it would be a bit tedious if you implement 10 methods for the same protocol. |
|
But the 3 have a drawback: conflict with similar method name. Plus, using Example in your context: class MyApp(object):
@protocol('NSURLConnectionDelegate')
def connection_didFailWithError_(self, connection, error):
print("Protocol method got called!!", connection, error)
def request_connection(self):
url = NSURL.URLWithString_(objc_str('abc'))
request = NSURLRequest.requestWithURL_(url)
connection = NSURLConnection.connectionWithRequest_delegate_(request, self)I really love this decorator :) |
|
That makes sense. I thought it's better than 3 now. :) |
|
Did you started the work to support it? If not, i'm gonna do it :) |
|
Nope, go ahead. ;) |
|
Done! The example has been updated, and i'm testing with Bluetooth Low Energy right now. Thanks a lot for your contribution! Doc is now required :) |
The delegate support is achieved by a objc_delegate() function that converts a Python object to the corresponded Objective C delegate instance. A list of protocols intended to conform are also passed to the objc_delegate() function.
The objc_delegate() dynamically creates a new Objective C class inherited by NSObject, then adds desired protocols methods and instantiates the instance. The instance is converted to Python object before returned so it can be passed to other MetaObjcClass methods that requires delegate instance.
In order to achieve dynamic implementation of protocol methods. A
delegate_registerdict is added to remember the class name and corresponded Python object. So the dynamic function can dispatch the call to real Python object's method. However, currently registered delegates won't get released. Still looking for a way to free unused objects.This commit also adds an example at exampls/delegate.py. However, because the protocol method will be called asynchronously. I needs to write the example as a simple Kivy app so the execution won't quit before the protocol instance gets called. There may be a simpler way to implement a event loop but I failed.
There is another problem about dynamically creating an Objective C class. That is, we need to use the objc_getProtocol() runtime function to find interested protocol methods (for signature and types). However, it seems not all protocols can be found through this function. More information about this issue can be found here: http://goo.gl/zA116F
Signed-off-by: Olli Wang olliwang@ollix.com