Created
February 1, 2012 02:36
-
-
Save mhutch/1714726 to your computer and use it in GitHub Desktop.
Convert NSObjects to .NET primitives
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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