Cocoa NsView doesn't show the image - cocoa

I am stuck with a problem I can not solve. I'm trying to show a small avatar in my app.
I created an NSView class, then add in interface builder a Custom View, and link it to the class.
It gives me no errors, but it doesn't diplay the image!
This is my .m NSView class file:
#import "Avatar.h"
#implementation Avatar
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self) {
NSRect rect = NSMakeRect(10, 10, 400, 300);
imageView = [[NSImageView alloc]initWithFrame:rect];
[imageView setImageScaling:NSScaleToFit];
NSImage *theImage = [NSImage imageNamed:#"/Users/blabla/nonloso/prova.jpg"];
[imageView setImage:theImage];
[self addSubview:imageView];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
}
#end
This is my .h NSView class file:
#import <Cocoa/Cocoa.h>
#interface Avatar : NSView {
#private
NSImageView *imageView;
}
#end

[-NSImage imageNamed] doesn't work that way – see its documentation.
You probably need -initWithContentsOfFile: instead.

Related

IB_DESIGNABLE Class not rendering on Interface Builder

This is my first try with IB_DESIGNABLE on Xcode.
I have this class to add color to a NSView.
header
#import <Cocoa/Cocoa.h>
IB_DESIGNABLE #interface NSViewComCor : NSView
#property (nonatomic, weak) IBInspectable NSColor *backgroundColor;
#end
implementation
#import "NSViewComCor.h"
#implementation NSViewComCor
#synthesize backgroundColor = _backgroundColor;
- (void)awakeFromNib {
[super awakeFromNib];
[self setWantsLayer:YES];
self.backgroundColor = [NSColor whiteColor]; //default color
}
- (NSColor *) backgroundColor
{
CGColorRef colorRef = self.layer.backgroundColor;
return [NSColor colorWithCGColor:colorRef];
}
- (void) setBackgroundColor:(NSColor *)backgroundColor
{ // color should change when changed on interface builder inspectable color box
self.layer.backgroundColor = backgroundColor.CGColor;
_backgroundColor = backgroundColor;
}
even with IB_DESIGNABLE, this class does not render with the correct color on interface builder... why?
As the point out in WWDC 2014 "What's New in Interface Builder" video, you have to:
Create framework.
Create class.
Mark view as designable (and properties as inspectable).
Go back to the main project and specify the base class in Interface Builder.
For example, I added a new "framework" target to the project, and added the following NSView subclass source to that framework:
IB_DESIGNABLE #interface CustomView : NSView
#property (nonatomic, strong) IBInspectable NSColor *backgroundColor;
#end
and
#implementation CustomView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
[self.backgroundColor setFill];
NSRectFill(dirtyRect);
}
#end
Then, when I went back to my main project and tried adding this CustomView as a subview on my storyboard, the "background color" was IB "inspectable" and I could see the changes in the color immediately rendered in IB.

Custom NSButtonCell, drawBezelWithFrame not called

