Manually setting UI button border width - Swift editor - swift

I have a requirement to create several UI buttons and want to initialize the border width of each of them as and when these buttons are created and organize them in the screen.
The Xcode swift editor has properties to configure several attributes of an UI button, but I don't see a way to set the border width. Another option is to do it through code like
button.layer.borderWidth = 1
But if I create n buttons I need to insert n outlet references to set the border width of each of them, which I don't want to do. Is there any easy solution so that once I have one button created with a given border width, then I can create replicas with copy-paste.

You can do something like this programmatically.
for view in self.view.subviews
{
if view.isKindOfClass(UIButton)
{
view.layer.borderWidth = 1
}
}

You can create custom class extend UIButton.
class BorderButton : UIButton {
init(frame: CGRect) {
super.init(frame: frame)
layer.borderWidth = 1
}
}
And more, you want to customize borderWidth value like this:
#IBDesignable
class BorderButton : UIButton {
#IBInsepctable borderWidth: CGFloat = 0 {
didSet {
layer.borderWidth = borderWidth
}
}
init(frame: CGRect) {
super.init(frame: frame)
borderWidth = 1
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
borderWidth = 1
}
}
Using #IBDesignable and #IBInspectable, you can set borderWidth value from storyboard.

Related

NSTextField created from custom class appears randomly

I have a main NSView with 2 NSView subviews containing each a custom NSButton (all created in Interface Builder). My custom button class is programmatically creating an NSTextField below the buttons, by adding it from the superview:
And the custom NSButton class code:
class buttonUpDown: NSButton {
var myLabel:NSTextField!
required public init?(coder: NSCoder) {
super.init(coder: coder)
let labelWidth=CGFloat(90)
print("init")
superview?.autoresizesSubviews = false
myLabel = NSTextField(frame: NSMakeRect(frame.origin.x+frame.size.width/2-labelWidth/2,frame.origin.y-20,labelWidth,16))
myLabel?.stringValue = "Mesh Quality"
myLabel.alignment = .center
myLabel.font? = .systemFont(ofSize: 8)
myLabel.backgroundColor = .red
myLabel.isBordered = false
myLabel.isEditable = false
superview!.addSubview(myLabel)
}
}
When I have a single Button referencing the class, the label appears properly.
But when I have 2, only 1 label is appearing randomly left or right:
What do I miss to have a text displayed below each button ?
Found the issue. Creating a label in the init function will give erratic positioning of the view frame. Adding them from the draw func, makes it more reliable.

Setting Corner Radius in Draw for UIImageView

I am setting some properties in the draw method of my UIImageView. However, these do not seem to be taking any affect at all. I see no rounded corners and no masking taking affect. The view is below:
//
// RoundImage.swift
//
//
import UIKit
class RoundImage: UIImageView {
//------------------
//MARK: - Setup and Initialization
//------------------
override init(frame: CGRect) {
super.init(frame: frame)
self.initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialize()
}
override func draw(_ rect: CGRect) {
super.draw(rect)
self.layer.cornerRadius = 30
self.layer.masksToBounds = true
self.clipsToBounds = true
}
//Setups content, styles, and defaults for the view
private func initialize(){
self.initStyle()
}
//Sets static content for the view
private func staticContent() {
}
//Styles the view's colors, borders, etc at initialization
private func initStyle(){
}
//Styles the view for variables that must be set at runtime
private func runtimeStyle(){
//TODO: These values cannot be changed in interface builder, but they should be able to be
}
//------------------
//MARK: - Interface Builder Methods
//------------------
//Sets the view up for interface builder with runtime styling and temp display values
override func prepareForInterfaceBuilder() {
self.runtimeStyle()
self.staticContent()
}
//------------------
//MARK: - Lifecycle Methods
//------------------
//Sets the view up with runtime styling and values
override func awakeFromNib() {
super.awakeFromNib()
self.runtimeStyle()
self.staticContent()
}
}
UIImageView when subclassed does not call the draw method at all. It is not allowed, although minimally documented. In this case, it is recommended to subclass UIView and then draw the image on the view in your draw method yourself.
For further information:
drawRect not being called in my subclass of UIImageView

UIButton Subclass using its size to set corner radius with Autolayout

I have the following subclass of UIButton just to give a circular border to a UIButton, assuming height and width of UIButton are set equal. But when auto layout does its job I do not get the correct radius. How can I change this class to behave correctly with auto layout?
import UIKit
class CircularButton: UIButton {
required init?(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)
self.layer.cornerRadius = self.bounds.size.height / 2
self.layer.borderWidth = 1
}
}
Always call:
setNeedsLayout()
layoutIfNeeded()
before accessing a view's frame or bounds when using AutoLayout. Otherwise, your accessing the view's size before its been set by AutoLayout. Calling these two methods forces an AutoLayout pass, allowing you to access the view's correct size.
Also, you should set the corner radius in awakeFromNib instead of init.

sectionInset not working with UICollectionView estimatedItemSize in iOS8 using AutoLayout

I can't get my UICollection to properly set sectionInset.left margin when using self-sizing cells with estimatedItemSize. Cells of the UICollectionview should have a somewhat fixed cell height but dynamic width according to the text length.
Here is how it looks when the self-sizing is enabled:
And when the self-sizing is disabled:
Oddly enough, it seems that sectionInset.right is working, i.e. the margin is added on the right hand side of the UICollectionView.
Here's my custom UICollectionViewFlowLayout, i'm toggling self-size mode using the comment.
class myFlow: UICollectionViewFlowLayout {
required init(coder: NSCoder) {
super.init(coder: coder)
self.minimumLineSpacing = 1
// self.estimatedItemSize = CGSize(width: 100, height: 35)
self.sectionInset.left = 20
}
And my custom UICollectionView:
class myCV: UICollectionView {
required init(coder decoder: NSCoder) {
super.init(coder: decoder)
self.layer.cornerRadius = 5.0
self.layer.borderWidth = 1.0
self.layer.borderColor = UIColor.lightGrayColor().CGColor
}
}
I've laid out the label inside the UICollectionView cell using AutoLayout:
I've found a work around this - use contentInset property of UIScrollView, that is super class of UICollectionView. It is not strictly saying is answer, but, at least, a solution of the problem

swift IBDesignable view not show in storyboard

I want to custom a 5-star UIView,also I want it to be render in storyboard. So I decide to use #IBDesignable and #IBInspectable.The following is my code.
import UIKit
#IBDesignable
class RatingView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
setUpView()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setUpView()
}
func setUpView() {
let imageView = UIImageView(frame:CGRectMake(0, 0, 50,50))
imageView.image = UIImage(named: "star")
addSubview(imageView)
}
}
And then in my storyboard , I pull a UIView into my canvas,and set Custom class to my custom view as RatingView.The compiler starts to compile storyboard file and I just wait for the custom view to be renderd in canvas.Here is the screenshot.
The state is "up to date",but the view has not been renderd.The view is just staying white,what I want to see is the image I add to the parent view.
When I use UILabel instead of UIImageView, the label is renderd in the canvas but not the UIImageView,how can I render my lovely star image in my canvas.(Images.xcassets has star.png file)
use UILabel instead of UIImageView
func setUpView() {
let label = UILabel(frame: CGRectMake(0, 0, 50, 50))
label.text = "text"
addSubview(label)
}
result:
I was trying to do the same exact thing. You need to put the view in a framework. As #Benson Tommy said in the comments take a look at WWDC 2014 session 411.
Here is a link to the session:https://developer.apple.com/videos/wwdc/2014/#411
Here is a link to the transcript of the session: http://asciiwwdc.com/2014/sessions/411