PeterStaev / NativeScript-Drop-Down

A NativeScript DropDown widget.
Apache License 2.0
105 stars 65 forks source link

[iOS] TypeError: undefined is not an object (evaluating 'this._listPicker.reloadAllComponents') #209

Closed NickIliev closed 5 years ago

NickIliev commented 5 years ago

The issue is happening under strange circumstances and only on iOS.

Steps to reproduce:

Execute tns run ios and the app will immediately crash with

JavaScript error:
file:///app/vendor.js:549:25: JS ERROR TypeError: undefined is not an object (evaluating 'this._listPicker.reloadAllComponents')
NativeScript caught signal 11.
Native Stack:
1   0x1027bf1df sig_handler(int)
2   0x1062a0b3d _sigtramp
3   0x118631940
4   0x1061e6b4d libunwind::UnwindCursor<libunwind::LocalAddressSpace, libunwind::Registers_x86_64>::step()
5   0x1061eae4c _Unwind_RaiseException
...

Note:

The orientation plugin was required as follows

var orientation =  require("nativescript-orientation"); 

Note if I use the TypeScript import the issue is not reproducible

import * as orientation from "nativescript-orientation";

The issue was reported through plain JS project were require is the only option.

Not sure if the issue is caused by logic in the orientation plugin (@NathanaelA) or by some other incompatibility between the two plugins.

NathanaelA commented 5 years ago

@NickIliev

The require vs import is a false trail; after you compile that statement in TS to JS, it will be the same. ;-)

However, as I have seen this type of issue appear in other components over the years -- this is the source of the call that causes issue. (So I know where to look right away. :grinning: )

https://github.com/NathanaelA/nativescript-orientation/blob/master/src/orientation.js#L310 Unfortunately this is needed; the root of the issue is that when I call the child refresh; the child (in this case the dropdown has something that might not be initialized correctly) which calls this: https://github.com/PeterStaev/NativeScript-Drop-Down/blob/master/drop-down.ios.ts#L154

Basically Peter needs to add a guard here as anything calling refresh will cause the same failure if it done it early enough. My refresh can occur at the startup if the person rotates quickly while the screen is still being built...

So I would recommend he changes this function to be:

  public refresh() {
        if (this._listPicker) {
            this._listPicker.reloadAllComponents();

            // Coerce selected index after we have set items to native view.
            selectedIndexProperty.coerce(this);
        }
    }

So that if _listPicker has NOT been created yet, this code ends up being a no-op. :grinning:

NathanaelA commented 5 years ago

@PeterStaev - Awesomely fast fix -- Thanks!

PeterStaev commented 5 years ago

Thank you both for the nice tracing! 👍