因为对象是引用类型而不是值类型,所以如果将UIView
设置为等于另一个UIView
,则视图是同一个对象。如果你修改了一个,你也可以修改另一个。
我有一个有趣的情况,我想在另一个视图中添加UIView
作为子视图,然后我做了一些修改,这些修改不应该影响原始的UIView
。如何制作UIView
的副本,以便我可以确保将该副本添加为子视图而不是对原始UIView
的引用?
请注意,我无法像创建原始文件一样重新创建视图,我需要一些方法来创建给定任何UIView
对象的副本。
答案 0 :(得分:105)
您可以制作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
}
}
使用示例:
let sourceView = UIView()
let copiedView: UIView = sourceView.copyView()
答案 1 :(得分:16)
您无法任意复制对象。只能复制实现NSCopying
协议的对象。
但是,有一种解决方法:由于UIView
可以序列化为磁盘(例如从XIB加载),因此可以使用NSKeyedArchiver
和NSKeyedUnarchiver
来创建序列化{ {1}}描述您的视图,然后再次反序列化以获得一个独立但相同的对象。
答案 2 :(得分:5)
iOS 12.0更新
从iOS 12.0开始不推荐使用方法archivedData(withRootObject:)
和unarchivedObject(with:)
。
这是@Ivan Porcolab使用较新API(自11.0起)的答案的更新,它也变得更加通用以支持其他类型。
extension NSObject {
func copyObject<T:NSObject>() throws -> T? {
let data = try NSKeyedArchiver.archivedData(withRootObject:self, requiringSecureCoding:false)
return try NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? T
}
}
答案 3 :(得分:4)
我认为您应该将UIView与.nib链接起来,然后创建一个新的。
属性不一样,但你保持外观和方法。
答案 4 :(得分:4)
这个答案显示了如何做@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
AnyObject
类型的对象。我们使用as! UIView
键入将其强制转换回UIView
,因为我们知道它是什么。如果我们的观点是UITextView
,那么我们可以输入它as! UITextView
。myViewCopy
不再有父视图。UIImage
时提到了一些问题。不过,请参阅this和this回答。已更新至Swift 3.0
答案 5 :(得分:1)
您必须使用模式原型
原型示例:
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"
答案 6 :(得分:0)
添加解决方案可能只是创建一个新的UIView
,然后复制任何关键属性。这可能不适用于OP的情况,但它可以很好地适用于其他情况。
例如,使用UITextView
,您可能只需要框架和属性文字:
let textViewCopy = UITextView(frame: textView.frame)
textViewCopy.attributedText = textView.attributedText
答案 7 :(得分:-1)
此外,您可以使用此模式复制View controller视图
let vc = UIViewController()
let anotherVc = UIViewController()
vc.view = anotherVc.copyView()
您可能需要使用它来缓存视图控制器或克隆。