在Swift中创build一个UIView的副本
由于对象是引用types,而不是值types,所以如果将UIView
设置为与另一个UIView
相同,则视图是相同的对象。 如果你修改一个,你也会修改其他的。
我有一个有趣的情况,我想添加一个UIView
作为子视图在另一个视图,然后我做了一些修改,这些修改不应该影响原来的UIView
。 我怎样才能做一个UIView
的副本,所以我可以确保我添加副本作为一个子视图,而不是对原始UIView
的引用?
请注意,我不能以创build原始相同的方式重新创build视图,我需要一些方法来创build任何UIView
对象的副本。
您不能任意复制对象。 只有实现NSCopying
协议的NSCopying
才能被复制。
但是,有一个解决方法:因为UIView
可以被序列化到磁盘(例如从XIB加载),您可以使用NSKeyedArchiver
和NSKeyedUnarchiver
创build一个序列化的NSData
描述您的视图,然后反序列化,以获得独立但相同的对象。
你可以做一个UIView扩展。 在下面的示例代码片段中,函数copyView返回一个AnyObject,因此您可以复制UIView的任何子类, 即 UIImageView。 如果只想复制UIView,则可以将返回types更改为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: UIView = sourceView.copyView()
我认为你应该把你的UIView与一个.nib连接起来,然后创build一个新的。
财产将不一样,但你保持外观和方法。
这个答案显示如何做@uliwitnessbuild议。 也就是说,通过归档并取消归档来获得相同的对象。 (这也基本上是Ivan Porkolab在他的回答中所做的,但我认为这是一种更可读的格式。)
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
笔记
- 取消存档数据会创build一个
AnyObject
types的对象。 我们用作as! UIView
as! UIView
types转换回UIView
因为我们知道这是什么。 如果我们的观点是一个UITextView
那么我们可以将其转换as! UITextView
as! UITextView
。 -
myViewCopy
不再有父视图。 - 有些人在使用
UIImage
时提到了一些问题。 但是,看到这个和这个答案。
更新到Swift 3.0
你必须使用模式原型
原型示例:
class ThieveryCorporationPersonDisplay { var name: String? let font: String init(font: String) { self.font = font } func clone() -> ThieveryCorporationPersonDisplay { return ThieveryCorporationPersonDisplay(font:self.font) } }
使用原型的一个例子:
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"
一个额外的解决scheme可能是创build一个新的UIView
,然后复制任何关键的属性。 这在OP的情况下可能不起作用,但对于其他情况可能会起作用。
例如,用UITextView
,可能所有你需要的是框架和属性文本:
let textViewCopy = UITextView(frame: textView.frame) textViewCopy.attributedText = textView.attributedText