Bug 28998 - A New Custom UIBarButtonItem Is Not Enabled By Default
Summary: A New Custom UIBarButtonItem Is Not Enabled By Default
Alias: None
Product: iOS
Classification: Xamarin
Component: General ()
Version: XI 8.9.x (iOS 8.3)
Hardware: PC Mac OS
: Normal normal
Target Milestone: Future Cycle (TBD)
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Reported: 2015-04-10 16:49 UTC by Jimmy [MSFT]
Modified: 2016-10-31 14:24 UTC (History)
5 users (show)

Is this bug a regression?: ---
Last known good build:

Repro Project (11.78 KB, application/zip)
2015-04-10 16:49 UTC, Jimmy [MSFT]

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Jimmy [MSFT] 2015-04-10 16:49:14 UTC
Created attachment 10718 [details]
Repro Project

*** Overview ***

A custom UIBarButtonItem that inherits from the UIBarButtonItem class has different “Enabled” values depending on if the default constructor is included in the custom class or not.

In the attach repro project, two UIBarButtonItems are created using:

var customBtn = new CustomButton(new UIImage(), UIBarButtonItemStyle.Plain, (sender, e) => {});

var normalBtn = new UIBarButtonItem(new UIImage(), UIBarButtonItemStyle.Plain, (sender, e) => {});

When the CustomButton class includes the default constructor, customBtn.Enabled returns false. If the default constructor is excluded, customBtn.Enabled return true.

This is compared to a regular UIBarButtonItem.Enabled which always returns true by default.

*** Steps to Reproduce ***

1. Run the attached repro project
2. In the Output, observe that the custom UIBarButtonItem returns a different Enabled value than the normal UIBarButtonItem
3. In “CustomButton.cs”, comment out the default constructor 
4. Run the app again and observe that the UIBarButtonItems now return the same Enabled value

*** Actual Results ***

If the default constructor is included, the custom UIBarButtonItem is not enabled by default.
If the default constructor is excluded, the custom UIBarButtonItem is enabled by default.

*** Expected Results ***

The custom UIBarButtonItem should be enabled by default regardless of the default constructor being included or not.

*** Environment Info ***
=== Xamarin Studio ===

Version 5.8.3 (build 1)
Installation UUID: 94ce5106-6a72-4691-b34e-cd5857b1db66
	Mono 3.12.1 ((detached/0849ec7)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 312010003

=== Xamarin.Android ===

Version: (Business Edition)
Android SDK: /Users/jimmygarrido/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		2.1   (API level 7)
		2.2   (API level 8)
		2.3   (API level 10)
		3.1   (API level 12)
		4.0   (API level 14)
		4.0.3 (API level 15)
		4.4   (API level 19)
		5.0   (API level 21)
Java SDK: /usr
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)

=== Xamarin Android Player ===

Version: Unknown version
Location: /Applications/Xamarin Android Player.app

=== Apple Developer Tools ===

Xcode 6.3 (7569)
Build 6D570

=== Xamarin.iOS ===

Version: (Business Edition)
Hash: f7736a4
Build date: 2015-04-09 04:22:08-0400

=== Xamarin.Mac ===

Version: (Business Edition)

=== Build Information ===

Release ID: 508030001
Git revision: 6e8e725e0d689351901c2c70453bfa4ea25e293b
Build date: 2015-04-06 20:31:47-04
Xamarin addins: 051cd5f8c1b5dbfc87eaef80a74aec03f34c60a8

=== Operating System ===

Mac OS X 10.10.3
Darwin Jimmys-MacBook-Pro.local 14.3.0 Darwin Kernel Version 14.3.0
    Mon Mar 23 11:59:05 PDT 2015
    root:xnu-2782.20.48~5/RELEASE_X86_64 x86_64
Comment 1 Rolf Bjarne Kvinge [MSFT] 2015-04-15 08:33:24 UTC
I can reproduce this.
Comment 2 Rolf Bjarne Kvinge [MSFT] 2015-04-15 09:23:12 UTC
This happens because Objective-C allows base classes to call initializers in derived classes, but we can't translate that to managed code.

This is what happens when creating a CustomButton instance:

1. [C#] CustomButton ctor (UIImage, UIBarButtonItemStyle, EventHandler)
2. [C#] UIBarButtonItem ctor (UIImage, UIBarButtonItemStyle, EventHandler)
3. [ObjC] UIBarButtonItem initWithImage:style:target:action:
4. [ObjC] CustomButton init
-> here we try to marshal the code to [CustomButton init] to the corresponding managed ctor, but our code determines that there already is a CustomButton instance, so we don't call neither the managed ctor, nor [UIBarButtonItem init], and we end up with a half-baked CustomButton instance because the base class' [UIBarButtonItem init] initializer wasn't called.
Comment 3 Rolf Bjarne Kvinge [MSFT] 2015-04-15 11:14:17 UTC
There is a simple workaround: just don't implement a default ctor for CustomButton (you can add a dummy argument to accomplish this, even make that argument optional so that your source code elsewhere doesn't have to change).

However I'm not able to come up with a good fix (one possibility is to call [super init] directly instead of trying to invoke the CustomButton ctor above, but that probably has its own set of pitfalls as well).

I'll have to think about it.
Comment 4 Nate Cook 2015-04-15 11:53:10 UTC
Out of curiosity does this happen for all subclassed UIControls or just for UIBarButtonItem?
Comment 5 Rolf Bjarne Kvinge [MSFT] 2015-04-15 11:55:58 UTC
It happens for all UIControls that call 'init' from other initializers. My guess (based on the fact that this is the first time we've seen this issue), is that it's probably only UIBarButtonItem.
Comment 6 Sebastien Pouliot 2015-04-15 14:49:54 UTC
We'll need to check if the recent support (from Apple) for exposing designated initializers can be used to detect such condition.
Comment 7 Rolf Bjarne Kvinge [MSFT] 2015-04-16 03:42:35 UTC
@Sebastien, it won't help, UIBarButtonItem doesn't have any information about designated initializers in its header.

Also this is simply a difference between Objective-C and C#: Objective-C can call derived constructors from base classes, C# can't. Example code: https://gist.github.com/rolfbjarne/eb0238f7bf9a91b8c3cf - note how calling [self init] in line 30 ends up in the derived class' init implementation.
Comment 8 Nate Cook 2015-04-18 11:23:50 UTC
Looks like they might have to add a footnote to the advertised: "Anything you can do in Objective-C and Java can be done in C# with Xamarin." :-)
Comment 9 Rolf Bjarne Kvinge [MSFT] 2016-06-29 08:50:49 UTC
This might have been fixed with the fix for #35458.
Comment 10 Rolf Bjarne Kvinge [MSFT] 2016-10-31 14:24:46 UTC
I can't reproduce the problem anymore with the test case, so it looks like this was fixed with the fix for bug #35458.