How can I extend UITextField without losing functionality? - ios

I need to extend my UITextField class in order to store some additional properties:
class UICustomTextField : UITextField{
var item = Item()
}
But when I do this:
let textField = UICustomTextField()
The keyboard covers up the TextField. Without extending the class it and use of UITextField directly it works.
There is any workaround ?

Related

UiTextField inside UiStackView is not responding

Goal: I'm building a time sheet using swift ui.
Question: At the top I have class A that inherits from UiViewController. It lays out a UiStackView in a vertical stack to divide the screen into three: top,center,bottom. I'm having issues inside the center view. I can only get interaction with the UiTextField inside the center if I add it directly.
Inside the center view, I have a class B that inherits from UiView. Within the class I have another UiStackView that will add a horizontal stack to layout some items nicely.
I've made a class C in the same file outside of the center view class, and it inherits from UiView. It contains a UiTextField that I setup and add.
Here's where things get weird, I can do inside class B, and I will be able to work with the UiTextField just fine:
`let temp = ClassC (inherits UiView)
self.addSubView(temp)` <- works
`ClassBUiStackView.addSubView(ClassC)
UiView temp = UiView(...)
temp.addSubView(ClassBUiStackView)
self.addSubView(temp)` <- fails
Let me provide some actual code:
`class A: UiViewController{
override func viewDidLoad(){
super.viewDidLoad()
self.top = ...
self.cnr = Class B
self.btm = ...
self.ClassAUiStackView(arrangedSubviews: [top,cnr,btm])
...constraints...
self.view.addSubview(ClassAUiStackView)
}
}
class B: UiView{
override init(...){
super.init(...)
self.ClassBUiStackView(...x,y,width,heigh...)
...constraints...
let temp = UiView(...)
self.ClassBUiStackView.addSubView(ClassC)
temp.addSubView(ClassBUiStackView)
}
}
class C: UiView{
var UiTF: UiTextField!
required init(..., classB, ...){
...setup UiTf...
self.UiTF.addTarget(self, action: #selector(uitfAction), for: .allEvents)
self.addSubView(UiTf)
}
#objc func uitfAction(senderL UITextField!){
...some action...
}
}
`
Any help on this would be much appreciated. This is my first Swift app so I'm still a newbie. Please elaborate as much, I will read it all (multiple-times). Thank you !
i found the answer that will make all my ui components responsive again, i had to add uiStackView.translatesAutoresizingMaskIntoConstraints = true, if this is taken away or set to false, the ui components do not respond.

Round button on custom class with UIAppearance

I am trying to apply styles on a custom class using UIAppearance()
class MainStyleButton: UIButton {}
with a code:
let buttonView = MainStyleButton.appearance()
buttonView.backgroundColor = Style.buttonColor
buttonView.layer.cornerRadius = 5
buttonView.layer.borderWidth = 5
buttonView.layer.borderColor = Style.buttonColor.cgColor
It works with color, but unfortunately doesn't make my button round. I would appreciate any tips.
Tested on simulator iPhone X, 8 with iOS 11.2.
I tried replicating your approach and set up a button. I tried to change the button's appearance in a UIViewController during viewDidLoad and also in the AppDelegate during applicationDidFinishLaunching using your code. I additionally tested changing the button type to .custom from the default type .system. None of this seemed to work, I could not override the same attributes that you couldn't.
From Apple's docs I understand that the button type defines its appearance and also which appearance attributes can be overridden:
A button’s type defines its basic appearance and behavior. You specify the type of a button at creation time using the init(type:) method or in your storyboard file. After creating a button, you cannot change its type.
I do not know why the attributes of interest to you are not changeable at this point
However I would like to offer a different approach that I personally use and allows you to change the buttons appearance. Since you already defined your custom class it is much simpler to define corner radius and other attributes that you would like, like so (or you could write a style function with parameters that you can call at any time, to be able to change the appearance based on where the button is used):
class MainStyleButton: UIButton {
override func awakeFromNib() {
layer.borderColor = Style.buttonColor.cgColor
layer.borderWidth = 5
layer.cornerRadius = 5
}
}
Or you can instantiate/use an IBOutlet for a system button and do this:
class MyViewController: UIViewController {
#IBOutlet weak var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// not necessary to do this is viewDidLoad, that's just my example
myButton.layer.borderColor = Style.buttonColor.cgColor
myButton.layer.cornerRadius = 5
myButton.layer.borderWidth = 5
}

