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 initializerlooks over all VM known classes for NSError subclasses and builds the mapallNSErrorClassesdomain to NSError subclass. To get to the party subclass shall contain staticgetClassDomainmethod which is being called to get domain this NSError subclass is responsible for.marshalleris responsible to create java side object corresponding to native one. But it first goes native side to get its domain staring and then ifallNSErrorClassescontains 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
WKErrorCodewas generated bybro-gento enum, then it was manually updated to implement NSErrorCode interfaceWKErrorwas manually written with implementation ofgetErrorCodeto return proper value fromWKErrorCode;WKErrorCodehad to be annotated with@ForceLinkClass(WKError.class)this forcesWKErrornot to be excluded from scope as long asWKErrorCodeis used.
how it was reworked in bro-gen to simplify bindings
- new enum template
nserror_enum_templateadded. it is used for enum as long as in enum specification there isnserror: true - this template contains
NSErrorWrapsubclass ofNSErrorsubclass. So no need to manually write NSError subclass getErrorCoderequired to be added enum (which connects NSError with it), usually there is global variable for this, so it has to be bound with enum bygetErrorCodename.
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