Because objects are reference types, not value types, if you set a UIView
equal to another UIView
, the views are the same object. If you modify one
You can't arbitrarily copy an object. Only objects that implement the NSCopying
protocol can be copied.
However, there is a workaround: Since UIView
s can be serialized to disk (e.g. to load from a XIB), you could use NSKeyedArchiver
and NSKeyedUnarchiver
to create a serialized NSData
describing your view, then de-serialize that again to get an independent but identical object.
You can make an UIView extension. In example snippet below, function copyView returns an AnyObject so you could copy any subclass of an UIView, ie UIImageView. If you want to copy only UIView you can change the return type to UIView.
//MARK: - UIView Extensions
extension UIView
{
func copyView<T: UIView>() -> T {
return NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: self)) as! T
}
}
Example usage:
let sourceView = UIView()
let copiedView: UIView = sourceView.copyView()
This answer shows how to do what @uliwitness suggested. That is, get an identical object by archiving it and then unarchiving it. (It is also basically what Ivan Porkolab did in his answer, but in a more readable format, I think.)
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
AnyObject
. We used as! UIView
to type cast it back to a UIView
since we know that's what it is. If our view were a UITextView
then we could type cast it as! UITextView
.myViewCopy
no longer has a parent view.UIImage
. However, see this and this answer.Updated to Swift 3.0
Additionally you can use this pattern to copy View controller view
let vc = UIViewController()
let anotherVc = UIViewController()
vc.view = anotherVc.copyView()
You may need this for caching view controller or cloning.
I think that you should link you UIView with a .nib and just create a new one.
Property will not be the same, but you keep appearance and methods.
An addition solution could be to just create a new UIView
and then copy over any critical properties. This may not work in the OP's case, but it could very well work for other cases.
For example, with a UITextView
, probably all you would need is the frame and attributed text:
let textViewCopy = UITextView(frame: textView.frame)
textViewCopy.attributedText = textView.attributedText