Cocoa 如何显示未归档的自定义NSView对象
我正在学习Cocoa编程,但我不知道如何 存档和取消存档自定义NSView子类 我制作了一个玩具应用程序,它显示一个窗口。这扇窗户 包含自定义BackgroundView类的实例(存档在 xib文件)。单击此背景视图中的任意位置可创建和 显示一个以单击点为原点的蓝色正方形。这个广场是 我的Square类的一个实例。所有这些都像我预期的那样有效 Square类实现NSCoding协议。我补充说 dataOfType:typeName:error:和readfromData:ofType:error:methods 到MyDocument类。从日志语句中可以看出 正方形被归档到文件中,而当文件 已加载。但是我不能让正方形在屏幕上显示出来 窗户。Square类的drawWithRect:方法从未被调用, 尽管我已经调用了setneeds,但在每个方块上显示:是 代码如下:Cocoa 如何显示未归档的自定义NSView对象,cocoa,nsview,Cocoa,Nsview,我正在学习Cocoa编程,但我不知道如何 存档和取消存档自定义NSView子类 我制作了一个玩具应用程序,它显示一个窗口。这扇窗户 包含自定义BackgroundView类的实例(存档在 xib文件)。单击此背景视图中的任意位置可创建和 显示一个以单击点为原点的蓝色正方形。这个广场是 我的Square类的一个实例。所有这些都像我预期的那样有效 Square类实现NSCoding协议。我补充说 dataOfType:typeName:error:和readfromData:ofType:error
Square.h
#import <Cocoa/Cocoa.h>
@interface Square : NSView <NSCoding> {
}
@end
Square.m
#import "Square.h"
@implementation Square
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
return self;
}
- (void)drawRect:(NSRect)rect {
[[NSColor blueColor] set];
NSBezierPath *newPath = [NSBezierPath bezierPathWithRect:[self bounds]];
[newPath fill];
}
-(void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeRect:[self frame] forKey:@"frame"];
}
-(id)initWithCoder:(NSCoder *)coder
{
NSRect theRect = [coder decodeRectForKey:@"frame"];
self = [super initWithFrame:theRect];
return self;
}
@end
-----
BackgroundView.h
#import <Cocoa/Cocoa.h>
@interface BackgroundView : NSView {
}
@end
BackgroundView.m
#import "BackgroundView.h"
#import "Square.h"
@implementation BackgroundView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
// Initialization code here.
}
return self;
}
- (void)drawRect:(NSRect)rect {
for (Square *subview in self.subviews)
[subview setNeedsDisplay:YES];
}
-(void)mouseDown:(NSEvent *)theEvent {
NSPoint unsetClick = [theEvent locationInWindow];
NSPoint theClick = [self convertPoint:unsetClick fromView:nil];
NSRect theRect;
theRect.origin = theClick;
theRect.size.width = 100.00;
theRect.size.height = 100.00;
Square *newSquare = [[Square alloc] initWithFrame:theRect];
[self addSubview:newSquare];
[newSquare setNeedsDisplay:YES];
}
@end
------
MyDocument.h
#import <Cocoa/Cocoa.h>
@class BackgroundView;
@interface MyDocument : NSDocument
{
IBOutlet BackgroundView *theBackgroundView;
}
@end
MyDocument.m
#import "MyDocument.h"
@implementation MyDocument
- (id)init
{
self = [super init];
return self;
}
- (NSString *)windowNibName
{
return @"MyDocument";
}
- (void)windowControllerDidLoadNib:(NSWindowController *) aController
{
[super windowControllerDidLoadNib:aController];
}
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
return [NSKeyedArchiver
archivedDataWithRootObject:[theBackgroundView subviews]];
if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain
code:unimpErr userInfo:NULL];
}
return nil;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName
error:(NSError **)outError
{
[theBackgroundView setSubviews:[NSKeyedUnarchiver
unarchiveObjectWithData:data]];
[theBackgroundView setNeedsDisplay:YES];
if ( outError != NULL ) {
*outError = [NSError errorWithDomain:NSOSStatusErrorDomain
code:unimpErr userInfo:NULL];
}
return YES;
}
@end
Square.h
#进口
@界面方块:NSView{
}
@结束
平方米
#导入“Square.h”
@实施广场
-(id)initWithFrame:(NSRect)帧{
self=[super initWithFrame:frame];
回归自我;
}
-(void)drawRect:(NSRect)rect{
[[NSColor blueColor]set];
NSBezierPath*newPath=[NSBezierPath bezierPathWithRect:[自边界]];
[新路径填充];
}
-(void)编码器WithCoder:(NSCoder*)编码器
{
[coder encodeRect:[self frame]forKey:@“frame”];
}
-(id)initWithCoder:(NSCoder*)编码器
{
NSRect-theRect=[coder-decodeRectForKey:@“frame”];
self=[super initWithFrame:theRect];
回归自我;
}
@结束
-----
背景视图
#进口
@接口背景视图:NSView{
}
@结束
背景视图
#导入“BackgroundView.h”
#导入“Square.h”
@实现背景视图
-(id)initWithFrame:(NSRect)帧{
self=[super initWithFrame:frame];
如果(自我){
//这里是初始化代码。
}
回归自我;
}
-(void)drawRect:(NSRect)rect{
用于(自.子视图中的方形*子视图)
[子视图设置需要显示:是];
}
-(无效)鼠标向下移动:(n事件*)事件{
NSPoint unset click=[theEvent location in window];
NSPoint theClick=[self convertPoint:unset从视图单击:nil];
NSRect-theRect;
theRect.origin=点击;
因此,ct.size.width=100.00;
因此,ct.size.height=100.00;
Square*newSquare=[[Square alloc]initWithFrame:theRect];
[自添加子视图:newSquare];
[新闻广场设置需要显示:是];
}
@结束
------
MyDocument.h
#进口
@课堂背景;
@接口MyDocument:NSDocument
{
IBOutlet背景视图*背景视图;
}
@结束
MyDocument.m
#导入“MyDocument.h”
@执行我的文件
-(id)init
{
self=[super init];
回归自我;
}
-(NSString*)windowNibName
{
返回@“MyDocument”;
}
-(void)WindowController IDLoadNib:(NSWindowController*)控制器
{
[超级窗口控制器IDLOADNIB:aController];
}
-(NSData*)数据类型:(NSString*)类型名称错误:(NSError**)外部错误
{
返回[NSKeyedArchiver
archivedDataWithRootObject:[theBackgroundView子视图]];
if(outError!=NULL){
*outError=[N错误errorWithDomain:NSOSStatusErrorDomain
代码:unperr userInfo:NULL];
}
返回零;
}
-(BOOL)readFromData:(NSData*)类型的数据:(NSString*)类型名
错误:(n错误**)外部错误
{
[背景视图设置子视图:[NSKeyedUnarchiver]
unarchiveObjectWithData:数据]];
[背景视图设置需要显示:是];
if(outError!=NULL){
*outError=[N错误errorWithDomain:NSOSStatusErrorDomain
代码:unperr userInfo:NULL];
}
返回YES;
}
@结束
正如我所见,您没有添加任何initWithXXX和encodeWithXXX方法,因为您没有自定义成员变量
我建议去看看苹果的 正如我所见,您没有添加任何initWithXXX和encodeWithXXX方法,因为您没有自定义成员变量
我建议去看看苹果的 由于Square是NSView的一个子类,并且NSView还实现了NSCoding,因此需要调用super对encodeWithCoder:和initWithCoder:的实现
@implementation Square
- (id)initWithFrame:(NSRect)frame
{
return [super initWithFrame:frame];
}
-(id)initWithCoder:(NSCoder *)coder
{
if ((self = [super initWithCoder:coder]))
{
NSRect theRect = [coder decodeRectForKey:@"frame"];
self = [super initWithFrame:theRect];
return self;
}
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[super encodeWithCoder:coder];
[coder encodeRect:[self frame] forKey:@"frame"];
}
- (void)drawRect:(NSRect)rect
{
[[NSColor blueColor] set];
[[NSBezierPath bezierPathWithRect:[self bounds]] fill];
}
@end
由于Square是NSView的一个子类,并且NSView还实现了NSCoding,因此需要调用super对encodeWithCoder:和initWithCoder:的实现
@implementation Square
- (id)initWithFrame:(NSRect)frame
{
return [super initWithFrame:frame];
}
-(id)initWithCoder:(NSCoder *)coder
{
if ((self = [super initWithCoder:coder]))
{
NSRect theRect = [coder decodeRectForKey:@"frame"];
self = [super initWithFrame:theRect];
return self;
}
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[super encodeWithCoder:coder];
[coder encodeRect:[self frame] forKey:@"frame"];
}
- (void)drawRect:(NSRect)rect
{
[[NSColor blueColor] set];
[[NSBezierPath bezierPathWithRect:[self bounds]] fill];
}
@end