UIControl Lifecycle - ios

Is there a documented Lifecycle for a UIControl somewhere?
Here's why I ask:
Suppose I have a UITextField. I could easily wire up a button that changes the border color like so:
myTextField.layer.borderColor = [[UIColor redColor] CGColor];
Now suppose I have a custom control that's a subclass of UIControl. That same code will not change the border color unless I also issue setNeedsLayout, like so:
[myControl setNeedsLayout];
Is there an event method somewhere that I need to implement to make this work without the setNeedsLayout?

For future generations, here's how I solved the problem on my own.
In my .h file:
#property (nonatomic, strong, setter = setBorderColor:) UIColor *borderColor;
In my .m file:
- (void)setBorderColor:(UIColor *)clr {
borderColor = clr;
myControl.layer.borderColor = borderColor.CGColor;
}
Works like a charm.

Related

How to programmatically add a label in a custom subview?

I'm designing a card game (cards against humanity) for iOS, there are two types of cards, the whites ones, and the black ones. So I've implemented a CardView class which inherits from UIView, and two class, WhiteCardView and BlackCardView which both inherit from CardView.
As you guess, almost only the color will change between those two, but I still want two different view class for those two (even if they are almost the same at the moment). So, I have four questions about that.
EDIT: I mnage to find out some answer by myself, but for the last one, I'm lost.
1.I need advice on my implementation, I don't know if I'm doing it right to set the colors of the cards which is stored in CardView but set in the init of my WhiteCardView. I think I have to override only one init, but I don't know which one. So if someone can confirm or correct what I already did, that would be great. Thanks
Here is my CardView code:
IB_DESIGNABLE
#interface CardView : UIView
-(void)customDrawUI;
-(void)setData;
#property (nonatomic) UIColor* IBInspectable secondaryColor;
#property (nonatomic) UIColor* IBInspectable primaryColor;
#property(nonatomic) UILabel* txtLabel;
#end
#implementation CardView
-(void)customDrawUI{
self.layer.cornerRadius=5.0;
self.backgroundColor = self.primaryColor;
}
-(void)setData{
self.txtLabel.text = #"some text";
}
#end
And the WhiteCardView code:
IB_DESIGNABLE
#interface WhiteCardView : CardView
#end
#implementation WhiteCardView
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect myFrame = self.bounds;
CGContextSetLineWidth(context, 1);
CGRectInset(myFrame, 5, 5);
[self.secondaryColor set];
UIRectFrame(myFrame);
}
-(id)initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
self.primaryColor= [UIColor whiteColor];
self.secondaryColor= [UIColor blackColor];
[super customDrawUI];
[super setData];
}
return self;
}
#end
2.In interface builder (where I correctly define the custom class for each of my cards), my views aren't live rendered, the code in my drawRect method WhiteCardView is executed but I can see no change.
And when I run my app, I get the same result. Just white rectangle, without any rounded angle.
Any idea why there is no changing in my view?
EDIT: I didn't put the IBDESIGNABLE tag in the right place, now it works !
3.Is there any way to execute that line: self.backgroundColor = self.primaryColor; in the parent drawRect method ? Because it's currently in both: White and BlackCardView, and there is certainly a way to do it in the parent class (I'll add common code to those two class, so I need a way to do it).
Maybe it's possible to do this in the init from CardView, but as it's not working at the moment, I can't test it.
EDIT: I find out, the setBackground couldn't be called from drawRect, so I define a new method in the CardView class to do that. And I call it from the init methods.
4.The most important part: how is it possible to add a label on each card (not via interface builder but via the CardView class), and be able to set its content programmatically?
I defined a property for that label, and I set its value but I have no idea how to render it.

Set UIButton Layer Border Width and Color in Interface Builder