I'm trying to figure out how to custom draw Buttons in Cocoa/OSX. Since my view is custom drawn I will not use IB and want to do it all in code. I created a subclass of NSButtonCell and a subclass of NSButton. In the Subclass of NSButtonCell I override the Method drawBezelWithFrame:inView: and in the initWithFrame Method of my subclassed NSButton I use setCell to set my CustomCell in the Button. However, drawBezelWithFrame gets not called and I don't understand why. Can someone point out what I've done wrong or what I miss here?
Subclass of NSButtonCell:
#import "TWIButtonCell.h"
#implementation TWIButtonCell
-(void)drawBezelWithFrame:(NSRect)frame inView:(NSView *)controlView
{
//// General Declarations
[[NSGraphicsContext currentContext] saveGraphicsState];
//// Color Declarations
NSColor* fillColor = [NSColor colorWithCalibratedRed: 0 green: 0.59 blue: 0.886 alpha: 1];
//// Rectangle Drawing
NSBezierPath* rectanglePath = [NSBezierPath bezierPathWithRect: NSMakeRect(8.5, 7.5, 85, 25)];
[fillColor setFill];
[rectanglePath fill];
[NSGraphicsContext restoreGraphicsState];
}
#end
Subclass of NSButton:
#import "TWIButton.h"
#import "TWIButtonCell.h"
#implementation TWIButton
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
TWIButtonCell *cell = [[TWIButtonCell alloc]init];
[self setCell:cell];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
}
#end
Usage:
- (void)addSendButton:(NSRect)btnSendRectRect
{
TWIButton *sendButton = [[TWIButton alloc] initWithFrame:btnSendRectRect];
[self addSubview:sendButton];
[sendButton setTitle:#"Send"];
[sendButton setTarget:self];
[sendButton setAction:#selector(send:)];
}
Following are the things seems to be missing out from your code.
You are not calling the [super drawRect:dirtyRect]
You are not overriding + (Class)cellClass in the Class(TWIButton) which is derived from NSButton.
Below is the code after changes:
#implementation TWIButton
- (id)initWithFrame:(NSRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
TWIButtonCell *cell = [[TWIButtonCell alloc]init];
[self setCell:cell];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect
{
// Drawing code here.
//Changes Added!!!
[super drawRect:dirtyRect];
}
//Changes Added!!!!
+ (Class)cellClass
{
return [TWIButtonCell class];
}
#end
Now keep the break point at drawBezelWithFrame and check it will get called.
One might forgo the NSButton subclass, since it looks like you are ONLY using it to instantiate the Cell type within the initializer.
Simply
NSButton *button ...
[button setCell: [[TWIButtonCell alloc] init] autorelease]];
btw. you will probably have a leak in the previous examples since you init and then call setCell that likely has its own retain.

xCode: Activating an IBAction from within a dynamically added subview

I have a separate UIView class that constructs a simple footer bar that contains a UIButton.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:CGRectMake(0, 410, 320, 50)];
if (self) {
int buttonHeight = self.frame.size.height;
int buttonWidth = 70;
int nextBtnPosX =0;
int nextBtnPosY =0;
self.backgroundColor =[UIColor colorWithRed:254.0/255.0 green:193.0/255.0 blue:32.0/255.0 alpha:1.0];
[self sendSubviewToBack:self];
UIButton *nextBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[nextBtn setTitle:#"Next" forState:UIControlStateNormal];
nextBtn.frame = CGRectMake(nextBtnPosX, nextBtnPosY, buttonWidth, buttonHeight);
[nextBtn addTarget:self.superview action:#selector(GoToNextPage) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:nextBtn];
}
return self;
}
I have several ViewControllers that then add this footer view class above to each view as a subview.
UIView *newFooter = [[theFooter alloc] init];
[self.view addSubview:newFooter];
Now the actual UIButton within the footer view needs to have its taget different for each viewController it is added to.
So I though it would be best to add the IBAction to the actual view controller then call this via the footer view.
But this is where I have come into a problem. How do I call the parent Controller to init the IBAction(GoToNextPage) from within the footer subview, from the addTarget?
Also would it be easier to have it all within the footer subview and pass in the target required, if so how else would this be done.
Here is a rough overview on what you should do.
This is how your UIView's header file should look
#protocol myViewControllerDelegate <NSObject>
#optional
- (void)didPushButton:(id)sender;
#end
#interface UIViewController : UITableViewController
{
__unsafe_unretained id <myViewControllerDelegate> delegate;
}
#property (nonatomic, assign) id <myViewControllerDelegate> delegate;
#end
Remember to #synthesize delegate; in your main file.
Finally in your main file, you will have an IBAction that receives the UIButton action.
Let's say that action is named buttonPushed.
Set that action to:
- (IBAction)buttonPushed:(id)sender
{
if (delegate)
[delegate didPushButton:sender];
}
Finally remember, that you need to set the delegate to each viewController you are using this viewController.
UIView *newFooter = [[theFooter alloc] init];
[self.view addSubview:newFooter];
newFooter.delegate = self;

how to set NSGradient to NSWindow background

I am new to cocoa I am try to set NSGradient to the NSWindow background but it's too difficult for me...I have try this code
NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor orangeColor] endingColor:[NSColor lightGrayColor]];
NSRect windowFrame = [self frame];
[gradient drawInRect:windowFrame angle:90];
but it is not working.... any other way to set NSGradient to NSWindow....
You can do it by subclassing NSWindow's View.
Create new window view's class (For example with title WindowViewSubclass).
Then .h file should look like this:
#import <Cocoa/Cocoa.h>
#interface WindowViewSubclass : NSView {
}
#end
and .m file:
#import "WindowViewSubclass.h"
#implementation WindowViewSubclass
- (void)drawRect:(NSRect)dirtyRect
{
NSGradient *gradient = [[NSGradient alloc] initWithStartingColor:[NSColor orangeColor] endingColor:[NSColor lightGrayColor]];
NSRect windowFrame = [self frame];
[gradient drawInRect:windowFrame angle:90];
}
#end
Now select window's view and go to Identity Inspectory -> Custom Class -> and select class like this:
Result:

Cocoa -- getting a simple NSImageView to work

I am confused about why this code does not display any image:
In the app delegate:
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
NSRect rect = window.frame;
rect.origin.x = 0;
rect.origin.y = 0;
BlueImageView *blueImageView = [[BlueImageView alloc]initWithFrame:rect];
window.contentView = blueImageView; // also tried [window.contentView addSubview: blueImageView];
}
BlueImageView.h:
#interface BlueImageView : NSImageView {
}
#end
BlueImageView.m:
#implementation BlueImageView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self setImage: [NSImage imageNamed:#"imagefile.png"]];
NSAssert(self.image, #"");
NSLog (#"Initialized");
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {
}
#end
The file imagefile.png exists. The NSAssert is not causing an exception. The NSLog is firing. But no image shows up in the window.
The drawRect: method is called to draw the view, and your implementation immediately returns. To get NSImageView to draw the image for you, call [super drawRect:dirtyRect]; in your implementation of drawRect:. If you aren't going to do any other drawing in drawRect:, just remove the method to speed up drawing.

Resources