IB_DESIGNABLE Class not rendering on Interface Builder - xcode

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.

Related

NSButton does not respond to MouseDown Events if it is a part of custom NSView

I have an OS X application with a main view (i.e., self.view) that contains an NSScrollView and the NSScrollView contains a custom NSView. The custom NSView (flippedNSView) is just an NSView custom class FlippedNSView with a -(BOOL)isFlipped { return YES; }
I have a function that creates a NSButton that is called in the ViewDidLoad.
If button is added to self.view, button works fine
If button is added to flippedNSView, button does not respond.
NSTextViews work fine and respond to MouseDown events, although they do not respond to text selection. Only the buttons do not respond.
Any ideas?
AppDelegate.h
#import "CodeObjViewController.h"
#interface AppDelegate : NSObject <NSApplicationDelegate> {
FlippedView *flippedNSView;
}
// Windows are defined in MainMenu.xib with the following hierarchy
// Window
// |_ View
// |_ flippedNSView
// |_ scrollView
// |_ myCustomView
#property (assign) IBOutlet NSWindow *window;
#property (strong) IBOutlet NSViewController *myViewController;
#property (weak) IBOutlet NSView *myCustomView;
#property(readwrite, strong, nonatomic) IBOutlet NSScrollView* scrollView;
#property(readwrite, strong, nonatomic) IBOutlet FlippedView * flippedNSView;
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
#synthesize scrollView;
#synthesize flippedNSView;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
_myViewController = [[CodeObjViewController alloc] initWithNibName:#"customViewController" bundle:nil];
[_myCustomView addSubview:[_myViewController view]];
[[_myViewController view] setFrame:[_myCustomView bounds]];
[scrollView setDocumentView: flippedNSView];
}
customViewController.h
#interface FlippedView : NSView
#end
//----------------------------------------------------------
#interface CodeObjViewController : NSViewController {
FlippedView *flippedNSView;
NSScrollView *scrollView;
}
customViewController.m
#implementation FlippedView
- (id)initWithFrame:(NSRect)frame {
self = [super initWithFrame:frame];
return self;
}
//----------------------------------------------------------
- (BOOL)isFlipped {
return YES;
}
#end
//----------------------------------------------------------
#implementation customViewController
// Custom View Controller
-(void) viewDidLoad {
// The scroll and flipped views are defined on menu.xib and declared on the AppDelegate.
AppDelegate *theAppDelegate = (AppDelegate*) [NSApplication sharedApplication].delegate;
flippedNSView = theAppDelegate.flippedNSView;
scrollView = theAppDelegate.scrollView;
NSButton *button = [[NSButton alloc] initWithFrame:NSMakeRect(0,0,10,10)];
[self.view addSubview:helpButton]; // THIS RESPONDS TO MOUSE DOWN
[flippedNSView addSubview:helpButton]; // THIS DOES NOT RESPOND TO MOUSE DOWN
[button setAction:#selector(buttonClicked:)];
[button setTarget:self];
}
-(void) buttonClicked : (id) sender {
NSLog(#"Button clicked");
}

Cocoa : Load NSViewController with nib

I have tried many possibilities I found on this site and read some explanations
from apple developer page, but seems like i couldn't resolve my problem about
loading NSViewController with/form NIB.
Files on Xcode Project look a bit like this :
SecondViewController.h
SecondViewController.m
SecondViewController.xib
AppDelegate.h
AppDelegate.m
MainMenu.xib
The main problem is how could i create the SecondViewController programatically with
the initial nib on SecondViewController.xib
Custom class of FileOwner on MainMenu.xib is NSApplication
Custom class of FileOwner on SecondViewController.xib is SecondViewController
There are some panels and window in MainMenu.xb (about window and preference panel)
This application has no main window (using notification icon on status bar)
SecondViewController.h
#interface SecondViewController : NSViewController {
BOOL fullScreenMode;
NSImageView *fullScreenbg;
NSImageView *imageView1;
NSImageView *imageView2;
NSPanel *imageWindow;
}
#property (assign) IBOutlet NSImageView *fullScreenbg;
#property (assign) IBOutlet NSImageView *imageView1;
#property (assign) IBOutlet NSImageView *imageView2;
#property (assign) IBOutlet NSPanel *imageWindow;
SecondViewController.m
#implementation SecondViewController {
NSImageView *nv1;
NSImageView *nv2;
NSSize curImgSize;
}
#synthesize fullScreenbg;
#synthesize imageView1;
#synthesize imageView2;
#synthesize imageWindow;
......
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
fullScreenMode = YES;
}
return self;
}
AppDelegate.h
#interface AppDelegate : NSObject <NSApplicationDelegate,NSWindowDelegate> {
NSPanel *aboutWindow;
IBOutlet NSMenu *myStatusMenu;
IBOutlet NSMenuItem *toggleFullScreen;
}
AppDelegate.m
#implementation AppDelegate {
SecondViewController *controller;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
controller = [[SecondViewController alloc]
initWithNibName:#"SecondViewController"
bundle:nil];
//Not work (fullscreenbg, imageView1, imageView2,imageWindow = nil)
//controller = [[SecondViewController alloc] init]; ?? <-- didn't work either
}
Even if using initWithNibName or just init, all the IBOutlet properties seems to be nil
on debug.
i've tried other solustions like "NSBundle loadNibNamed" or using loadView but it didn't work (warning message : "NSObject my not respond to loadView").
The main purpose of the secondViewController is to display notification message including
graphics and web element.
I hope someone could give me a best suggestion. Thanks.
This is normal behavior. IBOutlets are not connected in the constructor.
You can override viewDidLoad, call super and then do any initialization.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
//added this line :
if (nibBundleOrNil!=nil || ![nibBundleOrNil isEqualtoString:#""]) {
[NSBundle loadNibNamed:#"SecondViewController" owner:self];
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Initialization code here.
fullScreenMode = YES;
}
return self;
}

UILabel subclass

I know that this is a newbie question but I am a newbie so here goes:
I wish to use Chalkduster font quite a lot throughout my app (buttons, labels etc) and have tried subclassing UILabel to achieve this. I have the following in Default.h:
#import <UIKit/UIKit.h>
#interface Default : UILabel
{
UILabel *theLabel;
}
#property (nonatomic, strong) IBOutlet UILabel *theLabel;
#end
and this in my .m:
#import "Default.h"
#implementation Default
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
UIFont *custom = [[UIFont alloc] init];
custom = [UIFont fontWithName:#"Chalkduster" size:18];
self.font = custom;
NSLog(#"h");
}
return self;
}
#end
When I change the class in interface builder and run, I'm not seeing the Chalkduster font. I'd appreciate a hand in getting this set up as I believe it will save me a lot of time.
Cheers.
Some problems to fix:
1) You're mixing up the idea of Default being a label and Default containing a label. To subclass, get rid of the property inside your class and make your changes to self rather than theLabel (inside the if (self) { section).
2) Anything you code after an unconditional return isn't going to get executed...and I'm surprised the compiler didn't complain about those statements.
Edit: ...and one more thing that just dawned on me.
3) If you're loading from a xib or storyboard, the initialization is done by initWithCoder: instead of initWithFrame:, so:
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
self.font = [UIFont fontWithName:#"Chalkduster" size:18];
}
return self;
}
First of all I don't think that You're subclassing UILabel correctlly. So I made tutorial for You explaining how to do it. You don't need to IBOutlet object which is subclassed. JUST CALL IT WITH SELF. for example: self.font = ... If You want to subclass UILabel do this:
Create new class with title myLabel like this:
.h
#import <UIKit/UIKit.h>
#interface MyLabel : UILabel {
}
#end
.m
#import "MyLabel.h"
#implementation MyLabel
-(void)awakeFromNib {
UIFont *custom = [[UIFont alloc] init];
custom = [UIFont fontWithName:#"Chalkduster" size:18];
self.font = custom;
}
#end
Now select Your label in storyboard and go to indentity inspector and in Custom Class select created class above. Like this:
Output:
Note: Don't forget to release custom because You are allocating it.
Move the return self; three lines down. You return from the init method before you do your custom initialization.
Edit to reflect new information from comment:
When deserializing the view from a nib you also have to override initWithCoder:

Cocoa NsView doesn't show the image

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.

How do I edit an interface builder object programmatically?

I created a label using Interface Builder, and now I want to set the background color of the label using code instead of IB's color picker. (I want to do this so that I can define the color using RGB and eventually change the colorspace for the label.)
I'm in cocoa. How do I edit the attributes of an IB object using code?
My code looks like this:
//.h file
#import <UIKit/UIKit.h>
#interface IBAppDelegate : NSObject {
UILabel *label;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
#end
//.m file
#import "IBAppDelegate.h"
#implementation IBAppDelegate
#synthesize label;
(memory stuff...)
#end
- (void)applicationDidBecomeActive:(UIApplication*)application
{
self.label.backgroundColor = [UIColor colorWithRed:0.1f
green:0.2f
blue:0.3f
alpha:1.0f];
}
label.backgroundColor = [UIColor greenColor]
There's nothing special about the objects in your XIB file. They're just normal objects.

Resources