I can't see any way to copy an NSView and create an identical NSView object. I see google hits about "use an NSData" but I don't understand that.
2 Answers
To straight up "copy" an NSView, the view has to implement the NSCopying
protocol. Unfortunately, NSView does not.
Fortunately, it does implement the NSCoding
protocol, which means we can still duplicate a view like:
NSData * archivedView = [NSKeyedArchiver archivedDataWithRootObject:myView];
NSView * myViewCopy = [NSKeyedUnarchiver unarchiveObjectWithData:archivedView];
And voilá! You now have a duplicate of myView
.
Edit: (Swift version)
let archivedView = NSKeyedArchiver.archivedData(withRootObject: myView)
let myViewCopy = NSKeyedUnarchiver.unarchiveObject(with: archivedView)
(archivedView
is of type Data
, not NSData
)

- 8,217
- 1
- 37
- 43

- 242,470
- 58
- 448
- 498
-
4Note that if you subclass, you'll need to implement archiving support. The docs know all. – bbum Jun 24 '10 at 07:25
-
In every case that I subclass - even when I don't have data added but only a couple methods? – Nektarios Jun 24 '10 at 16:09
-
Nektarios: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmImplementCopy.html – Peter Hosey Jun 25 '10 at 07:59
-
Lifesaver. I waded through a few results in Google and confusion until I found this answer. Thanks! – John Gallagher Jun 02 '11 at 14:10
-
Unarchiving doesn't work for me when using an NSTextField. It throws the error `"This decoder will only decode classes that adopt NSSecureCoding. Class 'NSTextField' does not adopt it."`. I can't for the life of me figure our a way around this. – Noah Nuebling Jul 25 '21 at 19:13
-
I found a solution! See my answer to this question. – Noah Nuebling Jul 25 '21 at 21:09
Since around iOS 12 / macOS 14, the accepted answer by @Dave DeLong
doesn't work anymore in all cases.
The problem is, that some of the methods which were used in @Dave DeLong
s solution don't work anymore for objects that only adhere to the NSCoding
protocol but not the NSSecureCoding
protocol.
Solution
Luckily, there's still a solution that works for copying any Object that adheres to NSCoding
(and not only ones that adhere to NSSecureCoding
) even on the newest operating systems!
There are a few changes in this solution compared to the old one. Most importantly, you'll have to create an instance of NSKeyedUnarchiver
instead of using the more convenient class methods. The convenient class methods only support NSSecureCoding
but not NSCoding
in the newer operating systems.
My implementation looks like this:
public func insecureCopy<T: NSCoding>(of original: T) throws -> T {
/// See https://developer.apple.com/forums/thread/107533
if #available(macOS 10.13, *) {
let data = try NSKeyedArchiver.archivedData(withRootObject: original, requiringSecureCoding: false)
let unarchiver = try NSKeyedUnarchiver(forReadingFrom: data)
unarchiver.requiresSecureCoding = false
let copy = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as! T
return copy
} else { /// Fallback (untested)
let data = NSKeyedArchiver.archivedData(withRootObject: original)
let unarchiver = NSKeyedUnarchiver(forReadingWith: data)
unarchiver.requiresSecureCoding = false
let copy = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as! T
return copy
}
}
Notes
- The source for this solution was from
@eskimo
s great answer on this Apple Dev Forum Post: https://developer.apple.com/forums/thread/107533
as well as the WWDC session video that they linked to. - The method is called
insecureCopy()
because it works on non-secure coding objects. But, as far as I understand, this method is not in fact insecure. Working with non-secure NSCoding objects is only insecure if you save and load insecure archives to and from a file as far as I understand. Not if you just use the archives for copying like in this case. - The fallback code for macOS 10.13 and earlier is not tested.

- 219
- 2
- 11