iosswiftwebkitjavascriptcorejscontext

In what scenarios would iOS JSContext be nil since it returns an optional type?


I have an app which relies on Apple's JavaScriptCore heavily.

When I do:

let context = JSContext()

the context is an optional type.

In what scenarios would it be nil? I need to know how to properly handle this or which devices I should not support.


Solution

  • The Objective-C initialiser is imported into Swift as init!() - an initialiser that returns an implicitly-unwrapped optional (IUO). When you declare a context with this as the initialiser expression, the type of context will be inferred to be an optional type. The idea is that IUOs gets turned into regular optionals whenever possible (see SE-0054).

    You can get a non-optional JSContext just by adding an explicit type annotation:

    let context: JSContext = JSContext()
    

    The reason why the initialiser is imported as init!() and not init() or init?(), is likely because the Objective-C header file does not have nullability annotations. That is, the initialiser is declared:

    - (id)init;
    

    instead of either of these

    - (nullable id)init;
    - (nonnull id)init;
    

    This can be seen all over JavaScriptCore. All the parameter types and return value types are all imported into Swift as IUOs.

    All this is to say, that it could very well be the case that init can never return nil - it's just not annotated properly so it is not imported as a init() into Swift.

    Judging from the rest of the documentation in JavaScriptCore, it is highly likely that JSContext.init will not return nil. In the documentation of many other methods and properties in the module, it is clearly documented when something returns nil if it does. The documentation for JSContext.init does not mention this.