因为对象是引用类型而不是值类型,所以如果设置UIView等于另一个UIView,则视图是同一个对象.如果你修改一个,你也会修改另一个.
我有一个有趣的情况,我想UIView在另一个视图中添加一个子视图,然后我做一些修改,这些修改不应该影响原始UIView.我如何制作副本,UIView以便我可以确保将该副本添加为子视图而不是对原始副本的引用UIView?
请注意,我无法以创建原始的方式重新创建视图,我需要一些方法来创建给定任何UIView对象的副本.
Iva*_*lab 116
你可以制作一个UIView扩展.在下面的示例代码段中,函数copyView返回AnyObject,因此您可以复制UIView的任何子类,即 UIImageView.如果你想复制只的UIView你可以改变返回类型的UIView.
//MARK: - UIView Extensions
extension UIView
{
func copyView<T: UIView>() -> T {
return NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: self)) as! T
}
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
let sourceView = UIView()
let copiedView: UIView = sourceView.copyView()
Run Code Online (Sandbox Code Playgroud)
uli*_*ess 19
你不能随意复制一个对象.只能NSCopying复制实现协议的对象.
但是,有一个解决方法:由于UIViews可以序列化为磁盘(例如,从XIB加载),您可以使用NSKeyedArchiver和NSKeyedUnarchiver创建NSData描述视图的序列化,然后再次反序列化以获得独立但相同的对象.
iOS 12.0更新
自iOS 12.0起不推荐使用方法archivedData(withRootObject:)和unarchivedObject(with:)。
这是使用较新的API(自11.0起)对@Ivan Porcolab的答案的更新,它也变得更加通用以支持其他类型。
extension NSObject {
func copyObject<T:NSObject>() throws -> T? {
let data = try NSKeyedArchiver.archivedData(withRootObject:self, requiringSecureCoding:false)
return try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? T
}
}
Run Code Online (Sandbox Code Playgroud)
这个答案显示了如何做@uliwitness 的建议。也就是说,通过存档然后取消存档来获得相同的对象。(这基本上也是 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
Run Code Online (Sandbox Code Playgroud)
AnyObject。我们过去常常as! UIView将其强制转换为 a,UIView因为我们知道它就是这样。如果我们的视图是 aUITextView那么我们可以输入 cast it as! UITextView。myViewCopy不再有父视图。UIImage. 但是,请参阅此和此答案。更新到 Swift 3.0
| 归档时间: |
|
| 查看次数: |
24167 次 |
| 最近记录: |