Bug 58832 - NSString.DrawString(CGPoint,UIStringAttributes) incorrectly throws when called on background thread
Summary: NSString.DrawString(CGPoint,UIStringAttributes) incorrectly throws when calle...
Status: CONFIRMED
Alias: None
Product: iOS
Classification: Xamarin
Component: Xamarin.iOS.dll (show other bugs)
Version: XI 10.99 (xcode9)
Hardware: PC Mac OS
: --- normal
Target Milestone: Future Cycle (TBD)
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2017-08-16 23:12 UTC by Larry O'Brien
Modified: 2017-09-22 14:47 UTC (History)
5 users (show)

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


Attachments
Application that throws (WatermarkPage.cs line 59) (234.89 KB, application/zip)
2017-08-16 23:12 UTC, Larry O'Brien
Details


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 for Bug 58832 on Developer Community or GitHub if you have new information to add and do not yet see a matching new report.

If the latest results still closely match this report, you can use the original description:

  • Export the original title and description: Developer Community HTML or GitHub Markdown
  • Copy the title and description into the new report. Adjust them to be up-to-date if needed.
  • Add your new information.

In special cases on GitHub you might also want the comments: GitHub Markdown with public comments

Related Links:
Status:
CONFIRMED

Description Larry O'Brien 2017-08-16 23:12:38 UTC
Created attachment 24258 [details]
Application that throws (WatermarkPage.cs line 59)

I believe that `NSString.DrawString(CGPoint,UIStringAttributes)` should be callable from a background thread. I think the method is defined as an extension method in the class `NSStringDrawing`.

The attached project draws strings on a PdfPage. It is a port of Apple's sample: 

https://developer.apple.com/sample-code/wwdc/2017/Document-Watermark.zip

In Swift, working code looks like:

        let string: NSString = "U s e r   3 1 4 1 5 9"
        let attributes = [
            NSAttributedStringKey.foregroundColor: UIColor(colorLiteralRed: 0.5, green: 0.5, blue: 0.5, alpha: 0.5),
            NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 64)
        ]

        string.draw(at: CGPoint(x:250, y:40), withAttributes: attributes)

In C#, the straight-across port would seem to be: 

            var text = new NSString("Confidential");
            var attributes = new UIStringAttributes()
            {
                ForegroundColor = UIColor.FromRGBA(255, 0, 0, 125),
                Font = UIFont.BoldSystemFontOfSize(64)
            };

            text.DrawString(new CGPoint(250, 40), attributes);
            

But, when run, the `DrawString(CGPoint,UIAttributes)` call raises a `UIKitThreadAccessException`. If you wrap the call to `DrawString` in either a `InvokeOnMainThread` or `DispatchQueue.MainQueue.DispatchSync` call, the text is not written to the context (even if you block). 

You can successfully draw an attributed string if you change the code to:

			var attributes = new UIStringAttributes()
			{
				ForegroundColor = UIColor.FromRGBA(255, 0, 0, 125),
				Font = UIFont.BoldSystemFontOfSize(64)
			};

			var text = new NSAttributedString("Confidential", attributes);
           
			text.DrawString(new CGPoint(250, 40));

Also, NSString.DrawString(CGPoint,Font) works fine on a background thread:

			var t2 = new NSString("This works");
			t2.DrawString(new CGPoint(250, 90), UIFont.BoldSystemFontOfSize(30));

The attached project demonstrates the problem. WatermarkPage.cs, line 59, if left uncommented, throws. Comment it out and the program runs. 

---

=== Visual Studio Community 2017 for Mac (Preview) ===

Version 7.1 Preview (7.1 build 1267)
Installation UUID: 6b94f136-026d-4a5a-bf6d-af2c0d8dc019
Runtime:
	Mono 5.2.0.196 (2017-04/478c04a) (64-bit)
	GTK+ 2.24.23 (Raleigh theme)

	Package version: 502000196

