New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructors of controllers instantiated via storyboards aren't called #894

Closed
badlogic opened this Issue Apr 10, 2015 · 8 comments

Comments

Projects
None yet
5 participants
@badlogic
Contributor

badlogic commented Apr 10, 2015

Given the following UITableViewController:

@CustomClass("TestController")
public class TestController extends UITableViewController {
    private final List<String> items = new ArrayList<String>();

    @Override
    public void viewDidLoad() {
        super.viewDidLoad();
        items.add("Cat");
        items.add("Dog");
        items.add("Bird");
    }
...

I write this up to a storyboard. When the app loads, the TestController is unmarshalled and the viewDidLoad method is called. The app crashes with an NPE on the first call to items#add.

@badlogic badlogic added the bug label Apr 10, 2015

@badlogic badlogic added this to the 1.1 milestone Apr 10, 2015

@badlogic

This comment has been minimized.

Contributor

badlogic commented Apr 10, 2015

viewDidLoad is called before the default constructor and instance initializer code is called :(

@badlogic badlogic added the high label Apr 10, 2015

@BlueRiverInteractive

This comment has been minimized.

Contributor

BlueRiverInteractive commented Apr 10, 2015

Possibly related: You cannot override the constructor of a native class like UIView. You can, but when objc creates a new instance of your subclass, it will not invoke the Java constructor. So if you want to execute code on object creation, you have to override one of the protected initXXX methods.

@ntherning

This comment has been minimized.

Contributor

ntherning commented Apr 10, 2015

This is "by design". :-) If the ObjC side instantiates an instance of your custom class no constructor will be called on the Java side. You can set up of fields in afterMarshaled() or in viewDidLoad(). Yeah, this sucks and we should do something about it but it's not trivial.

@badlogic

This comment has been minimized.

Contributor

badlogic commented Apr 10, 2015

What's the problem with calling the (default) constructor?
On Apr 10, 2015 7:54 PM, "Niklas Therning" notifications@github.com wrote:

This is "by design". :-) If the ObjC side instantiates an instance of your
custom class no constructor will be called on the Java side. You can set up
of fields in afterMarshaled() or in viewDidLoad(). Yeah, this sucks and
we should do something about it but it's not trivial.


Reply to this email directly or view it on GitHub
#894 (comment).

@ntherning

This comment has been minimized.

Contributor

ntherning commented Apr 10, 2015

It ultimately calls ObjCObject() which calls alloc and init on the ObjC side. We need a way to know in the default constructor that it shouldn't do alloc/init. Also, we don't do anything ATM when the object is allocated/inited on the ObjC side. It's not until it is passed over to the Java side we create an instance on that side. We need a way to hook into the allocation/initialization on the ObjC side.

@ntherning

This comment has been minimized.

Contributor

ntherning commented Apr 14, 2015

We definitely need to fix this and make it possible to bind constructors. But there's not enough time for 1.1. Will postpone until 1.2.

@ntherning ntherning modified the milestones: 1.2, 1.1 Apr 14, 2015

@badlogic badlogic changed the title from NPE when accessing final member after unmarshalling UITableViewController to Constructors of controllers instantiated via storyboards aren't called Apr 14, 2015

@ntherning ntherning modified the milestones: 1.2, 1.3, Smörgåsbord May 6, 2015

@simophin

This comment has been minimized.

simophin commented Jul 17, 2015

This sort of breaks Java language, when can this be fixed?

@badlogic badlogic modified the milestones: 1.7, Smörgåsbord Aug 6, 2015

@badlogic badlogic self-assigned this Aug 6, 2015

@badlogic badlogic modified the milestones: Smörgåsbord, 1.7 Aug 24, 2015

@JohnColanduoni

This comment has been minimized.

JohnColanduoni commented Sep 16, 2015

As a possible suggestion for how to fix this, you might want to take a look at how Xamarin does it. Instead of having an init method, constructors for both the "create from managed code" (parameterless) and "create managed wrapper for unmanaged object" (with a pointer parameter) cases are provided.

The main disadvantage to this is that you cannot make managed versions of init return nil, but I suspect this an uncommon use case.

@ntherning ntherning added this to the 1.9 milestone Oct 1, 2015

@ntherning ntherning removed this from the Smörgåsbord milestone Oct 1, 2015

@ntherning ntherning assigned ntherning and unassigned badlogic Oct 1, 2015

@ntherning ntherning added ready in progress and removed ready labels Oct 1, 2015

@ntherning ntherning closed this Oct 8, 2015

@ntherning ntherning removed the in progress label Oct 8, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment