Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reverse NSObject.FromObject back to a regular C# type

What is the reverse of NSObject.FromObject, e.g., getting a regular C# object back out of an NSObject. Understandably, this could only work for simple types.

Update. Let's say I even know the type - but not before runtime. I tried

Convert.ChangeType (value, info.PropertyType, null)

but i get a message that "Value is not a convertible object: MonoMac.Foundation.NSString to System.String".

Update 2. How FromObject works:

using MonoMac.ObjCRuntime;
using System;
using System.Drawing;
public static NSObject FromObject (object obj)
{
    NSObject result;
    if (obj == null)
    {
        result = NSNull.Null;
    }
    else
    {
        Type type = obj.GetType ();
        if (type == typeof(NSObject) || type.IsSubclassOf (typeof(NSObject)))
        {
            result = (NSObject)obj;
        }
        else
        {
            switch (Type.GetTypeCode (type))
            {
            case 3:
                result = new NSNumber ((bool)obj);
                return result;
            case 4:
                result = new NSNumber ((ushort)((char)obj));
                return result;
            case 5:
                result = new NSNumber ((sbyte)obj);
                return result;
            case 6:
                result = new NSNumber ((byte)obj);
                return result;
            case 7:
                result = new NSNumber ((short)obj);
                return result;
            case 8:
                result = new NSNumber ((ushort)obj);
                return result;
            case 9:
                result = new NSNumber ((int)obj);
                return result;
            case 10:
                result = new NSNumber ((uint)obj);
                return result;
            case 11:
                result = new NSNumber ((long)obj);
                return result;
            case 12:
                result = new NSNumber ((ulong)obj);
                return result;
            case 13:
                result = new NSNumber ((float)obj);
                return result;
            case 14:
                result = new NSNumber ((double)obj);
                return result;
            case 18:
                result = new NSString ((string)obj);
                return result;
            }
            if (type == typeof(IntPtr))
            {
                result = NSValue.ValueFromPointer ((IntPtr)obj);
            }
            else
            {
                if (type == typeof(SizeF))
                {
                    result = NSValue.FromSizeF ((SizeF)obj);
                }
                else
                {
                    if (type == typeof(RectangleF))
                    {
                        result = NSValue.FromRectangleF ((RectangleF)obj);
                    }
                    else
                    {
                        if (type == typeof(PointF))
                        {
                            result = NSValue.FromPointF ((PointF)obj);
                        }
                        else
                        {
                            INativeObject nativeObject = obj as INativeObject;
                            if (nativeObject != null)
                            {
                                result = Runtime.GetNSObject (nativeObject.Handle);
                            }
                            else
                            {
                                result = null;
                            }
                        }
                    }
                }
            }
        }
    }
    return result;
}
like image 550
tofutim Avatar asked Sep 26 '13 09:09

tofutim


1 Answers

Just like the FromObject conversion, you have to handle that case by case.

for NSNumbers, use explicit casting (works for bool as well):

NSNumber number;
double d = (double)number;

for NSStrings, implicit conversion even work:

NSString nsstring;
string converted = nsstring;

But I guess you already figured the value types conversions.

For reference type, all types deriving from NSObject (that's the case for most of the objects you want to pass back and forth to native) have a constructor overload taking an IntPtr as argument. use that.

NSObject native;
var label = new UILabel (native.Handle);

That being said, the NSObject is redundant. Your native library could just return an IntPtr (void*) you could use to recreate your objects. You DON'T have to do this:

IntPtr ptr;
NSObject nsobject = new NSObject (ptr);
like image 151
Stephane Delcroix Avatar answered Sep 19 '22 17:09

Stephane Delcroix