Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting an Objective-C class name without having a MonoTouch managed class

I can't for the life of me figure out how to translate this into MonoTouch. Any takers?

for(UIView* view in cell.subviews)
{
    if([[[view class] description] isEqualToString:@"UITableViewCellReorderControl"])
    {
    }
}

Mostly it's the View Class Description that has me stumped...

like image 791
Rick Avatar asked Jul 25 '12 17:07

Rick


2 Answers

In general, @Monoman's is solution is the right way to find instances of a particular class, even when you're looking for a CocoaTouch class from within a MonoTouch program.

Sometimes, however, you'll discover that there's an internal CocoaTouch class that's not exposed in MonoTouch (or even in the iOS Platform headers). In such a case, you'll have to resort to tricks like @poupou is doing.

Unfortunately, his answers won't work here either. view.GetType() is returning the most-derived MonoTouch type that each Subview implements, and then ToString(), Class.Name, or even @selector("description") each operate on the wrong type and give an overly generic answer ("UIView" in this case).

In order to make this work, you'll have to go one layer deeper under the covers than @poupou proposed.

// ** using MonoTouch.ObjCRuntime; **

private string GetClassName (IntPtr obj) {
    Selector description = new Selector ("description");
    Selector cls = new Selector ("class");
    IntPtr viewcls = Messaging.IntPtr_objc_msgSend (obj, cls.Handle);
    var name = NSString.FromHandle (Messaging.IntPtr_objc_msgSend (viewcls, description.Handle));
    return name;
}

Here's an alternative that's not a whole lot more fiddly (maybe even less?), but will work on any Objective-C class, not just those that respond to NSObject's description message:

// ** using System.Runtime.InteropServices; **

[DllImport ("/usr/lib/libobjc.dylib")]
private static extern IntPtr object_getClassName (IntPtr obj);

private string GetClassName (IntPtr obj) {
    return Marshal.PtrToStringAuto(object_getClassName(obj));
}

It's actually surprising and a little bit sad that MonoTouch doesn't provide an import for object_getClassName() already.

You would use either one of those like so:

foreach (UIView view in cell.Subviews) {
    if (GetClassName(view.Handle) == "UITableViewCellReorderControl") {
    }
}

Big fat disclaimer: Pretty much any time you're resorting to tricks like these, you're relying on CocoaTouch implementation details that Apple reserves the right to change. Rule of thumb: if you can do what you want with @Monoman's solution, you're probably safe. Otherwise, you're taking matters in to your own hands.

like image 108
sblom Avatar answered Oct 21 '22 15:10

sblom


I'm not using Monotouch currently, but shouldn't you just check the managed type of the subview?

   foreach (UIView view in cell.subviews)
   {
     if (view is UITableViewCellReorderControl) {}
   }
like image 5
Monoman Avatar answered Oct 21 '22 17:10

Monoman