CALayer initWithLayer: привязан к конструктору по умолчанию по ошибке? Могу ли я переопределить конструктор по умолчанию? - PullRequest
2 голосов
/ 06 марта 2012

Я не могу найти эквивалентный связанный метод для initWithLayer CALayer: селектор (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.(Как указано в моем предыдущем вопросе Анимировать пользовательское свойство с помощью CoreAnimation в Monotouch? )

Было ли это сделано по ошибке, или я неправильно сказал, что невозможно переопределить конструктор по умолчанию?

В документации Apple указано, что единственное использование initWithLayer - это создание теневых копий, а не инициализация слоя, из-за чего я могу предположить, что это ошибка Monotouch

Документация Apple

initWithLayer: переопределить, чтобы скопировать или инициализировать пользовательские поля указанного слоя.

  • (id) initWithLayer: (id) layer Параметры layer Уровень, с которогонастраиваемые поля должны быть скопированы.Возвращаемое значение Экземпляр слоя с любыми пользовательскими переменными экземпляра, скопированными из слоя.

Обсуждение Этот инициализатор используется для создания теневых копий слоев, например, для метода presentationLayer.

Подклассыможет дополнительно скопировать свои переменные экземпляра в новый объект.

Подклассы всегда должны вызывать реализацию суперкласса

Примечание: вызов этого метода в любой другой ситуации приведет к неопределенному поведению.Не используйте этот метод для инициализации нового слоя с содержимым существующего слоя.Доступность Доступно в iOS 2.0 и более поздних версиях.Объявлено в CALayer.h

EDIT:

Причина, по которой мне нужно переопределить этот метод, заключается в том, что платформа CoreAnimation вызывает этот метод для создания собственной внутренней копии моего слоя.Мне нужно иметь возможность переопределить его, чтобы включить новые свойства, которые я добавил в свой слой, чтобы CoreAnimation знал, как изменять значения моих свойств в ходе анимации.Я не буду называть это сам.Вот почему я не могу просто вызвать Clone ()

Я пытался добавить модификацию в код Рольфа, но он все равно не вызывается:

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

1 Ответ

4 голосов
/ 06 марта 2012

Я не могу найти эквивалентный связанный метод для initWithLayer: селектора (слоя) CALayer, который я могу переопределить.

Глядя на сборку Monotouch, селектор initWithLayer привязан к конструктору по умолчанию следующим образом:

Немного терминологии: public CALayer (CALayer other) не является конструктором по умолчанию - конструктор по умолчанию не имеет параметров.

Однако мне нужно иметь возможность переопределить initWithLayer для того, чтобы анимировать мое пользовательское свойство в моем классе CALayer. (Как указано в моем предыдущем вопросе. Анимируйте пользовательское свойство с помощью CoreAnimation в Monotouch?)

Этот вопрос не говорит, почему вам нужно переопределить конструктор initWithLayer. Однако я обнаружил, что: Почему анимация пользовательских свойств CALayer приводит к тому, что другие свойства становятся равными нулю во время анимации? , что, по-видимому, является тем, что вы пытаетесь сделать. В этом случае я думаю, что есть более простой способ удовлетворить ваши потребности: вам просто нужно переопределить метод Clone в вашем пользовательском классе CALayer и выполнить там правильную инициализацию.

Было ли это сделано по ошибке, или я неверно сказал, что невозможно переопределить конструктор по умолчанию?

Технически, в C # вы не переопределяете конструктор. В вашем базовом классе вы предоставляете свои собственные конструкторы, и все они должны вызывать один конструктор в непосредственном базовом классе (в некоторых случаях это может быть сделано неявно компилятором).

Тем не менее, в MonoTouch вы можете предоставить конструктор в вашем классе, который будет делать все, что вы хотите (я все же считаю, что вы должны сначала попробовать подход Clone):

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.
    }
}
...