Чи можна скопіювати 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.