Можно ли скопировать 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?
Satyam
1
Итак, если у вас есть определенная комбинация UIView и вы хотите использовать ее несколько раз, вам нужно будет создать подкласс такого UIView?
Anonymous White
Да, подклассы или категории с фабричными методами уровня класса, которые возвращают предварительно настроенные экземпляры этого представления.
Энгин Курутепе
162

это может сработать для вас ... заархивируйте представление, а затем сразу же разархивируйте его. Это должно дать вам полную копию представления:

id copyOfView = 
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:originalView]];
j2emanue
источник
1
Это похоже на хитрость, но работает как мечта. Ответ ssj ниже - это в основном «конструктор копирования», который подходит для небольших классов. Вы можете использовать среду выполнения obj-c, чтобы скопировать все свойства сразу .. Это еще проще;)
Патрик Боркович
1
Это работает, но кажется очень медленным даже для тривиальных деревьев представлений.
Ian Newson
6
Это работает, но будьте осторожны! Он не устанавливает значения для @IBOutlets, все они равны нулю после "копирования"
nalexn
1
Похоже, это игнорирует UIImageViews :(
Юлиан Онофрей
1
Спасибо, отлично работает! ТАКЖЕ обратите внимание, что скопированное представление не имеет супервизора (родителя), ограничений и распознавателей жестов (если они есть у родителя).
Sajjon 01
25

Вы можете сделать расширение UIView. В приведенном ниже примере быстрого фрагмента функция copyView возвращает AnyObject, поэтому вы можете скопировать любой подкласс UIView, то есть UIImageView. Если вы хотите скопировать только UIView, вы можете изменить тип возвращаемого значения на 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
Спасибо, отлично работает! ТАКЖЕ обратите внимание, что скопированное представление не имеет супервизора (родителя), ограничений и распознавателей жестов (если они есть у родителя).
Sajjon 01
6

для swift3.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];
ssj
источник
14
это не ответ на вопрос.
bluefloyd8
1
что, если у вашего ярлыка есть другие специальные параметры, такие как numberOfLines или tag? Вы установите все свойства?
iamirzhan 02