Create a copy of a UIView in Swift

后端 未结 7 1844
长发绾君心
长发绾君心 2020-11-29 05:01

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

相关标签:
7条回答
  • 2020-11-29 05:24

    You can't arbitrarily copy an object. Only objects that implement the NSCopying protocol can be copied.

    However, there is a workaround: Since UIViews 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.

    0 讨论(0)
  • 2020-11-29 05:24

    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()
    
    0 讨论(0)
  • 2020-11-29 05:25

    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
    

    Notes

    • Unarchiving the data creates an object of type 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.
    • The myViewCopy no longer has a parent view.
    • Some people mention some problems when working with UIImage. However, see this and this answer.

    Updated to Swift 3.0

    0 讨论(0)
  • 2020-11-29 05:29

    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.

    0 讨论(0)
  • 2020-11-29 05:33

    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.

    0 讨论(0)
  • 2020-11-29 05:46

    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 
    
    0 讨论(0)
提交回复
热议问题