* Fix many version checks to be based on Xcode version instead of iOS version.
* Added/fixed a few expected values according to platform version to match behavior in older macOS versions.
* Convert it into a MM8027/MT8027 error (with documentation).
* Add information about the selector and managed method that triggered the error.
Now the problem reported in issue #4254 shows up as:
> ObjCRuntime.RuntimeException: Failed to marshal the Objective-C object 0x7f8080412810 (type: UIView). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'UIKit.UIView&' does not have a constructor that takes one IntPtr argument).
> Additional information:
> Selector: popoverController:willRepositionPopoverToRect:inView:
> Method: UIKit.UIPopoverController+_UIPopoverControllerDelegate.WillReposition(UIKit.UIPopoverController, CoreGraphics.CGRect ByRef, UIKit.UIView ByRef)
instead of just:
> ObjCRuntime.RuntimeException: Failed to marshal the Objective-C object 0x7f8080412810 (type: UIView). Could not find an existing managed instance for this object, nor was it possible to create a new managed instance (because the type 'UIKit.UIView&' does not have a constructor that takes one IntPtr argument).
which makes it much easier to understand, track down, and fix/work around,
both for customers and ourselves.
Creating a new NSString doesn't always lead to creating a new NSString, which
will obviously cause trouble.
The scenario is:
* An NSString with the value @"Bye" is added to an NSDictionary, with the same
string as both the key and the value.
* The (managed) string indexer is used to try to get the value back. The
string indexer would call 'new NSString ("Bye")', which would create a new
managed NSString, and maybe a new native NSString (or maybe it would re-use
an existing NSString). Then the handle of this NSString would be passed to
the native API, and the same handle would come back as the result (since the
same string is both the key and the value). We'd call Runtime.GetNSString on
the returned handle, get back the same managed instance that was created
just before the call to the native method. Finally, just before returning
this managed instance from the indexer, we'd dispose it... since it was
created in a 'using' block. Then we'd return a disposed NSString object from
the indexer. Ops.
The fix is to not create a managed wrapper for the NSString handle we need to
pass to the native API, but create and free the native NSString object without
using a managed wrapper.