bro-gen: binding NSError error codes right
23 Oct 2017 | bro-gen bindingIn RoboVM’s cocoatouch there are bunch of NSError subclasses that don’t exist in objc iOS itself. For example WKError
This is hand written class required to allow RoboVM’s NSError return object error code which can be used to compare against enum members, such as WKErrorCode.
NSError
provides information by following properties:
@interface NSError : NSObject <NSCopying, NSSecureCoding>
@property (readonly, copy) NSErrorDomain domain;
@property (readonly) NSInteger code;
@property (readonly, copy) NSDictionary<NSErrorUserInfoKey, id> * userInfo;
in RoboVM world NSError
exposes same methods, but there is another hand written method getErrorCode
and its purpose is to return Object representation for error which can be used to compare agains error codes enums, usually present in binding as well.
So all this is just to allow using following code:
NSError error;
if (error.getErrorCode() == WKErrorCode.MediaPlayer) {
....
}
instead of:
NSError error;
if (error.getCode() == WKErrorCode.MediaPlayer.value()) {
....
}
how it works
getErrorCode is confusing as it knows only about values of NSCocoaErrorCode
enum. The magic is in following places:
What is happening:
static initializer
looks over all VM known classes for NSError subclasses and builds the mapallNSErrorClasses
domain to NSError subclass. To get to the party subclass shall contain staticgetClassDomain
method which is being called to get domain this NSError subclass is responsible for.marshaller
is responsible to create java side object corresponding to native one. But it first goes native side to get its domain staring and then ifallNSErrorClasses
contains class for domain it creates this virtual NSError subclass instance, e.g.WKError
- now WKError will be able to return proper object in
getErrorCode
how it was bound
WKErrorCode
was generated bybro-gen
to enum, then it was manually updated to implement NSErrorCode interfaceWKError
was manually written with implementation ofgetErrorCode
to return proper value fromWKErrorCode
;WKErrorCode
had to be annotated with@ForceLinkClass(WKError.class)
this forcesWKError
not to be excluded from scope as long asWKErrorCode
is used.
how it was reworked in bro-gen to simplify bindings
- new enum template
nserror_enum_template
added. it is used for enum as long as in enum specification there isnserror: true
- this template contains
NSErrorWrap
subclass ofNSError
subclass. So no need to manually write NSError subclass getErrorCode
required to be added enum (which connects NSError with it), usually there is global variable for this, so it has to be bound with enum bygetErrorCode
name.
Check this example:
enums:
GADErrorCode: {nserror: true, prefix: kGADError}
....
values:
kGADErrorDomain:
class: GADErrorCode
name: getClassDomain
Happy bro-gening!
Related: Tutorial: [ADMOB] using bro-gen to quick generate bindings
Comments