Crea una copy de una UIView en Swift

Como los objects son types de reference, no types de valor, si configura una UIView igual a otra UIView , las vistas son el mismo object. Si modifica uno, también modificará el otro.

Tengo una situación interesante en la que me gustaría agregar una UIView como una subvista en otra vista, luego hago algunas modificaciones, y esas modificaciones no deberían afectar la UIView original. ¿Cómo puedo hacer una copy de UIView para asegurarme de agregar esa copy como una subvista en lugar de una reference a la UIView original?

Tenga en count que no puedo volver a crear la vista de la misma manera que se creó el original, necesito alguna forma de crear una copy dada cualquier object UIView .

No puede copyr arbitrariamente un object. Solo se pueden copyr los objects que implementan el protocolo NSCopying .

Sin embargo, hay una solución: dado que UIView s puede ser serializado en el disco (por ejemplo, para cargar desde un XIB), puede usar NSKeyedArchiver y NSKeyedUnarchiver para crear un NSData serializado que describa su vista, luego des-serializarlo nuevamente para get un NSData independiente pero object idéntico

Puede hacer una extensión UIView. En el fragment de ejemplo a continuación, la function copyView devuelve un AnyObject para que pueda copyr cualquier subclass de una UIView, es decir , UIImageView. Si desea copyr solo UIView, 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 } } 

Ejemplo de uso:

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

Creo que deberías vincularte UIView con un .nib y solo crear uno nuevo.

La propiedad no será la misma, pero mantendrá apariencia y methods.

Esta respuesta muestra cómo hacer lo que @uliwitness sugirió. Es decir, get un object idéntico archivándolo y luego desarchándolo. (También es básicamente lo que hizo Ivan Porkolab en su respuesta, pero en un formatting más legible, creo.)

 let myView = UIView() // create an NSData object from myView let archive = NSKeyedArchiver.archivedData(withRootObject: myView) // create a clone by unarchiving the NSData let myViewCopy = NSKeyedUnarchiver.unarchiveObject(with: archive) as! UIView 

Notas

  • Desarchivar los datos crea un object de tipo AnyObject . ¡Usamos as! UIView as! UIView para escribir la vuelta a una UIView ya que sabemos que es lo que es. Si nuestra vista fuera una UITextView entonces podríamos escribirla as! UITextView as! UITextView .
  • El myViewCopy ya no tiene una vista principal.
  • Algunas personas mencionan algunos problemas al trabajar con UIImage . Sin embargo, vea esto y esta respuesta.

Actualizado a Swift 3.0

Debes usar el patrón Prototype.

Ejemplo del prototipo:

 class ThieveryCorporationPersonDisplay { var name: String? let font: String init(font: String) { self.font = font } func clone() -> ThieveryCorporationPersonDisplay { return ThieveryCorporationPersonDisplay(font:self.font) } } 

Un ejemplo de uso de prototipo:

 let Prototype = ThieveryCorporationPersonDisplay(font:"Ubuntu") let Philippe = Prototype.clone() Philippe.name = "Philippe" let Christoph = Prototype.clone() Christoph.name = "Christoph" let Eduardo = Prototype.clone() Eduardo.name = "Eduardo" 

Una solución adicional podría ser simplemente crear una nueva UIView y luego copyr sobre cualquier propiedad crítica. Esto puede no funcionar en el caso de los OP, pero podría funcionar para otros casos.

Por ejemplo, con un UITextView , probablemente todo lo que necesitará es el marco y el text atribuido:

 let textViewCopy = UITextView(frame: textView.frame) textViewCopy.attributedText = textView.attributedText