Lazy UILabel property of custom control

I want to be able to set the title of my custom control in interface builder and implement the title as a UILabel. I have created my properties thus:
#IBInspectable var titleText: String? {
get {
return title.text
}
set(newTitleText) {
title.text = newTitleText
}
}
#IBInspectable lazy var title: UILabel = UILabel.init()
Is this a good/recommended way to do this? I also want the control to layout the UILabel if the title text has been set and plan to do this by overriding layoutSubviews - again is this recommended or would you suggest a different pattern?
My ultimate aim is to be able to enable a designer to configure my control from IB and exposing the UILabel as a property that can be configured in IB would be my ideal.
#IBInspectable can be used only with the following types:
Int
CGFloat
Double
String
Bool
CGPoint
CGSize
CGRect
UIColor
UIImage
So, no, you can not "expose a UILabel" for design-time manipulation.
First, I don't think that you need to make your variable lazy here, also, if you want to create a new instance of UILabel, it's better to user the constructor UILabel().
Now, I am not sure if I understand correctly your question, but if I did, then you can expose your custom view properties (a string that represents your title label for example) to the Attributes Inspector.
You would do it like so:
#IBDesignable
class CustomView: UIView {
#IBOutlet weak var titleLabel: UILabel!
#IBInspectable var title: String? {
didSet { self.titleLabel.text = title }
}
}
To break up the code above :
First you make the class (your custom view) #IBDesignable so that it supports live preview in the Interface Builder.
Then, inside your custom view class, you create a title property (which is a String) and make sure to make it #IBInspectable so that you can change this property later via the Attributes Inspector.
Finally you add a property observer ( didSet ) so that the text property of your custom label is updated whenever you change the title property from the Attributes Inspector.

Override UI element .enabled property in Swift

I want to override property of UIView class to do extra lines of code each time property value of .enabled is changed. How do I do that?
For example:
There is MyUIView class myClass
There is myClass.enabled property
I want to override this to add next things
Edit subview of type UIView and set background to red colour if enabled/green if disabled.
Edit subview of type UIButton and make it disabled if disabled/enabled if enabled.
The code will look something like this -
class SubClass: UIView {
override var userInteractionEnabled: Bool {
didSet {
// Do the color change and other stuff.
// Use oldValue to access old value
}
}
}
There is much more to explore about this setter and getter.

Need to get placeholder text of UITextField

Is it possible to get the placeholder value of UITextField, which is designed in storyboard?
I need to validate the form which is having more textfields, so instead of giving static value, I want to give placeholder string of particular textfield as alert message.
Use the placeholder property:
textField.placeholder
For placeholder first you should create IBOUTLET for textfield and then do:
if let str = textfiled.placeholder {
if !str.isEmpty {
//do something
}
}
The UITextField class has a placeholder property. To reference the UITextField in code, you'll need to create an outlet for it in your view controller.
If you named the outlet myTextField, you could reference the placeholder like this:
let placeholder = self.myTextField.placeholder
Its work ...
For getting placeholder text you need to wire up your textfield with its IBOutlet object like,
#IBOutlet var txtField : UITextField?
Now you set Placeholder Statically or dynamically
self.txtField!.attributedPlaceholder = NSAttributedString(string:"Good", attributes:[NSForegroundColorAttributeName: UIColor.grayColor()])
After that anywhere you can simply get its placeholder text and compare or validate ur textfield like
if((self.txtField!.placeholder! as NSString).isEqualToString("Good"))
{
// Do here Whatever you want
}
else if(self.txtField!.placeholder!.isEmpty == true)
{
// check its empty or not
}
Simply write like below code,
if((self.myTextFiled!.placeholder! as NSString).isEqualToString("AnyString"))
{
// your code here
}

Resources