cocoa - Drawing in a view: Why can't I get my NSImage to display in my NSImageView? -


i created nsimageview using code:

@implementation iconview  -(void)awakefromnib {      [self setimagerect:nsmakerect(36, 66, 144, 144)];     [self setimageview:[[nsimageview alloc] initwithframe:[self imagerect]]];     [self addsubview:[self imageview]];      //for frame around image:     [self setframerect:nsmakerect(18, 42, 180, 180)];     [nsbezierpath setdefaultlinewidth:12];   }  - (void)drawrect:(nsrect)dirtyrect {     [super drawrect:dirtyrect];      // drawing code here.      [[self alertcolor] set];     [nsbezierpath strokerect:[self framerect]];     [[[self imageview] image] setsize:[self imagerect].size ]; } 

and set nsimageview's image this:

@implementation iconviewcontroller   -(void)setcolor:(nscolor *)color forapplication:(nsrunningapplication *)app {      iconview* iconview = (iconview*)[self view]; //the view associated controller     [iconview setalertcolor:color];     [[iconview imageview] setimage:[app icon]];     nslog(@"app icon: %@", [app icon]);      [[self view] setneedsdisplay:yes];  } 

the log output this:

2015-05-07 22:29:27.711 helloapplication[1569:17913] app icon: <nsimage 0x608000260c00 size={32, 32} reps=(     "<nsiconrefimagerep:0x608000083bb0 iconref=0x103 size:128x128 pixels:128x128>",     "<nsiconrefimagerep:0x608000083d90 iconref=0x103 size:128x128 pixels:256x256>",     "<nsiconrefimagerep:0x608000083e30 iconref=0x103 size:256x256 pixels:256x256>",     "<nsiconrefimagerep:0x608000083de0 iconref=0x103 size:256x256 pixels:512x512>",     "<nsiconrefimagerep:0x608000084150 iconref=0x103 size:512x512 pixels:512x512>",     "<nsiconrefimagerep:0x608000084100 iconref=0x103 size:48x48 pixels:48x48>",     "<nsiconrefimagerep:0x608000084790 iconref=0x103 size:36x36 pixels:36x36>",     "<nsiconrefimagerep:0x608000084ec0 iconref=0x103 size:36x36 pixels:72x72>",     "<nsiconrefimagerep:0x608000084470 iconref=0x103 size:32x32 pixels:32x32>",     "<nsiconrefimagerep:0x608000085000 iconref=0x103 size:32x32 pixels:64x64>",     "<nsiconrefimagerep:0x608000085050 iconref=0x103 size:18x18 pixels:18x18>",     "<nsiconrefimagerep:0x608000084fb0 iconref=0x103 size:18x18 pixels:36x36>",     "<nsiconrefimagerep:0x6080000850a0 iconref=0x103 size:16x16 pixels:16x16>",     "<nsiconrefimagerep:0x6080000850f0 iconref=0x103 size:16x16 pixels:32x32>",     "<nsiconrefimagerep:0x608000085140 iconref=0x103 size:512x512 pixels:1024x1024>" )> 

so, looks have nsimage--but won't display. see stroke of framerect in proper color, no image displays. ib shows in iconview.xib iconviewcontroller(file's owner) connected iconview:

enter image description here

my window controller this:

// //  mywindowcontroller.m //  helloapplication //  @implementation mywindowcontroller   - (void)windowdidload {     [super windowdidload];      // implement method handle initialization after window controller's window has been loaded nib file.  }  - (void)setupview {      [self setviewctrl:[[iconviewcontroller alloc] initwithnibname:@"iconview" bundle:nil]];     …     …     nsview* view = [[self viewctrl] view];     [[self window] setcontentsize:[view bounds].size];  //[view bounds] returns struct, elements must     [[self window] setcontentview:view];                //accessed dot notation.     … }  -(id) initwithwindownibname:(nsstring *)windownibname {      if (self = [super initwithwindownibname:windownibname]) {         [self setupview];     }      return self; }  @end 

my appdelegate this:

// //  appdelegate.m //  helloapplication //  #import "appdelegate.h" #import "mywindowcontroller.h"   @interface appdelegate ()  @property(strong) mywindowcontroller* windowctrl;  @end   @implementation appdelegate   - (void)applicationdidfinishlaunching:(nsnotification *)anotification {      [self setwindowctrl:[[mywindowcontroller alloc] initwithwindownibname:@"mainwindow"]];     [[self windowctrl] showwindow:self];  } 

if need more files or screenshots let me know:

// //  iconview.h //  helloapplication //  #import <cocoa/cocoa.h>  @interface iconview : nsview  @property(copy) nscolor* alertcolor; @property(weak) nsimageview* imageview;  @end 

...

// //  iconview.m //  helloapplication //  #import "iconview.h"  @interface iconview()  @property(assign) nsrect framerect; @property(assign) nsrect imagerect;   -(void)awakefromnib;  @end   @implementation iconview  -(void)awakefromnib {      [self setimagerect:nsmakerect(36, 66, 144, 144)];     [self setimageview:[[nsimageview alloc] initwithframe:[self imagerect]]];     [self addsubview:[self imageview]];      [self setframerect:nsmakerect(18, 42, 180, 180)];     [nsbezierpath setdefaultlinewidth:12];   }  - (void)drawrect:(nsrect)dirtyrect {     [super drawrect:dirtyrect];      // drawing code here.      [[self alertcolor] set];     [nsbezierpath strokerect:[self framerect]];     [[[self imageview] image] setsize:[self imagerect].size ]; }  @end 

...

// //  iconviewcontroller.h //  helloapplication //  #import <cocoa/cocoa.h> #import "myactivitymonitordelegateprotocol.h"  @interface iconviewcontroller : nsviewcontroller <myactivitymonitordelegateprotocol>   @end 

...

// //  iconviewcontroller.m //  helloapplication //  #import "iconviewcontroller.h" #import "iconview.h"  @interface iconviewcontroller ()  -(void)setcolor:(nscolor*)color forapplication:(nsrunningapplication*)app;  @end    @implementation iconviewcontroller   -(void)setcolor:(nscolor *)color forapplication:(nsrunningapplication *)app {      iconview* iconview = (iconview*)[self view]; //the view associated controller     [iconview setalertcolor:color];     [[iconview imageview] setimage:[app icon]];     nslog(@"app icon: %@", [app icon]);      [[self view] setneedsdisplay:yes];  }  -(void)applicationdidlaunch:(nsrunningapplication *)app {     [self setcolor:[nscolor greencolor] forapplication:app]; }  -(void)applicationdidterminate:(nsrunningapplication *)app {      [self setcolor:[nscolor redcolor] forapplication:app]; }   - (void)viewdidload {     [super viewdidload];     // view setup here. }  @end 

this example old cocoa book, p 240-241:

cocoa programming: quick start guide developers.

response @joshua nozzi's answer:

(1)

-drawrect:— don't set properties here, least of all, causes further drawing in subviews (such setting image view's image).

