Bug 14573 - Tokenizer member on UITextView not set
Summary: Tokenizer member on UITextView not set
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll ()
Version: 6.4.4
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
Depends on:
Reported: 2013-09-09 16:21 UTC by David Scharf
Modified: 2013-09-30 04:20 UTC (History)
3 users (show)

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

Tokenizer TestCase (1.41 MB, application/zip)
2013-09-09 16:55 UTC, David Scharf

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 David Scharf 2013-09-09 16:21:25 UTC
When creating a new UITextView, my understanding is, that it should have a Tokenizer member set. It does not have that in my version of MonoTouch. To reproduce this issue, create a new project and post this two lines in the FinishedLaunching() function.

UITextView tv = new UITextView ();
Console.WriteLine (" tokenizer : " + tv.Tokenizer);

The Tokenizer will be "null".

I am on the newest version of the stable branch for iOS6. I'm not exactly sure what that is, but I just updated. Where can I find this information?
Comment 1 Sebastien Pouliot 2013-09-09 16:43:15 UTC
It's non-null inside an existing application.

Can you attach your test case ? maybe it's called just a bit too early and something it not (yet) fully initialized.

The easiest way to get exact version information is to use the "Xamarin Studio" menu, "About Xamarin Studio" item, "Show Details" button and copy/paste the version informations (you can use the "Copy Information" button).
Comment 2 David Scharf 2013-09-09 16:55:23 UTC
Created attachment 4816 [details]
Tokenizer TestCase
Comment 3 David Scharf 2013-09-09 16:56:53 UTC
Thanks for getting back to me so fast. I've uploaded the test case for you. I'm actually working on a much bigger app and the two lines I posted is just the boiled down code so you can see what's happening. I modified the test case a bit to be sure that all the init is done by the time I check the Tokenizer.
Comment 4 David Scharf 2013-09-09 16:57:53 UTC
Oh and my version is Could've found it myself, sorry..
Comment 5 Sebastien Pouliot 2013-09-09 17:32:22 UTC
Thanks for the test case. It turns out I was wrong (comment #1) because I was using a different version of iOS.

In iOS6 `tv.Tokenizer` is null while `v.WeakTokenizer.Description` shows:

"<UIWebDocumentView: 0xc96a800; frame = (0 0; 100 23); text = ''; opaque = NO; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0xc1d1140>; layer = <UIWebLayer: 0xc1cfe10>>"

So what happens is the `Tokenizer` is set to a "private" Apple type. The managed code does not know about it and treat it as an weakly typed `NSObject`. 

Now since it inherit from `UIView` and that `UIView` does not conform (by default) to `UITextInputTokenizer` then the (.NET) cast returns `null`.
Comment 7 David Scharf 2013-09-09 17:41:49 UTC
Ok, but even in iOS 6 the Tokenizer should be a UITextInputTokenizer and available via this Member. Or how can I access the Tokenizer in MonoTouch then? It shouldn't be a UIView in any case.
Comment 8 Sebastien Pouliot 2013-09-09 17:48:09 UTC
> It shouldn't be a UIView in any case.

It can be any type that conforms to the `UITextInputTokenizer` protocol - which `UIWebDocumentView` does obviously (since it works on iOS6) but since it's undocumented that information is not really helpful (since it can't be registered properly).

> Or how can I access the Tokenizer in MonoTouch then?

Anyway to workaround this kind (of really uncommon issue) you need to use the `Weak` property.

You can use it as an `NSObject` and send messages to selectors to it - but that's not very elegant.

The other way is to wrap it inside an existing (non-abstract) type that does what you want, e.g.

	var tokenizer = new UITextInputStringTokenizer (tv.WeakTokenizer.Handle);
	tokenizer.Release (); // the ctor will do an extra Retain
	Console.WriteLine ("is tokenizer null ? : " + (tokenizer == null ));

That will give you a `tokenizer` instance that expose the right API. It's cheating but it follows the right rules (so it's safe).

You might want to do this conditionally to avoid it whenever possible, e.g.

	var tokenizer = tv.Tokenizer;
	if (tokenizer == null) {
		tokenizer = new UITextInputStringTokenizer (tv.WeakTokenizer.Handle);
		tokenizer.Release ();
	// go on using `tokenizer`
Comment 9 David Scharf 2013-09-09 17:59:47 UTC
Ah ok, I didn't know that much about the inner workings of the framework. Thanks for shedding some light on this, I got it to work the way you suggested!
Comment 10 David Scharf 2013-09-23 04:54:13 UTC
I just switched to the iOS 7 SDK, and it turns out that "UITextView.Tokenizer" is null again. If have also verified that this is not an initialization issue. Could you look in to that?
Comment 11 David Scharf 2013-09-25 09:41:33 UTC
Any thoughts about this?
Comment 12 Rolf Bjarne Kvinge [MSFT] 2013-09-26 07:44:03 UTC
This does not depend on the SDK you built with, but the device/simulator you're running on. Can you confirm if you're running this on an iOS6 or iOS7 device/simulator?
Comment 13 David Scharf 2013-09-26 07:45:21 UTC
I ran it on an iOS 7 Simulator and an iOS 7 device.
Comment 14 Rolf Bjarne Kvinge [MSFT] 2013-09-27 08:51:32 UTC
I can't reproduce this. 

In any case it is not a bug in MonoTouch, the Tokenizer property will only be set if the underlying ObjC value can be cast to UITextInputTokenizer (which isn't always true).

I suggest you use Sebastien's suggestion from comment #8, and it'll work fine.

In the future we'll expose a property typed as an interface, and that would only be null if the actual value is null too.
Comment 15 David Scharf 2013-09-28 11:46:24 UTC
Thanks for getting back to me on this. I have tested this in XCode, and you're right. The Tokenizer property is not being set in the native environment. Sebastiens workaround does not work with iOS 7, but that's ok. I assume this is an iOS 7 bug but I will see if anyone has answers to this on Stackoverflow.

But if you say you can't reproduce this, what setup are you using? I can clearly see that this property will not be set in the example project that I uploaded to this thread.
Comment 16 Rolf Bjarne Kvinge [MSFT] 2013-09-30 04:20:52 UTC
Why doesn't Sebastien's workaround work on iOS7?

I use Xamarin.iOS 7.0, and if I run the test case from comment #2 on the iOS 7 simulator it prints:

 is tokenizer null ? : False