【问题标题】:CALayer initWithLayer: bound to default constructor by mistake? Can I override the default constructor?CALayer initWithLayer:错误地绑定到默认构造函数?我可以覆盖默认构造函数吗?
【发布时间】:2012-03-06 07:26:21
【问题描述】:

我找不到任何可以覆盖的 CALayer 的 initWithLayer:(layer) 选择器的等效绑定方法。

查看 Monotouch 程序集,选择器 initWithLayer 绑定到默认构造函数,如下所示:

[Export ("initWithLayer:")]
    public CALayer (CALayer other)
    {
        if (base.GetType () == typeof(CALayer))
        {
            Messaging.intptr_objc_msgSend_intptr (base.Handle, CALayer.selInitWithLayer, other.Handle);
        }
        else
        {
            Messaging.intptr_objc_msgSendSuper_intptr (base.SuperHandle, CALayer.selInitWithLayer, other.Handle);
            this.Clone (other);
        }
    }

但是,我需要能够覆盖 initWithLayer 以便在我的 CALayer 类中为我的自定义属性设置动画。 (在我之前的问题Animate a custom property using CoreAnimation in Monotouch?中指定)

这是错误地完成,还是我说不可能覆盖默认构造函数是不正确的?

Apples 文档指出 initWithLayer 的唯一用途是创建卷影副本,而不是用于初始化图层,这让我觉得它可能是 Monotouch 错误

Apple 文档

initWithLayer:覆盖以复制或初始化自定义字段 指定层。

  • (id)initWithLayer:(id)layer 参数 layer 应该从中复制自定义字段的层。返回值 具有任意 从图层复制的自定义实例变量。

讨论 这个初始化器用于创建图层的影子副本, 例如,对于presentationLayer 方法。

子类可以选择将它们的实例变量复制到新的 对象。

子类应该总是调用超类实现

注意:在任何其他情况下调用此方法都会产生 未定义的行为。不要使用此方法初始化新层 与现有图层的内容。可用性 在 iOS 2.0 中可用 然后。在 CALayer.h 中声明

编辑:

我需要重写这个方法的原因是 CoreAnimation 框架调用这个方法来创建它自己的层的内部副本。我需要能够覆盖它以包含我添加到图层中的新属性,以便 CoreAnimation 知道在动画过程中补间我的属性值。我不会自己打电话给这个。这就是为什么我不能简单地调用 Clone()

我尝试对 Rolf 的代码进行修改,但仍然没有被调用:

//Needed to do this as sel_registerName is private
[DllImport ("/usr/lib/libobjc.dylib")]
    internal static extern IntPtr sel_registerName (string name);

    static IntPtr selInitWithLayer = sel_registerName("initWithLayer:");

    [Export ("initWithLayer:")]
    public CircleLayer (CALayer other)  //changed SuperHandle to other.SuperHandle as using this.SuperHandle gives me an object reference required error.
        : base (Messaging.intptr_objc_msgSendSuper_intptr (other.SuperHandle, CircleLayer.selInitWithLayer, other.Handle))
    {
        // custom initialization here
        Console.WriteLine("Got to here");
    }

【问题讨论】:

    标签: c# xamarin.ios core-animation overriding


    【解决方案1】:

    我找不到任何可以覆盖的 CALayer 的 initWithLayer:(layer) 选择器的等效绑定方法。

    查看 Monotouch 程序集,选择器 initWithLayer 绑定到默认构造函数,如下所示:

    一点术语:public CALayer (CALayer other) 不是默认构造函数 - 默认构造函数没有任何参数。

    但是,我需要能够覆盖 initWithLayer 以便在我的 CALayer 类中为我的自定义属性设置动画。 (正如我之前的问题中指定的,在 Monotouch 中使用 CoreAnimation 为自定义属性设置动画?)

    这个问题并没有说明为什么需要重写 initWithLayer 构造函数。我确实找到了这个:Why animating custom CALayer properties causes other properties to be nil during animation?,这似乎是你想要做的。在这种情况下,我认为有一种更简单的方法可以满足您的需求:您只需覆盖自定义 CALayer 类中的 Clone 方法,并在那里进行适当的初始化。

    这是错误地完成,还是我说不可能覆盖默认构造函数是不正确的?

    从技术上讲,在 C# 中,您不会覆盖构造函数。在您的基类中,您提供自己的构造函数,并且它们都必须调用直接基类中的一个构造函数(在某些情况下,这可能由编译器隐式完成)。

    也就是说,在 MonoTouch 中,你可以在你的类中提供一个构造函数来做你想做的一切(我仍然相信你应该首先尝试克隆方法):

    public MyCALayer : CALayer {
        [Export ("initWithLayer:")]
        public MyCALayer (CALayer other) : base (other)
        {
            // custom initialization here
        }
    
        public override void Clone ()
        {
            // copy any code that you care about here.
        }
    }
    

    【讨论】:

    • 感谢您的详细回复。非常感激。我需要这样做的原因是 CA 框架应该调用 initWithLayer: 在动画期间创建我的图层的副本。我试过使用 Clone() 但它没有调用它。我也尝试过您提供的 Selector 导出代码,但 Selector.sel_registerName() 似乎是私有的,我无法调用它。编译器还声明“SuperHandle”需要非静态引用。我编辑了我的问题以显示我如何更改代码。它会构建,但仍然没有为动画调用 initWithLayer: 方法。 :-(
    • 我不是说你应该调用 Clone,我的意思是你应该在 CircleLayer 中覆盖 Clone,它会在调用 initWithLayer ctor 时被调用(看看你粘贴的第一个代码, this.Clone 在 ctor 中被调用)。
    • 谢谢。即使它仍然不适合我,我想这是我问题的答案,我一定做错了其他事情(我想这是我的另一个问题)。谢谢:-)
    猜你喜欢
    • 2023-03-20
    • 1970-01-01
    • 2017-11-10
    • 1970-01-01
    • 2016-07-23
    • 2011-02-09
    • 2012-06-30
    • 2010-10-30
    • 2014-05-15
    相关资源
    最近更新 更多