可以复制UIView吗?


81

只需使用这种方式:

UIView* view2 = [view1 copy]; // view1 existed

这将导致模拟器无法启动此应用。

尝试保留,

UIView* view2 = [view1 retain]; // view1 existed
// modify view2 frame etc

对的任何修改view2将适用于view1我理解与view2共享相同的记忆view1

为什么不能UIView复制?是什么原因?

Answers:


33

您的应用可能会崩溃,并显示以下内容:

 [UIView copyWithZone:]: unrecognized selector sent to instance 0x1c6280

原因是UIView没有实现复制协议,因此copyWithZoneUIView中没有选择器。


10
我应该怎么做才能实现UIView的副本?
萨蒂扬2012年

1
因此,如果您具有一定的UIView组合并且要多次使用,则需要继承此类UIView?
匿名白人

是的,带有类级工厂方法的子类或类别可返回该视图的预配置实例。
Engin Kurutepe 2012年

162

这可能对您有用...将视图存档,然后立即取消存档。这应该给您一个视图的深层副本:

id copyOfView = 
[NSKeyedUnarchiver unarchiveObjectWithData:[NSKeyedArchiver archivedDataWithRootObject:originalView]];

1
这似乎有点破烂,但就像梦一样。ssj的答案基本上是一个“复制构造函数”,适用于小型类。您也许可以使用obj-c运行时一次复制所有属性。.这仍然更容易;)
Patrick Borkowicz 2012年

1
这是可行的,但是对于琐碎的视图树来说似乎非常慢。
伊恩·纽森

6
它有效,但是要当心!它不会为@IBOutlets设置值,所有这些值在“复制”后均为零
nalexn 2014年

1
这似乎忽略了UIImageViews :(
Iulian Onofrei

1
谢谢,效果很好!还请注意,复制的视图没有父视图(父视图),没有约束,也没有手势识别器(如果父视图有)。
Sajjon

25

您可以进行UIView扩展。在下面的示例快速代码段中,函数copyView返回一个AnyObject,因此您可以复制UIView的任何子类,UIImageView。如果你想复制UIViews你可以改变返回类型的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 = sourceView.copyView()

1
谢谢,效果很好!还请注意,复制的视图没有父视图(父视图),没有约束,也没有手势识别器(如果父视图有)。
Sajjon

6

对于swift3.0.1:

extension UIView{
 func copyView() -> AnyObject{
    return NSKeyedUnarchiver.unarchiveObject(with: NSKeyedArchiver.archivedData(withRootObject: self))! as AnyObject
 }
}

1

UIView没有实现NSCoping协议,请参见UIView.h中的声明:

@interface UIView : UIResponder <NSCoding, UIAppearance, UIAppearanceContainer, UIDynamicItem, UITraitEnvironment, UICoordinateSpace, UIFocusEnvironment>

因此,如果我们想要一个copy类似的方法,就需要NSCoping在一个类别中实现该协议。


-6

您可以使方法如下所示:

-(UILabel*)copyLabelFrom:(UILabel*)label{
//add whatever needs to be copied
UILabel *newLabel = [[UILabel alloc]initWithFrame:label.frame];
newLabel.backgroundColor = label.backgroundColor;
newLabel.textColor = label.textColor;
newLabel.textAlignment = label.textAlignment;
newLabel.text = label.text;
newLabel.font = label.font;

return [newLabel autorelease];

}

然后,您可以将ivar设置为返回值,并像这样保留它:

myLabel = [[self copyLabelFrom:myOtherLabel] retain];

14
这没有回答问题。
bluefloyd13年

1
如果您的标签具有其他自定义参数(例如numberOfLines或tag)怎么办?您会设置所有属性吗?
iamirzhan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.