=== NuGet ===

Version: 4.3.0.2418

=== .NET Core ===

Runtime: Not installed
SDK: Not installed
MSBuild SDKs: /Library/Frameworks/Mono.framework/Versions/5.2.0/lib/mono/msbuild/15.0/bin/Sdks

=== Xamarin.Profiler ===

Version: 1.4.0
Location: /Applications/Xamarin Profiler.app/Contents/MacOS/Xamarin Profiler

=== Apple Developer Tools ===

Xcode 9.0 (13226.5)
Build 9M202q

=== Xamarin.iOS ===

Version: 10.99.3.38 (Visual Studio Community)
Hash: 4e3cad4
Branch: xcode9
Build date: 2017-08-11 10:58:25-1000

=== Xamarin.Android ===

Version: 7.3.1.2 (Visual Studio Community)
Android SDK: /Users/larryobrien/Library/Developer/Xamarin/android-sdk-macosx
	Supported Android versions:
		2.3   (API level 10)
		4.0.3 (API level 15)
		4.4   (API level 19)
		5.0   (API level 21)
		5.1   (API level 22)
		6.0   (API level 23)

SDK Tools Version: 25.2.5
SDK Platform Tools Version: 25.0.5
SDK Build Tools Version: 25.0.3

Java SDK: /usr
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

Android Designer EPL code available here:
https://github.com/xamarin/AndroidDesigner.EPL

=== Xamarin.Mac ===

Version: 3.99.3.38 (Visual Studio Community)

=== Xamarin Inspector ===

Version: 1.3.0-alpha2
Hash: fa030e0
Branch: master
Build date: Thu, 01 Jun 2017 20:55:26 GMT
Client compatibility: 1

=== Build Information ===

Release ID: 701001267
Git revision: 342f47be42098b95880cf4c6d957719b5fef53e3
Build date: 2017-07-12 17:43:22-04
Xamarin addins: e513cc1830b4daa75f67c608e2c722e811b23ab2
Build lane: monodevelop-lion-d15-3-xcode9

=== Operating System ===

Mac OS X 10.12.6
Darwin 16.7.0 Darwin Kernel Version 16.7.0
    Thu Jun 15 17:36:27 PDT 2017
    root:xnu-3789.70.16~2/RELEASE_X86_64 x86_64
Comment 1 Alex Soto [MSFT] 2017-08-17 02:08:43 UTC
I am not entirely sure on this one the API used here is:

https://developer.apple.com/documentation/foundation/nsstring/1533109-drawatpoint

the documentation just states this:

> There must be either a focused view or an active graphics context when you call this method.

Which could imply it is thread safe, the only requirement is a GCContext or a focused view according to it.

@rolf / @sebastien thoughts?

Moving to need awaiting Rolf's or Sebastien's input
Comment 2 Rolf Bjarne Kvinge [MSFT] 2017-08-17 06:41:56 UTC
I think it should be thread safe, based on the documentation.

Also Xcode 9 added the same ui thread check we have, which means that if the Xcode sample is working fine in Xcode 9, it implies the API is safe to use.
Comment 3 Sebastien Pouliot 2017-08-17 13:05:57 UTC
> Also Xcode 9 added the same ui thread check we have

Is it enabled by default ?
I wanted to look at the option but have not gotten around to do it yet :(
Comment 4 Rolf Bjarne Kvinge [MSFT] 2017-08-17 13:23:01 UTC
> > Also Xcode 9 added the same ui thread check we have
> 
> Is it enabled by default ?
> I wanted to look at the option but have not gotten around to do it yet :(

Yes, it's enabled by default when debugging with Xcode (https://developer.apple.com/documentation/code_diagnostics/main_thread_checker).(In reply to Sebastien Pouliot from comment #3)
Comment 5 Manuel de la Peña [MSFT] 2017-09-22 14:47:01 UTC
After a conversation with @sebastien, setting to confirmed.