Как сделать копию для UILabel?

У меня IBOutlet UILabel *label;

и я хочу сделать это

UILabel *label = [titleLabel copy];
label.text = @"Clone";
titleLabel.text = @"Original";
NSLog(@"label : %@, title : %@",label.text,titleLabel.text);

и это исключение исключения

* Завершение приложения из-за неперехваченного исключения "NSInvalidArgumentException", причина: '- [UILabel copyWithZone:]: нераспознанный селектор, отправленный в экземпляр 0x6a4a450' * Первый стек вызовов броска: (0x126f052 0x1823d0a 0x1270ced 0x11d5f00 0x11d5ce2 0x1271bd9 0x2ed6 0x1270e1a 0x2851 0x28264e 0x1e2a73 0x1e2ce2 0x1e2ea8 0x1e9d9a 0x24af 0x1ba9d6 0x1bb8a6 0x1ca743 0x1cb1f8 0x1beaa9 0x215cfa9 0x12431c5 0x11a8022 0x11a690a 0x11a5db4 0x11a5ccb 0x1bb2a7 0x1bca9b 0x21c2 0x2135)

Ответ 1

Нет публичного API Apple для глубокой копии UILabel. Лучше всего сделать вспомогательный метод, который скопирует все детали, о которых вы заботитесь.

- (UILabel *)deepLabelCopy:(UILabel *)label {
    UILabel *duplicateLabel = [[UILabel alloc] initWithFrame:label.frame];
    duplicateLabel.text = label.text;
    duplicateLabel.textColor = label.textColor;
    // etc... anything else which is important to your ULabel

    return [duplicateLabel autorelease];
}

Если вы хотите использовать его по всей базе кода, вы можете изменить его на статический метод и поместить его в какой-то класс полезности. Если вы назвали класс LabelUtils, вы могли бы сделать что-то вроде...

+ (UILabel *)deepLabelCopy(UILabel *)label {
    // ...
}

и вызывается с помощью UILabel *dupLabel = [LabelUtils deepLabelCopy:origLabel];

Ответ 2

Я рекомендую использовать объединенную версию ответа 1 и ответа 2:

- (UILabel *)copyLabel:(UILabel *)label {
    NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject: label];
    UILabel* copy = [NSKeyedUnarchiver unarchiveObjectWithData: archivedData];
    return copy;
}

Затем просто используйте что-то вроде

UILabel* labelcopy = [self copyLabel:originalLabel];

в вашем коде.

Ответ 3

UILabel не соответствует NSCopying, поэтому вы не можете сделать копию через -copy.

Но он соответствует NSCoding, поэтому вы можете архивировать текущий экземпляр, а затем разблокировать "копию".

NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject: label];
UILabel *labelCopy =   [NSKeyedUnarchiver unarchiveObjectWithData: archivedData];

Затем вам нужно будет назначить любые дополнительные свойства, которые не были перенесены в архив (например, делегат) по мере необходимости.

Ответ 4

Решение Swift 3

Я создал его как расширение для UILabel.

extension UILabel {
    func createCopy() -> UILabel {
        let archivedData = NSKeyedArchiver.archivedData(withRootObject: self)
        return NSKeyedUnarchiver.unarchiveObject(with: archivedData) as! UILabel
    }
}

Как использовать

let anotherNameLabel = nameLabel.createCopy()

Дополнительная информация - Как это работает?

NSKeyedArchiver возьмет объект из памяти и преобразует его в текст. "Keyed" означает, что он использует слова для описания свойств этого объекта, таких как "LabelFrame", "LabelText" и т.д. (Это поддельные ключи.) Это также называется сериализацией в других технологиях.

NSKeyedUnarchiver делает обратное. Он примет этот текст и построит объект. Здесь мы берем этот объект (Any?) и преобразуем его в UILabel.

Ответ 5

Я решил это таким образом и хотел опубликовать его для легкого копирования и вставки, если вы думаете делать то же самое.

func makeCopy() -> UILabel {

  let label = UILabel(frame: frame)
  label.text = text
  label.font = font
  label.textColor = textColor
  label.shadowColor = shadowColor
  label.shadowOffset = shadowOffset
  label.textAlignment = textAlignment
  label.lineBreakMode = lineBreakMode
  label.attributedText = attributedText
  label.highlightedTextColor = highlightedTextColor
  label.isHighlighted = isHighlighted
  label.isUserInteractionEnabled = isUserInteractionEnabled
  label.isEnabled = isEnabled
  label.numberOfLines = numberOfLines
  label.adjustsFontSizeToFitWidth = adjustsFontSizeToFitWidth
  label.baselineAdjustment = baselineAdjustment
  label.minimumScaleFactor = minimumScaleFactor
  label.allowsDefaultTighteningForTruncation = allowsDefaultTighteningForTruncation
  label.preferredMaxLayoutWidth = preferredMaxLayoutWidth

  return label
}