Domanda

Sto imparando programmazione Cocoa, e sono in grado di capire come Archiviazione e annullamento di un personalizzato NSView sottoclasse

Ho fatto una domanda di giocattolo che presenta una finestra. questa finestra contiene un'istanza della mia classe BackgroundView personalizzato (archiviato in il file XI ter). Facendo clic su ovunque in questo BackgroundView crea e visualizza un quadrato blu la cui origine è il punto di scatto. Questa piazza è un'istanza della mia classe Square. Tutto questo funziona come mi aspetto.

La classe Square implementa il protocollo NSCoding. Ho aggiunto dataOfType: typeName: errore: e readfromData: OfType: errore: metodi alla classe myDocument. Per quanto posso dire dalle dichiarazioni di registro, il Piazze vengono archiviati nel file, e non archiviati quando il file viene caricato. Ma io sono in grado di effettuare le piazze si mostrano su la finestra. Il drawWithRect classe Square: il metodo non viene mai chiamato, anche se ho chiamato setNeedsDisplay: Si. su ogni quadrato

Il codice è il seguente:

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
È stato utile?

Soluzione

Dal momento che Square è una sottoclasse di NSView, e NSView implementa anche NSCoding, è necessario richiamare l'implementazione di super-sia encodeWithCoder: e 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

Altri suggerimenti

Come posso vedere che non aggiungere qualsiasi dei metodi initWithXXX e encodeWithXXX dal momento che non si dispone di variabili membro personalizzate.

Vi suggerisco di controllare Sketch Esempio .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top