Skip to content

Instantly share code, notes, and snippets.

@mhutch
Created February 1, 2012 02:36
Show Gist options
  • Save mhutch/1714726 to your computer and use it in GitHub Desktop.
Save mhutch/1714726 to your computer and use it in GitHub Desktop.
Convert NSObjects to .NET primitives
class NSObjectConverter
{
static IntPtr selObjCType = MonoMac.ObjCRuntime.Selector.GetHandle ("objCType");
static IntPtr clsNSCFBoolean = Class.GetHandle ("NSCFBoolean");
public static object ConvertNumber (NSNumber num)
{
char kind;
unsafe {
kind = (char) *((byte *) MonoMac.ObjCRuntime.Messaging.IntPtr_objc_msgSend (num.Handle, selObjCType));
}
switch (kind) {
case 'c':
//HACK: bools always seem to be encoded as char type so inspect the class
if (num.ClassHandle == clsNSCFBoolean)
goto case 'B';
return num.SByteValue;
case 'C':
//HACK: bools always seem to be encoded as char type so inspect the class
if (num.ClassHandle == clsNSCFBoolean)
goto case 'B';
return num.ByteValue;
case 'B':
return num.BoolValue;
case 's':
return num.Int16Value;
case 'S':
return num.UInt16Value;
case 'i':
case 'l':
return num.Int32Value;
case 'I':
case 'L':
return num.UInt32Value;
case 'q':
return num.Int64Value;
case 'Q':
return num.UInt64Value;
case 'f':
return num.FloatValue;
case 'd':
return num.DoubleValue;
default:
throw new NotSupportedException ("NSNumber of type " + kind);
}
}
public static byte[] ConvertData (NSData data)
{
var bytes = new byte[data.Length];
Marshal.Copy (data.Bytes, bytes, 0, (int)data.Length);
return bytes;
}
public static object ConvertPrimitive (NSObject obj)
{
var arr = obj as NSArray;
if (arr != null) {
var objArr = new object[arr.Count];
for (uint i = 0; i < objArr.Length; i++) {
objArr[i] = ConvertPrimitive (MonoMac.ObjCRuntime.Runtime.GetNSObject (arr.ValueAt (i)));
}
return MakeStrongerTypedArray (objArr);
}
var str = obj as NSString;
if (str != null)
return str.ToString ();
var num = obj as NSNumber;
if (num != null)
return ConvertNumber (num);
var date = obj as NSDate;
if (date != null)
return (DateTime) (NSDate) date;
var data = obj as NSData;
if (data != null)
return ConvertData (data);
throw new NotSupportedException (obj.ToString ());
}
static Type FindStrongestCommonType (System.Collections.IEnumerable objects)
{
var en = objects.GetEnumerator ();
if (!en.MoveNext ())
throw new ArgumentException ();
Type t = en.Current.GetType ();
Type o = typeof (object);
while (en.MoveNext ()) {
var u = en.Current.GetType ();
while (!u.IsSubclassOf (t)) {
t = t.BaseType;
if (t.Equals (o))
return o;
}
}
return t;
}
static Array MakeStrongerTypedArray (object[] objArr)
{
if (objArr.Length == 0)
return objArr;
var t = FindStrongestCommonType (objArr);
if (t.Equals (typeof (object)))
return objArr;
var typedArr = Array.CreateInstance (t, objArr.Length);
Array.Copy (objArr, typedArr, objArr.Length);
return typedArr;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment