从 NSPasteBoard 存储和检索自定义 object
Storing and retrieving a custom object from NSPasteBoard
我有一个属于这个 class 的 object,其中包含以下声明:
HEADER
@interface MyClassObject : NSObject <NSCopying, NSPasteboardWriting, NSPasteboardReading>
@property (nonatomic, strong) NSArray *children;
@property (nonatomic, assign) NSInteger type;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) id node;
children
包含此 class 的其他 object,node
包含可以是 NSView
或 [=15 的 object =].
我希望能够复制并粘贴 object 这种类型 to/from NSPasteboard
。
我身边有 google 但解释很模糊。
我应该怎么做才能使这个 class copiable/readable 成为 NSPasteboard 或者换句话说,使其符合 NSPasteboardWriting
和 NSPasteboardReading
协议?
我完全不知道这是如何完成的,而且和往常一样,Apple 文档和任何东西都不是一回事。
我只讨论写作。阅读基本上是一样的(但当然是相反的;))
写
声明你写的类型
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard {
return @[@"com.mycompany.mytype"];
}
写入数据
- (id)pasteboardPropertyListForType:(NSString *)type {
//check the type we are asked to write
if(![type isEqualToString:@"com.mycompany.mytype"]) return nil;
//create a _plist_ object
// :: ONLY PLIST TYPES
NSMutableDictionary *plist = [[NSMutableDictionary alloc] init];
...
return plist;
}
这是完整的解决方案。
首先是让 class 也符合 NSCoding
。在这种情况下,class 声明将是
@interface MyClassObject : NSObject <NSCopying, NSPasteboardWriting, NSPasteboardReading, NSCoding>
要使其与 NSCoding
兼容,您必须实施 encodeWithCoder:
和 initWithCoder:
... 在我的例子中:
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:@(self.type) forKey:@"type"];
[coder encodeObject:self.name forKey:@"name"];
// converting the node to NSData...
// the object contained in node must be compatible with NSCoding
NSData *nodeData = [NSKeyedArchiver archivedDataWithRootObject:self.node];
[coder encodeObject:nodeData forKey:@"node"];
NSData *childrenData = [NSKeyedArchiver archivedDataWithRootObject:self.children];
[coder encodeObject:childrenData forKey:@"children"];
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
_type = [[coder decodeObjectForKey:@"type"] integerValue];
_name = [coder decodeObjectForKey:@"name"];
NSData *nodeData = [coder decodeObjectForKey:@"node"];
_efeito = [NSKeyedUnarchiver unarchiveObjectWithData:nodeData];
NSData *childrenData = [coder decodeObjectForKey:@"children"];
_children = [NSKeyedUnarchiver unarchiveObjectWithData:childrenData];
_parent = nil; // I want this to be nil when the object is recreated
}
要使 class 与 NSPasteboard 一起工作,您必须添加这 4 个方法:
-(id)initWithPasteboardPropertyList:(id)propertyList ofType:(NSString *)type {
return [NSKeyedUnarchiver unarchiveObjectWithData:propertyList];
}
+(NSArray *)readableTypesForPasteboard:(NSPasteboard *)pasteboard {
// I am using the bundleID as a type
return @[[[NSBundle mainBundle] bundleIdentifier]];
}
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard {
// I am using the bundleID as a type
return @[[[NSBundle mainBundle] bundleIdentifier]];
}
- (id)pasteboardPropertyListForType:(NSString *)type {
// I am using the bundleID as a type
if(![type isEqualToString:[[NSBundle mainBundle] bundleIdentifier]]) {
return nil;
}
return [NSKeyedArchiver archivedDataWithRootObject:self];
}
然后,在 class 上执行您添加的复制和粘贴:
- (void)copy:(id)sender {
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
[pasteBoard clearContents];
NSArray *copiedObjects = @[theObjectYouWantToCopyToThePasteboard];
[pasteBoard writeObjects:copiedObjects];
}
- (void)paste:sender {
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = @[[LayerObject class]];
NSDictionary *options = [NSDictionary dictionary];
BOOL ok = [pasteboard canReadItemWithDataConformingToTypes:@[[[NSBundle mainBundle] bundleIdentifier]]];
if (ok) {
NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
MyObjectClass *object = [objectsToPaste objectAtIndex:0];
// object is the one you have copied to the pasteboard
// now you can do whatever you want with it.
// add the code here.
}
}
我有一个属于这个 class 的 object,其中包含以下声明:
HEADER
@interface MyClassObject : NSObject <NSCopying, NSPasteboardWriting, NSPasteboardReading>
@property (nonatomic, strong) NSArray *children;
@property (nonatomic, assign) NSInteger type;
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) id node;
children
包含此 class 的其他 object,node
包含可以是 NSView
或 [=15 的 object =].
我希望能够复制并粘贴 object 这种类型 to/from NSPasteboard
。
我身边有 google 但解释很模糊。
我应该怎么做才能使这个 class copiable/readable 成为 NSPasteboard 或者换句话说,使其符合 NSPasteboardWriting
和 NSPasteboardReading
协议?
我完全不知道这是如何完成的,而且和往常一样,Apple 文档和任何东西都不是一回事。
我只讨论写作。阅读基本上是一样的(但当然是相反的;))
写
声明你写的类型
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard { return @[@"com.mycompany.mytype"]; }
写入数据
- (id)pasteboardPropertyListForType:(NSString *)type { //check the type we are asked to write if(![type isEqualToString:@"com.mycompany.mytype"]) return nil; //create a _plist_ object // :: ONLY PLIST TYPES NSMutableDictionary *plist = [[NSMutableDictionary alloc] init]; ... return plist; }
这是完整的解决方案。
首先是让 class 也符合 NSCoding
。在这种情况下,class 声明将是
@interface MyClassObject : NSObject <NSCopying, NSPasteboardWriting, NSPasteboardReading, NSCoding>
要使其与 NSCoding
兼容,您必须实施 encodeWithCoder:
和 initWithCoder:
... 在我的例子中:
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:@(self.type) forKey:@"type"];
[coder encodeObject:self.name forKey:@"name"];
// converting the node to NSData...
// the object contained in node must be compatible with NSCoding
NSData *nodeData = [NSKeyedArchiver archivedDataWithRootObject:self.node];
[coder encodeObject:nodeData forKey:@"node"];
NSData *childrenData = [NSKeyedArchiver archivedDataWithRootObject:self.children];
[coder encodeObject:childrenData forKey:@"children"];
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
_type = [[coder decodeObjectForKey:@"type"] integerValue];
_name = [coder decodeObjectForKey:@"name"];
NSData *nodeData = [coder decodeObjectForKey:@"node"];
_efeito = [NSKeyedUnarchiver unarchiveObjectWithData:nodeData];
NSData *childrenData = [coder decodeObjectForKey:@"children"];
_children = [NSKeyedUnarchiver unarchiveObjectWithData:childrenData];
_parent = nil; // I want this to be nil when the object is recreated
}
要使 class 与 NSPasteboard 一起工作,您必须添加这 4 个方法:
-(id)initWithPasteboardPropertyList:(id)propertyList ofType:(NSString *)type {
return [NSKeyedUnarchiver unarchiveObjectWithData:propertyList];
}
+(NSArray *)readableTypesForPasteboard:(NSPasteboard *)pasteboard {
// I am using the bundleID as a type
return @[[[NSBundle mainBundle] bundleIdentifier]];
}
- (NSArray *)writableTypesForPasteboard:(NSPasteboard *)pasteboard {
// I am using the bundleID as a type
return @[[[NSBundle mainBundle] bundleIdentifier]];
}
- (id)pasteboardPropertyListForType:(NSString *)type {
// I am using the bundleID as a type
if(![type isEqualToString:[[NSBundle mainBundle] bundleIdentifier]]) {
return nil;
}
return [NSKeyedArchiver archivedDataWithRootObject:self];
}
然后,在 class 上执行您添加的复制和粘贴:
- (void)copy:(id)sender {
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
[pasteBoard clearContents];
NSArray *copiedObjects = @[theObjectYouWantToCopyToThePasteboard];
[pasteBoard writeObjects:copiedObjects];
}
- (void)paste:sender {
NSPasteboard *pasteboard = [NSPasteboard generalPasteboard];
NSArray *classArray = @[[LayerObject class]];
NSDictionary *options = [NSDictionary dictionary];
BOOL ok = [pasteboard canReadItemWithDataConformingToTypes:@[[[NSBundle mainBundle] bundleIdentifier]]];
if (ok) {
NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options];
MyObjectClass *object = [objectsToPaste objectAtIndex:0];
// object is the one you have copied to the pasteboard
// now you can do whatever you want with it.
// add the code here.
}
}