Чи можна скопіювати UIView?


81

Просто використовуючи такий спосіб:

UIView* view2 = [view1 copy]; // view1 existed

Це призведе до того, що симулятор не зможе запустити цю програму.

Спробуйте зберегти,

UIView* view2 = [view1 retain]; // view1 existed
// modify view2 frame etc

Будь-які зміни, view2які стосуватимуться, стосуються view1, я розумію, view2спільного використання тієї ж пам'яті view1.

Чому не UIViewможна скопіювати? В чому причина?

Відповіді:


33

Ваш додаток, ймовірно, аварійно завершує роботу, наприклад:

 [UIView copyWithZone:]: unrecognized selector sent to instance 0x1c6280

Причина полягає в тому, що UIView не реалізує протокол копіювання, і тому copyWithZoneв UIView немає селектора.


10
Що мені робити, щоб застосувати копію UIView?
Сатьям,

1
Отже, якщо у вас є певна комбінація UIView і ви хочете використовувати її кілька разів, вам доведеться підкласувати такий UIView?
Anonymous White

Так, підклас або категорія із заводськими методами рівня класу, які повертають попередньо налаштовані екземпляри цього подання.
Engin Kurutepe

162

це може працювати для вас ... заархівуйте подання, а потім архівуйте його відразу після. Це має дати вам глибоку копію подання:

id copyOfView = 
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:originalView]];

1
Це, здається, трохи зламати, але працює як мрія. Відповідь ssj нижче - це, в основному, "конструктор копіювання", що добре для невеликих класів. Можливо, ви можете скористатися середовищем виконання obj-c для копіювання всіх властивостей одночасно .. Це все ще простіше;)
Патрік Боркович,

1
Це працює, але, здається, дуже повільно навіть для тривіальних дерев огляду.
Ян Ньюсон

6
Це працює, але будьте обережні! Він не встановлює значень для @IBOutlets, всі вони дорівнюють нулю після "копіювання"
nalexn

1
Здається, це ігнорує UIImageViews :(
Юліан Онофрей

1
Дякую, чудово працює! ТАКЖЕ, будь ласка, зверніть увагу, що скопійований подання не має суперперегляду (батьківського), обмежень та розпізнавачів жестів (якщо батько мав такі).
Саджон

25

Ви можете зробити розширення UIView. У прикладі швидкого фрагмента нижче, функція copyView повертає AnyObject, щоб ви могли скопіювати будь-який підклас UIView, тобто UIImageView. Якщо ви хочете скопіювати лише UIViews, ви можете змінити тип повернення на UIView.

//MARK: - UIView Extensions

    extension UIView
    {
       func copyView<T: UIView>() -> T {
            return NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: self)) as! T
       }
    }

Приклад використання:

let sourceView = UIView()
let copiedView = sourceView.copyView()

1
Дякую, чудово працює! ТАКЖЕ, будь ласка, зверніть увагу, що скопійований подання не має суперперегляду (батьківського), обмежень та розпізнавачів жестів (якщо батько мав такі).
Саджон

6

для швидкого3.0.1:

extension UIView{
 func copyView() -> AnyObject{
    return NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: self))! as AnyObject
 }
}

1

UIViewне реалізує NSCopingпротокол, див. декларацію в UIView.h :

@interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusEnvironment>

Отже, якщо ми хочемо мати copyподібний метод, нам потрібно реалізувати NSCopingпротокол у категорії або близько того.


-6

Ви можете зробити метод приблизно таким:

-(UILabel*)copyLabelFrom:(UILabel*)label{
//add whatever needs to be copied
UILabel *newLabel = [[UILabel alloc]initWithFrame:label.frame];
newLabel.backgroundColor = label.backgroundColor;
newLabel.textColor = label.textColor;
newLabel.textAlignment = label.textAlignment;
newLabel.text = label.text;
newLabel.font = label.font;

return [newLabel autorelease];

}

Тоді ви можете встановити для ivar значення, яке повертається, і зберегти його таким чином:

myLabel = [[self copyLabelFrom:myOtherLabel] retain];

14
це не відповідає на питання.
bluefloyd8,

1
а якщо ваша мітка має інші користувацькі параметри, такі як numberOfLines або тег? Ви встановите всі властивості?
Яміржан,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.