¿Se puede copiar UIView?

81

Simplemente usando de esta manera:

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

Esto hará que el simulador no pueda iniciar esta aplicación.

Intenta retener

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

Cualquier modificación view2se aplicará a view1, entiendo que view2comparten la misma memoria con view1.

¿Por qué no se UIViewpuede copiar? ¿Cuál es la razón?

Para descanso
fuente

Respuestas:

33

Tu aplicación probablemente se bloquee con algo como:

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

La razón es que UIView no implementa el protocolo de copia y, por lo tanto, no hay ningún copyWithZoneselector en UIView.

Engin Kurutepe
fuente
10
¿Qué debo hacer para implementar la copia de UIView?
Satyam
1
Entonces, si tiene una cierta combinación de UIView y desea usarla varias veces, necesitará subclasificar tal UIView.
Anonymous White
Sí, subclasificación o categoría con métodos de fábrica a nivel de clase que devuelven instancias preconfiguradas de esa vista.
Engin Kurutepe
162

esto podría funcionar para usted ... archive la vista y luego desarchive inmediatamente después. Esto debería darle una copia profunda de una vista:

id copyOfView = 
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:originalView]];
j2emanue
fuente
1
Eso parece un truco pero funciona como un sueño. La respuesta de ssj a continuación es básicamente un 'constructor de copias' que está bien para clases pequeñas. Quizás pueda usar el tiempo de ejecución de obj-c para copiar todas las propiedades a la vez. Esto es aún más fácil;)
Patrick Borkowicz
1
Esto funciona, pero parece ser muy lento incluso para árboles de vista triviales.
Ian Newson
6
Funciona, ¡pero cuidado! No establece valores para @IBOutlets, todos ellos son nulos después de "copiar"
nalexn
1
Esto parece ignorar UIImageViews :(
Iulian Onofrei
1
¡Gracias, funciona muy bien! TAMBIÉN tenga en cuenta que la vista copiada no tiene supervista (padre), ni restricciones ni reconocedores de gestos (si el padre tenía alguno).
Sajjon
25

Puede crear una extensión UIView. En el siguiente fragmento de código rápido de ejemplo, la función copyView devuelve un objeto AnyObject para que pueda copiar cualquier subclase de un UIView, es decir , UIImageView. Si desea copiar solo UIViews, puede cambiar el tipo de retorno a UIView.

//MARK: - UIView Extensions

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

Uso de ejemplo:

let sourceView = UIView()
let copiedView = sourceView.copyView()
Ivan Porkolab
fuente
1
¡Gracias, funciona muy bien! TAMBIÉN tenga en cuenta que la vista copiada no tiene supervista (padre), ni restricciones ni reconocedores de gestos (si el padre tenía alguno).
Sajjon
6

para swift3.0.1:

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

UIViewno implementa el NSCopingprotocolo, vea la declaración en UIView.h :

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

Entonces, si queremos tener un copymétodo similar, necesitamos implementar el NSCopingprotocolo en una categoría más o menos.

HongchaoZhang
fuente
-6

Puedes hacer que el método sea algo como esto:

-(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];

}

Luego puede establecer su ivar en el valor de retorno y retenerlo así:

myLabel = [[self copyLabelFrom:myOtherLabel] retain];
ssj
fuente
14
esto no responde a la pregunta.
bluefloyd8
1
¿Qué pasa si su etiqueta tiene otros parámetros personalizados como numberOfLines o tag? ¿Establecerás todas las propiedades?
iamirzhan