Can I use IB_DESIGNABLE and/or IBInspectable to set layer.borderWidth and layer.borderColor in Interface Builder? I am currently creating my button in code but I'd like to be able to set all of this in IB but I'm not sure if these properties can be set that way in Xcode 6. I'd like to make this an IBOutlet instead of having all of this set in code. Here is my button code now.
directions = [UIButton buttonWithType:UIButtonTypeRoundedRect];
directions.titleLabel.textAlignment = NSTextAlignmentCenter;
directions.titleLabel.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:20.0];
[directions setTitle:#"Directions" forState:UIControlStateNormal];
[directions setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
directions.frame = CGRectMake(20, 178, 70, 70);
directions.layer.borderWidth = 2.0f;
directions.layer.borderColor = [UIColor whiteColor].CGColor;
directions.clipsToBounds = YES;
directions.backgroundColor = [UIColor clearColor];
[directions addTarget:self action:#selector(getDirections:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:directions];
I set these values as suggested and the border is never shown in the simulator.
EDIT: I found out why the border wasn't showing up when setting these values in IB. The border color is a CGColor so I had to set it in code.
Actually you can set some properties of a view's layer through interface builder. I know that I can set a layer's borderWidth and cornerRadius through xcode. borderColor doesn't work, probably because the layer wants a CGColor instead of a UIColor.
You might have to use Strings instead of numbers, but it works!
But you can use categories to proxy properties such as layer.borderColor. (From the ConventionalC CocoaPod)
CALayer+XibConfiguration.h:
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
#interface CALayer(XibConfiguration)
// This assigns a CGColor to borderColor.
#property(nonatomic, assign) UIColor* borderUIColor;
#end
CALayer+XibConfiguration.m:
#import "CALayer+XibConfiguration.h"
#implementation CALayer(XibConfiguration)
-(void)setBorderUIColor:(UIColor*)color
{
self.borderColor = color.CGColor;
}
-(UIColor*)borderUIColor
{
return [UIColor colorWithCGColor:self.borderColor];
}
#end
The result will be apparent during runtime, not in Xcode.
You can set most of those in the interface builder adding runtime attributes to the elements:
For layer.borderWidth = 2.0f; would be:
Select the button and add a new attribute
keypath : layer.borderWidth
type: Number
Value 2
These changes will not be visible inside the interface builder, only at runtime
yes u can
in the right side click on identity inspector, u will find like this
click + in User Defined Runtime Attributes
select keypath and edit it
write the code like this
layer.cornerRadius and in Type change the type to number and set ur required value like this
u can also change text colors and so many.
Happy coding

How to change UITableView border color in Xcode

Anybody knows how to change UITableView border color in storyboard. I am using Xcode.
Try this in User Defined Runtime Attributes set the key path and value
You can probably use User Defined Runtime Attributes to set borderColor or borderWidth through XIB or Storyboard. You will need to select your view and then click on Identity inspector. You will see "User Defined Runtime Attributes" where you can set the borderColor for your tableView.
borderColor on any view(or UIView Subclass) could also be set using storyboard with a little bit of coding and this approach could be really handy if you're setting border color on multiple UI Objects.
Below are the steps how to achieve it,
Create a category on CALayer class. Declare a property of type UIColor with a suitable name, I'll name it as borderUIColor .
Write the setter and getter for this property.
In the 'Setter' method just set the "borderColor" property of layer to the new colors CGColor value.
In the 'Getter' method return UIColor with layer's borderColor.
P.S: Remember, Categories can't have stored properties. 'borderUIColor' is used as a calculated property, just as a reference to achieve what we're focusing on.
Please have a look at the below code sample;
Objective C:
Interface File:
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
#interface CALayer (BorderProperties)
// This assigns a CGColor to borderColor.
#property (nonatomic, assign) UIColor* borderUIColor;
#end
Implementation File:
#import "CALayer+BorderProperties.h"
#implementation CALayer (BorderProperties)
- (void)setBorderUIColor:(UIColor *)color {
self.borderColor = color.CGColor;
}
- (UIColor *)borderUIColor {
return [UIColor colorWithCGColor:self.borderColor];
}
#end
Swift 2.0:
extension CALayer {
var borderUIColor: UIColor {
set {
self.borderColor = newValue.CGColor
}
get {
return UIColor(CGColor: self.borderColor!)
}
}
}
And finally go to your storyboard/XIB, follow the remaining steps;
Click on the View object for which you want to set border Color.
Click on "Identity Inspector"(3rd from Left) in "Utility"(Right side of the screen) panel.
Under "User Defined Runtime Attributes", click on the "+" button to add a key path.
Set the type of the key path to "Color".
Enter the value for key path as "layer.borderUIColor". [Remember this should be the variable name you declared in category, not borderColor here it's borderUIColor].
Finally chose whatever color you want.
Edit: You've to set layer.borderWidth property value to at least 1 to see the border color.
Build and Run.
Happy Coding. :)
Try following code
#import "QuartzCore/QuartzCore.h"
tableview.layer.borderWidth = 1.0;
tableview.layer.borderColor = [UIColor lightGrayColor].CGColor;

Objective-C, border color not working with UIColor

I can set the border color using the following code:
[[self.single layer] setBorderColor:[[UIColor colorWithRed:178.0f/255.0f green:178.0f/255.0f blue:178.0f/255.0f alpha:1.0] CGColor];
and it works just fine. But I need to apply this to multiple borders, so I tried the following:
.h
#property (weak, nonatomic) UIColor *appColor;
.m
within viewDidLoad
self.appColor = [UIColor colorWithRed:178.0f/255.0f green:178.0f/255.0f blue:178.0f/255.0f alpha:1.0];
and then later, where the previous color assignment was
[[self.single layer] setBorderColor:[self.appColor CGColor]];
But this does not work - the border comes out black (regardless of what I set for self.appColor). I have also tried [[self.single layer] setBorderColor:self.appColor.CGColor]; with no success. How can I define a UIColor variable just once, but use it to assign border colors in multiple places?
Change this line:
#property (weak, nonatomic) UIColor *appColor;
To:
#property (nonatomic, strong) UIColor *appColor;
And see if this helps you.

Change foregroundColor of a UIView

Is there a way to change the foregroundColor of a UIView?
I'm creating an arrow using an UIView (drawRect) like this ">", with a clear background, only two black lines. This is working great. But afterwards I would like to change the color of the ">" from black to red, for example. Would be nice to have an animation in it, like a gradient from black to red, using CAKeyframeAnimation. I can do it for borderColor and backgroundColor but these properties are not the ones that I'm looking for.
I'm changing the borderColor of another UIView using this block of animation. I would like to do the same with the foregroundColor but it's not working in iOS.
CAKeyframeAnimation* colorAnim = [CAKeyframeAnimation animationWithKeyPath:#"borderColor"];
NSArray* colorValues = [NSArray arrayWithObjects:(id)[UIColor blackColor].CGColor,(id)[UIColor redColor].CGColor, nil];
colorAnim.values = colorValues;
colorAnim.calculationMode = kCAAnimationPaced;
colorAnim.duration = 5.0;
colorAnim.repeatCount = 1;
[self.myView.layer addAnimation:colorAnim forKey:#"borderColor"];
I appreciate any help, thanks!
The UIView class does not have a foregroundColor property, so you have to implement it yourself. In your UIView subclass interface, define the property:
#property (nonatomic, strong) UIColor *foregroundColor;
In your subclass implementation, override the setForegroundColor: setter method:
- (void)setForegroundColor:(UIColor *)newForegoundColor
{
_foregroundColor = newForegroundColor;
[self setNeedsDisplay]; // This is need so that drawRect: is called
}
In whichever initialiser you're are using in the subclass, set the foregroundColor property to a default:
self.foregroundColor = [UIColor blackColor];
In your drawRect: implementation, use the foregroundColor property to stroke the chevron you are drawing:
CGContextSetStrokeColorWithColor(context, self.foregroundColor.CGColor);

Resources