在没有 MonoTouch 托管类的情况下获取 Objective-C 类名
Posted
技术标签:
【中文标题】在没有 MonoTouch 托管类的情况下获取 Objective-C 类名【英文标题】:Getting an Objective-C class name without having a MonoTouch managed class 【发布时间】:2012-07-24 05:11:53 【问题描述】:我终其一生都想不出如何将它翻译成 MonoTouch。有接盘侠吗?
for(UIView* view in cell.subviews)
if([[[view class] description] isEqualToString:@"UITableViewCellReorderControl"])
让我难过的主要是视图类描述......
【问题讨论】:
【参考方案1】:我目前没有使用 Monotouch,但您不应该只检查子视图的托管类型吗?
foreach (UIView view in cell.subviews)
if (view is UITableViewCellReorderControl)
【讨论】:
是的,原来的 direct 主要是在做:view.GetType ().ToString ()
其中[view class]
返回类型,description
返回名称(description
也被使用,由默认为NSObject.ToString()
。然而,来自@Monoman 的adapted 翻译更能代表这意味着什么。
如果 System.Linq 可用,您可以进一步缩写:foreach(var view in cell.subViews.OfType<UITableViewCellReorderControl>())
foreach (UIView subView in cell.Subviews) if(subView is UITableViewCellReorderControl) 抛出错误:错误 CS0246:找不到类型或命名空间名称“UITableViewCellReorderControl”。您是否缺少 using 指令或程序集引用? (CS0246)
这在这种情况下不起作用,因为UITableViewCellReorderControl
是一个深层的UIKit
内部。【参考方案2】:
Objective-C Class
的处理大部分隐藏在 MonoTouch 提供的 API 中。主要是 System.Type
和 description
主要是 ToString
- 但这不会显示一些内部结构。
您可以尝试以下几件事(从简单到复杂):
在view
实例上调用ToString
可能包括原始类名(作为描述的一部分) - 但它与调用class
本身的description
不同.
foreach (UIView view in cell.Subviews)
if (view.ToString ().Contains ("UITableViewCellReorderControl"))
接下来尝试查看Class
上的Name
是否与description
相同。
foreach (UIView view in cell.Subviews)
MonoTouch.ObjCRuntime.Class c = new MonoTouch.ObjCRuntime.Class (view.GetType ());
if (c.Name == "UITableViewCellReorderControl")
最后真正调用Class
实例上的description
选择器。类似(未尝试):
MonoTouch.ObjCRuntime.Selector description = new MonoTouch.ObjCRuntime.Selector ("description");
foreach (UIView view in cell.Subviews)
MonoTouch.ObjCRuntime.Class c = new MonoTouch.ObjCRuntime.Class (view.GetType ());
var name = NSString.FromHandle (MonoTouch.ObjCRuntime.Messaging.IntPtr_objc_msgSend (c.Handle, description.Handle));
if (name == "UITableViewCellReorderControl")
【讨论】:
我修复并测试了你的第三个。这些都没有捕获 OP 案例中的类型。我添加了一个答案,其中包含我测试过的几个实现。 效果很好!但是现在我必须弄清楚在哪里实现,以便表格中的单元格获得 ReorderControl 的新位置。如果我把它放在 WillDisplay 中,一切看起来都很好,直到我实际移动一个单元格。然后所有移动的单元格恢复到原始控件位置。关于移动后哪个方法会更新设置的任何想法?【参考方案3】:一般来说,@Monoman's is
solution 是查找特定类实例的正确方法,即使是在 MonoTouch 程序中查找 CocoaTouch 类时也是如此。
但是,有时您会发现有一个内部 CocoaTouch 类未在 MonoTouch 中公开(甚至在 ios 平台标头中)。在这种情况下,您将不得不求助于tricks like @poupou is doing。
不幸的是,他的答案在这里也行不通。 view.GetType()
正在返回每个 Subview
实现的最衍生的 MonoTouch 类型,然后是 ToString()
、Class.Name
甚至 @selector("description")
每个都在错误的类型上操作并给出过于通用的答案(“UIView
" 在这种情况下)。
为了完成这项工作,您必须比@poupou 建议的更深入一层。
// ** 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;
这里有一个替代方案,它不是更复杂(甚至可能更少?),但适用于任何 Objective-C 类,而不仅仅是那些响应NSObject
的description
消息的类:
// ** 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));
MonoTouch 还没有为object_getClassName()
提供导入,这确实令人惊讶,也有点遗憾。
您可以使用其中任何一种:
foreach (UIView view in cell.Subviews)
if (GetClassName(view.Handle) == "UITableViewCellReorderControl")
大胖子免责声明:几乎任何时候您使用这些技巧时,您都依赖于 Apple 保留更改权利的 CocoaTouch 实现细节。经验法则:如果您可以使用 @Monoman 的解决方案做您想做的事,那么您可能是安全的。否则,您将自己处理事情。
【讨论】:
【参考方案4】:这对我有用:
foreach(var subview in this.ContentView.Superview.Subviews)
if(subview.Class.Name.EndsWith("UITableViewCellReorderControl"))
【讨论】:
以上是关于在没有 MonoTouch 托管类的情况下获取 Objective-C 类名的主要内容,如果未能解决你的问题,请参考以下文章
如何在模拟器中为 MonoTouch 应用程序生成 .dSYM?