I have the following code in .h file:
#import <UIKit/UIKit.h>
#interface SCLoginViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *btnLogin;
#end
and the following code in .m file:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
// Do any additional setup after loading the view from its nib.
// Add gradient to the buttons
btnLogin.layer.cornerRadius = 10;
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = btnLogin.layer.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithWhite:1.0f alpha:0.1f].CGColor,
(id)[UIColor colorWithWhite:0.4f alpha:0.5f].CGColor,
nil];
gradientLayer.cornerRadius = btnLogin.layer.cornerRadius;
[btnLogin.layer addSublayer:gradientLayer];
// Add shadow
btnLogin.layer.shadowColor = [UIColor darkGrayColor].CGColor;
btnLogin.layer.shadowOpacity = 1.0;
btnLogin.layer.shadowOffset = CGSizeMake(2.0, 2.0);
}
This is how the button sits on the screen:
Something is horribly wrong though. I know I am missing something simple, but can't figure it out. I created regular outlet called btnLogin but any change I try to make to it is not working. The button is rounded rect button. I tried Custom button and that didn't help.
Thank you!
From the image, I see that you did not make a connection from your btnLogin on the nib file to the file's owner - .h file. So this line below has no connection to the button that you are trying to make changes.
#property (weak, nonatomic) IBOutlet UIButton *btnLogin;
Once you make that proper connection, it should show up the btnLogin name where Referencing Outlets is on the image you provided.
Related
I create a category of UIButton class, use IB_DESIGNABLE. But I got an strange error Failed to render instance of RoundedCornerButton: Rendering the view took longer than 200 ms. Your drawing code may suffer from slow performance. I tried many suggestions on this website but still cannot fix it. please help me to find the root cause.Please see the image for more detail (RoundedCornerButton: is the category of UIButton class)
Update: the code for RoundedCornerButton class:
.h file
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface RoundedCornerButton : UIButton
#property (nonatomic) IBInspectable int cornerRadius;
#property (nonatomic) IBInspectable int borderWidth;
#property (nonatomic) IBInspectable UIColor* borderColor;
#end
.m file:
#import "RoundedCornerButton.h"
#implementation RoundedCornerButton
-(void)drawRect:(CGRect)rect{
self.layer.borderWidth = self.borderWidth;
self.layer.borderColor = self.borderColor.CGColor;
[self.layer setCornerRadius:self.cornerRadius];
self.clipsToBounds = YES;
}
#end
I can run my project on device successful, but I got the Red warning as above.(It so strange, I use Xcode 7.0)
You mustn't play with your layer in drawRect like that. That isn't drawing! Drawing is about content.
Move that code somewhere else, such as awakeFromNib and prepareForInterfaceBuilder (both), and all will be well.
Here's example code:
#implementation RoundedCornerButton
-(void) config {
self.layer.borderWidth = self.borderWidth;
self.layer.borderColor = self.borderColor.CGColor;
[self.layer setCornerRadius:self.cornerRadius];
self.clipsToBounds = YES;
}
-(void)prepareForInterfaceBuilder {
[self config];
}
-(void)awakeFromNib {
[super awakeFromNib];
[self config];
}
#end
And you can see it works fine in IB in Xcode 7:
I'm about to begin a big project which will contains a lot of UI customization.
For example, I need an UIView which will look like that :
So I wrote an UIView custom class but i really don't know if my code is optimized and if there are best ways to do that, so could you give me some advice plz ?
Here's my code :
// DPIViewHeader.h
#define HEADER_HEIGHT 30.0f
#define HEADER_COLOR [UIColor colorWithRed:161.0f/255.0f green:209.0f/255.0f blue:249.0f/255.0f alpha:1.0f]
#define BORDER_WIDTH 2.0f
#define BORDER_COLOR [[UIColor colorWithRed:82.0f/255.0f green:159.0f/255.0f blue:210.0f/255.0f alpha:1.0f] CGColor]
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface DPIViewWithHeaderTest : UIView
// properties
#property (strong, nonatomic) NSString *title;
#property (strong, nonatomic) UIColor *headerColor;
#property (strong, nonatomic) UIView *headerView;
#property (strong, nonatomic) UIView *contentView;
// methods
- (id)initWithFrame:(CGRect)frame title:(NSString *)title;
- (id)initWithFrame:(CGRect)frame title:(NSString *)title headerColor:(UIColor *)headerColor;
#end
// DPIViewHeader.m
#import "DPIViewWithHeaderTest.h"
#implementation DPIViewWithHeaderTest
- (id)initWithFrame:(CGRect)frame title:(NSString *)title {
self = [super initWithFrame:frame];
if (self) {
self.title = title;
}
return self;
}
- (void)layoutSubviews {
// set header view and content view
self.headerView = [[UIView alloc] initWithFrame:CGRectMake(self.bounds.origin.x, self.bounds.origin.y, self.frame.size.width, HEADER_HEIGHT)];
self.contentView = [[UIView alloc] initWithFrame:CGRectMake(self.bounds.origin.x, self.bounds.origin.y + HEADER_HEIGHT, self.frame.size.width, self.frame.size.height - HEADER_HEIGHT)];
// add title label
UILabel *label = [[UILabel alloc] init];
label.text = self.title;
[label sizeToFit];
label.center = CGPointMake(label.frame.size.width/2 + 10, self.headerView.frame.size.height/2);
label.backgroundColor = [UIColor clearColor];
[self.headerView addSubview:label];
// set color header
self.headerView.backgroundColor = HEADER_COLOR;
// set border attributes
self.layer.borderWidth = BORDER_WIDTH;
self.layer.borderColor = BORDER_COLOR;
self.headerView.layer.borderWidth = BORDER_WIDTH;
self.headerView.layer.borderColor = BORDER_COLOR;
// add subviews
[self addSubview:self.headerView];
[self addSubview:self.contentView];
}
#end
It really depends (like everything :) ) .
Let me tell you why using two scenarios:
The View is non-customisable:
If DPIViewWithHeaderTest is going to be embedded in a UITableViewCell, then well, scroll performance will be terrible due to high memory usage. Therefore improper for this purpose.
The next scenario: just a simple view, somewhere, with a static background, and some data. It's OK than, but not the best solution.
Good Solution
For both purposes I would suggest creating images. A prerendered image is cached and leaves very small memory footprint. Moreover in this case you could even create strechable one. Isn't this great ?
What if a UIView has to be customisable (like colour, size) ? Then this is the only solution but I would consider rewriting the implementation depending on purpose.
If there are going to be lots of such views, they are animated, for example this is a background of UITableViewCell you should consider drawing them using QuartzCore/Core Graphics for better performance.
For just one (or few) view, this implementation is just fine :) .
Last piece of advice
Generally, unless the view is to be customisable, I would suggest creating images.
For three reasons: performance, look and easiness of creation. Believe me, well crafted images look way better than custom drawing :)
I've seen some solutions, none of which have worked for my issue.
I have a UIButton created by simply drag/dropping into the UIViewController in Storyboard editor.
The UIButton has an outlet linked to the .h file for the UIViewController associated to that view. It is also Synthesized in the .m file.
#property (strong, nonatomic) IBOutlet UIButton *answerButton;
I want to change the location of the button during run time like this;
CGRect btFrame = answerButton.frame;
btFrame.origin.x = xOne;
btFrame.origin.y = yOne;
answerButton.frame = btFrame;
However whenever I try this, the button refuses to move.
All other editing functions (like setTitle etc) are functional, but for some reason the frame won't move how I want it to.
Simply uncheck "Use Autolayout" in the file inspector..
.h file
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UIButton *theButton;
}
#property(nonatomic, strong) IBOutlet UIButton *theButton;
-(IBAction)moveTheButton:(id)sender;
#end
.m file
-(IBAction)moveTheButton:(id)sender{
CGRect btFrame = theButton.frame;
btFrame.origin.x = 90;
btFrame.origin.y = 150;
theButton.frame = btFrame;
}
This code moves the button from one point to another.
Replace your code by the below, which includes code to remove auto resizing mask.
CGRect btFrame = answerButton.frame;
btFrame.origin.x = xOne;
btFrame.origin.y = yOne;
answerButton.autoresizingMask = UIViewAutoresizingNone;
answerButton.frame = btFrame;
I'm working with creating my own custom view templates programmatically for the app I'm working on. To achieve this i have a custom view controller MyVC with a a custom view myView added on to it which is a property of MyVC. The class looks something like this:
MyVC.h
#import <UIKit/UIKit.h>
#interface MyVC : UIViewController{
MyCustomView *myView;
}
#property(nonatomic, retain) MyCustomView *myView
#end
In the implementation i want to assign a background color to 'myView' and i do something like this in the viewDidLoad (after synthesizing my property of corse)
-(void)viewDidLoad{
self.myView = [[MyCustomView alloc] initWithFrame:someFrame];
self.myView.backgroundColor = [UIColor clearColor];
}
Now when i analyze my code i get a 'potential leak of an object' message when i assign the color. Is it because myView or the background color or both are being retained?
In any case id like to know how this can be done correctly without potential leaks?
If you don't using ARC you should release over retained property:
-(void)viewDidLoad{
//allocate and initialize myView
self.myView = [[[MyCustomView alloc] initWithFrame:someFrame] autorelease];
self.myView.backgroundColor = [UIColor clearColor];
}
I have create a UIVeiw class and a .xib. Within this .xib view I have its set to freeform with the dimensions of 400x200 and I have assigned it to my custom class with the same name:
Storyboard: blogView
Class Files: blogView.h & blogView.m
Within in the .xib i have added a label and a text field and linked them up to variable within the .h files etc (See code below).
blogCont.h
#import <UIKit/UIKit.h>
#interface blogCont : UIView
#property (strong, nonatomic) IBOutlet UILabel *lbBlogDate;
#property (strong, nonatomic) IBOutlet UITextView *txtBlogTitle;
#end
blogCont.m
#import "newsStoryView.h"
#implementation blogCont
#synthesize lbBlogDate;
#synthesize txtBlogTitle;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code place a log to see if it loads
NSLog(#"View Loaded");
}
return self;
}
#end
Now with in my main viewController.m file i have added the following code to init this view class, and I have added a background colour to see if this loads in.
viewController.m
UIView *blogCont = [[blogView alloc] init];
blogCont.backgroundColor = [UIColor purpleColor];
[subview addSubview:blogCont];
Now when I run this it all works well but as I do not see the purple background it looks as if the view does not load, but within the log I do see the NSLog message I have within this view NSLog(#"View Loaded"); so it seems it initiating this, but I cannot for the life of me get this to display?
Now if I change the code slightly to my main View Controller.m fiel to:
CGRect blogFrame;
blogFrame.origin.x = 20;
blogFrame.origin.y = 20;
blogFrame.size = CGRectMake(400,200);;
newsStoryView *blogCont = [[blogView alloc] blogFrame];
blogCont.backgroundColor = [UIColor purpleColor];
[subview addSubview:blogCont];
Then I get my view display a nice purple box, so this shows up when I set a frame size and the init the view with it 'blogFrame', bu tI thought that all this would be set within the .xib settings so no need to do this?
SO how can I create this external view class and assign it into another view and then manipulate its data, as accessing the label in the .xib using blogCont.lbBlogDate.text does not seem to work that is it probably does but as I cannot view it i cannot confirm it.
What am i doing wrong?
Thanks
Seems I nearly answered my own question then did:
I was not setting the size within my separate class view I was asking for a size when init it:
- (id)initWithFrame:(CGRect)frame
this is asking for a size
so I could do the following to the above:
- (id)init
{
self = [super initWithFrame:CGRectMake(0, 0, 478, 220)];
.... rest of code
Setting the size within the view load.
But I could also set it when I init it in my main view controller as below:
newsStoryView *blogCont = [[blogView alloc] initWithFrame:CGRectMake(0, 0, 400, 200)];
This is better as I can control the position of each one. Hope this helps anyone