ios-jsc
ios-jsc copied to clipboard
Objective-C Inheritance using ES6 Class syntax
Once we have adopted the latest JSC version, we can implement the Objective-C inheritance using the class syntax.
Will this fix the problem of passing an object with inherited properties to extend? I'm currently getting «No implementation found for exposed method...» for functions that are inherited from another object. E.g. with UIViewController.extend(Object.create(SharedFunctions)).
@moll: if you use some sort of mixin mechanism that copies the shared functions to each JavaScript class before registering it in the Objective-C runtime, then yes.
Umm, what do you mean by mixin mechanism? I've just got Object.create in mind to take advantage of prototypes in a prototypical language. :)
Right now the object you pass to NSObject.extend becomes the prototype of the new class - its __proto__ is set to the prototype of the class you extend (in your case UIViewController). This means that any connections to an existing prototype chains are severed. What's more, the current extend mechanism only considers the object's own properties, largely because for the purposes of extend it never exists in a prototype chain other than the one extend itself builds.
What you can do right now is manually copy the functions in SharedFunctions to the object you pass to extend and this should have the desired effect. With classes, however, you would be able to use a mixin mechamism to achieve the same result in a more idiomatic way.
Ah, thx, mkay, then it makes sense inherited properties won't work now.
I take it the proposal in this issue will split the inheritance and method-exposing and class registering bits, right? Cause creating an object that has UIControllerView as an ancestor prototype is a different concern from making its public methods available for iOS. Then I could use whatever inheritance scheme I'm after as long as the root of it inherits from e.g. UIControllerView. That would have to happen with the class syntax anyways I assume.
PS. Opened an issue on the extend plugin you linked to. Turned out it's consistent with its inherited properties use too. Other than that a simple for in loop would do the trick equivalently.
Yes, you are correct, the idea is to create a new register function that accepts a constructor function with prototypes and everything already attached like so:
class MyView extends UIView {
constructor(value) {
super();
this._value = value;
}
drawRect(rect) {
// drawing logic here
}
}
interop.objc.register(MyView);
You could do the same by wiring everything by hand like so:
function MyView(value) {
var self = Reflect.construct(UIView, undefined, MyView);
self._value = value;
return self;
}
Object.setPrototypeOf(MyView, UIView);
MyView.prototype = Object.create(UIView.prototype);
MyView.prototype.constructor = MyView;
MyView.prototype.drawRect = function () {
// drawing logic here
};
interop.objc.register(MyView);
In this case however you need to ignore the this value JavaScript generates for you when evaluating new MyView('foo') and invoke the base constructor. That is because the JavaScript constructors for Objective-C classes return a special kind of object that is bound to a native Objective-C object and manages its lifetime. The new class syntax invokes the base constructor and uses it to initialize the this value inside the constructor function when you execute super() instead of you having to do it by hand.
ES6 class syntax is sadly being postponed for 1.4.
- 💯 We need to support this in order to switch TypeScript to ES2015 output.