【问题标题】:Getting an Objective-C class name without having a MonoTouch managed class在没有 MonoTouch 托管类的情况下获取 Objective-C 类名
【发布时间】:2012-07-24 05:11:53
【问题描述】:

我终其一生都想不出如何将它翻译成 MonoTouch。有接盘侠吗?

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

让我难过的主要是视图类描述......

【问题讨论】:

    标签: c# objective-c ios xamarin.ios translate


    【解决方案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.Typedescription 主要是 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 类,而不仅仅是那些响应NSObjectdescription 消息的类:

    // ** 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"))
          {
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-02-11
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        • 1970-01-01
        • 1970-01-01
        • 2021-10-20
        • 2021-09-29
        相关资源
        最近更新 更多