i’m setting size of imageview’s image. example following dutifully removed code drawrect: needed called once, when try setting size of nsimageview's image elsewhere, e.g. in iconviewcontroller's viewdidload: method, doesn't succeed in setting displayed image's size, must happen late. ah, works if set size in iconviewcontroller’s setcolor:forapp: method right before telling view needs redrawn:

-(void)setcolor:(nscolor *)color forapplication:(nsrunningapplication *)app {      iconview* iconview = (iconview*)[self view]; //the view associated controller     nsimageview* imageview = [iconview imageview];      [iconview setalertcolor:color];     [imageview setimage:[app icon] ];     //nslog(@"app icon: %@", [app icon]);     [ [imageview image] setsize:[iconview imagerect].size ];     [[self view] setneedsdisplay:yes];  } 

(2)

your call -setupview comes during window controller's initialization, [window's] nib hasn't been loaded yet...

it looks these lines concern you:

- (void)setupview {     …     …     [[self window] setcontentsize:[view bounds].size];  //[view bounds] returns struct, elements must     [[self window] setcontentview:view];                //accessed dot notation. 

calling [[self window] dosomething] before window unarchived means [self window] nil, , calling [nil dosomething] won’t anything. moved lines window controller’s windowdidload method:

@implementation mywindowcontroller   - (void)windowdidload {     [super windowdidload];      // implement method handle initialization after window controller's window has been loaded nib file.      nsview* view = [[self viewctrl] view];     [[self window] setcontentsize:[view bounds].size];  //[view bounds] returns struct, elements must     [[self window] setcontentview:view];                //accessed dot notation.   } 

and seems there may other errors well: i’ve read shouldn’t call accessor methods in init methods--instead should access ivars directly.

(3)

you appear have application delegate methods (did launch / did terminate) in icon view controller

no, don’t think case; tutorial i’m following used confusing method names. kept thinking cocoa methods myself put comment in code indicating custom methods. here declaration of iconviewcontroller:

@interface iconviewcontroller : nsviewcontroller <myactivitymonitordelegateprotocol> 

and applicationdidlaunch:/applicationdidterminate: methods declared myactivitymonitordelegateprotocol. application in method names refers application launched/terminated on system while my app running.

some points:

  1. your -drawrect: implementation should fast , lightweight possible, means should handle drawing. don't set properties here, least of all, causes further drawing in subviews (such setting image view's image).

  2. your call -setupview comes during window controller's initialization, nib hasn't been loaded yet. meanwhile -windowdidloadnib method sits empty, comment suggestion it's setting things after stuff's been loaded nibs. recipe messages sent nil , / things not working right. try setting stuff -windowdidloadnib instead of init routine.

  3. you appear have application delegate methods (did launch / did terminate) in icon view controller, yet specify dedicated app delegate. application delegate methods need in 1 place: actual delegate.

i hope helps.


Comments