Add subviews without losing focus (firstResponder status) on NSView - swift

How can I add subview without losing firstResponder status?
let scrollAreaRect = self.finalFrame
let scrolledView = NSView(frame: scrollAreaRect)
// Inserisco pulsanti di esempio
for i in 1 ... 10{
let bt = LevelButton(frame: NSRect( x: 0,
y: i*30,
width: Int(scrolledView.frame.width),
height: 30),
name: "Primo Livello",
number: 1)
scrolledView.addSubview(bt)
}
scrolledView.resignFirstResponder()
scrollView = NSScrollView(frame: scrollAreaRect)
scrollView.resignFirstResponder()
scrollView.documentView = scrolledView
scrollView.contentView.scrollToPoint((NSMakePoint(0, scrolledView.frame.size.height)))
self.addSubview(scrollView)
After run that code in initializer function, the NSView not calls more keyDown handle. How can I reassign firstResponder status to main view? Call resignFirstResponder on all subviews not works.

Related

resignFirstResponder is not working as expected.the key board pop's down for every key press rather than for return only

i have 3 UITextField. when i set the resignFirstResponder for the text field, for every key press the key board goes down and key board pops up when we enter. which means for each letter pressed the key board disappears
I tried creating an outlet for the text field as below but the print statement is executed but the key board is not getting disappeared when focus lost or moved to the next text field
#IBAction func done(_ sender: UITextField) {
print("Text field done$$$$$$$$$$$$$$$")
sender.endEditing(true)
sender.resignFirstResponder()
// print("After Resign")
}
tried the below one also:
self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
//Textfield
let textfield = UITextField()
textfield.setShadowTextField(username, "user-name")
textfield.setShadowTextField(useremail, "email")
textfield.setShadowTextField(userPhone, "phone")
//Hide Keyboard
textName.resignFirstResponder()
textEmail.resignFirstResponder()
userPhone.resignFirstResponder()
//
name = textName.text ?? ""
emailphone = textEmail.text ?? ""
//Button
if isFirstTimeSubView == true {
button?.setSemiButtonLeft(btnFemaleSelector, shadowViewFemale)
button?.setGradientButton(btnFemaleSelector, startColor: "0d5e90", endColor: "8ec67d")
button?.setSemiButtonRight(btnMaleSelector, shadowViewMale)
button?.setGradientButton(btnMaleSelector, startColor: "FFFFFF", endColor: "FFFFFF")
isFirstTimeSubView = false
}
button?.setRoundButton(btnSubmit, shadowView)
button?.setGradientButton(btnSubmit, startColor: "0d5e90", endColor: "8ec67d")
//textNam.sendAction("resignFirstResponder", to:nil, from:nil, forEvent:nil)
// self.userText.delegate = selftextName.resignFirstResponder()
}
extension UITextField {
func setShadowTextField(_ textfield: UITextField?, _ imagename: String?) {
// set color & border
textfield?.borderStyle = .none
textfield?.backgroundColor = UIColor.white
// set corner
textfield?.layer.cornerRadius = (textfield?.frame.size.height ?? 0.0) / 2
//set shadow
textfield?.layer.shadowOpacity = 0.4
textfield?.layer.shadowRadius = 15
textfield?.layer.shadowOffset = CGSize(width: 5, height: 10)
textfield?.layer.shadowColor = UIColor.gray.cgColor
// set icon & Placeholder position
let UIViewController = UIView(frame: CGRect(x: 0, y: 0, width: 60, height: textfield?.frame.size.height ?? 0.0))
let icon = UIImageView(image: UIImage(named: imagename ?? ""))
icon.frame = CGRect(x: 0, y: 0, width: UIViewController.frame.size.width / 4, height: UIViewController.frame.size.height / 4)
icon.center = UIViewController.center
UIViewController.addSubview(icon)
textfield?.leftView = UIViewController
textfield?.leftViewMode = .always
}
}
The question is a little unclear but if you want the keyboard to go down when you've pressed the done button, you should implement the UITextFieldDelegate on your view controller and during the textFieldShouldReturn(_:) method call resignFirstResponder from there:
class myVC: UIViewController, UITextFieldDelegate{
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
return true
}
}
and don't forget to set the delegate in the viewDidLoad for your VC:
override func viewDidLoad() {
super.viewDidLoad()
/// Text field delegate handling
textFieldFirstName.delegate = self
}
https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619603-textfieldshouldreturn?language=objc
By calling resignFirstResponder in viewDidLayoutSubviews, you are resigning the responder every time the viewDidLayoutSubviews is called, i.e. When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method. So I presume the keyboard will be changing the bounds, causing viewDidLayoutSubviews to fire after each keypress and creating the behaviour you are seeing

Add action to button in .xib file Using Swift(4.0)

I implemented horizontal(Paging) slide show of views, created separate xib and integrated with the view controller. Slide show is working as expected but I want add action to the every views so that from there I can move directly to the respective main content pages. Find the below code for implementation of slide show.
func createSlides() -> [Slide] {
let slide1:Slide = Bundle.main.loadNibNamed("Slide", owner: self, options: nil)?.first as! Slide
slide1.labelTitle.text = "Page1"
let slide2:Slide = Bundle.main.loadNibNamed("Slide", owner: self, options: nil)?.first as! Slide
slide2.labelTitle.text = "Page2"
return [slide1, slide2]
Slide Function
func setupSlideScrollView(slides : [Slide]) {
scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
scrollView.contentSize = CGSize(width: view.frame.width * CGFloat(slides.count), height: view.frame.height)
scrollView.isPagingEnabled = true
for i in 0 ..< slides.count {
slides[i].frame = CGRect(x: view.frame.width * CGFloat(i), y: 0, width: view.frame.width, height: view.frame.height)
scrollView.addSubview(slides[i])
}
}
Xib file
class Slide: UIView {
#IBOutlet weak var labelTitle: UILabel!
var onClickCallback: (() -> Void)?
override init (frame : CGRect) {
super.init(frame : frame)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
}
If I think what you are asking is right then do this. (BTW I am a bit rusty at this so please don't crucify me if I'm wrong). Also I don't know where you are designing this so I am going to assume it is in a different place to main.viewcontroller. If it isn't just add a button and create a segue to the content page.
Make a public var in createSlides Func and set it to the slide you are on. Eg: Slide 1. When slide two is opened it should update the var two slide two. For the sake of this we will call the var test
Add a button into your design file
Add a #IBAction into the viewcontroller. This #IBAction should be linked with your button.
inside this #IBAction create a segue to the content using the variable we created before. self.performSegue(withIdentifier: test, sender: self)
In the main view controller add two segues from the view with the slidshow to the view controller with the content (Assuming you only have two slides). One segue should be called slide 1 (The same name as the let you created in createSlides func.) The second should be called slide 2 (for obvious reasons.)
Now when your button in slide 1 is pressed it should perform the segue slide 1 and show your main content
Hope I helped, Toby.
Also if this doesn't work, is not what you want to achieve or is badly worded please comment what it is and I will try to fix it.
call this function and pass pageIndex where you want to jump:
func jumpToView(_ index : Int) {
let offset = CGPoint(x: view.frame.width * CGFloat(index), y: 0)
scrollView.setContentOffset(offset, animated: true)
}
Hope this what you are looking.
First line in function let offset = CGPoint(x: view.frame.width * CGFloat(index), y: 0), for calculate position where you want to move in scrollview. E.g : for first xib position will be CGPoint(x:0,y:0) and for 3rd xib, position will be CGPoint(x:200,y:0), consider each xib width is 100
setContentOffset use to scroll at specific location/point.
For more check Link

Can't set var in subview

I have an app with a UIViewController with custom UIViews in it. I want to set a variable in that custom UIView and it doesn't update...
I have done this a thousand times and it always worked but this time it doesn't and I really can't figure out what I'm doing wrong, any help is welcome!
In my viewcontroller:
var sjablonview: sjablonPicker!
sjablonview = sjablonPicker(frame: CGRect(x: btnUndo.frame.origin.x, y: DrawingView.frame.origin.y,
width: (btnX.frame.origin.x + btnX.frame.size.width) - btnUndo.frame.origin.x, height: 250))
sjablonview.alpha = 1
sjablonview.mpUitklapping = 300
self.view.addSubview(sjablonview)
In my custom UIView:
class sjablonPicker: UIView {
var mpUitklapping = CGFloat(100)
override init(frame: CGRect){
super.init(frame: frame)
print(mpUitklapping) // --> output = 100 and not 300
...
You are printing from inside your initialiser. Your view is initialized before you change the value of mpUitklapping. Your initializer gets called from this line:
sjablonview = sjablonPicker(frame: CGRect(x: btnUndo.frame.origin.x, y: DrawingView.frame.origin.y, width: (btnX.frame.origin.x + btnX.frame.size.width) - btnUndo.frame.origin.x, height: 250))
The value gets changed, you just don't print the updated value.

create scrollview programmatically in swift without outlet

I have tried enough but i don't understand what is wrong with code, it was working fine when I created an outlet, but then I found out that i don't need an outlet, so want to create it just programmatically.
var BestPractices = UIScrollView(frame: CGRectMake(0, 94, 768, 924))
BestPractices.hidden = true
I cannot access the properties of "BestPractices" in viewController , while same code works fine in playground
This is an answer from this question.
.
class ScrollingViewController : UIViewController {
// Create a scrollView property that we'll set as our view in -loadView
let scrollView = UIScrollView(frame: UIScreen.mainScreen().bounds)
override func loadView() {
// calling self.view later on will return a UIView!, but we can simply call
// self.scrollView to adjust properties of the scroll view:
self.view = self.scrollView
// setup the scroll view
self.scrollView.contentSize = CGSize(width:1234, height: 5678)
// etc...
}
func example() {
let sampleSubView = UIView()
self.view.addSubview(sampleSubView) // adds to the scroll view
// cannot do this:
// self.view.contentOffset = CGPoint(x: 10, y: 20)
// so instead we do this:
self.scrollView.contentOffset = CGPoint(x: 10, y: 20)
}
add this line to identify scroll bar at last of loadview().
scrollView.backgroundColor = UIColor.blue

How to update UILabel that is a subview of inputView?

I have UITextView where user types a text. When the keyboard is shown, I add inputView with UIlabel on it. I want this UIlabel to hold character length of the text. It seems very easy task, but unfortunatelly it does not update this word counter UILabel when user change text..
this is how I load the inputView
_textView.inputView = [self inputAccessoryView];
in inputAccessoryView I simply add UILabel as a subview. When keyboard is show, UILabel is also show with inputView. I track changes on
- (void)textViewDidChange:(UITextView *)textView
unfortunatelly the UILabel is never updated (redrawn). When I log in to console its value, the value is correct, so its updating, but the UIlabel is never redrawn and holds the default value.
Can anyone help me with this?
did you
_textView.delegate = self;
?
I know it was 5 years ago, but it might help others, who like me stumble upon your question.
I use a UIToolbar as my inputAccessoryView (in my case it has a label, a flexible separator and a button).
On textFieldEditingChanged event I rebuild part of the toolbar like this
#IBAction func textFieldEditingChanged(_ sender: UITextField) {
//get a reference to the toolbar
let toolBar = sender.inputAccessoryView as! UIToolbar
//create a new label and set size + other properties
toolbarLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 40, height: 22))
toolbarLabel.text = mySpecificCalculatedString(sender.text!)
toolbarLabel.font = defaultFont(17)
toolbarLabel.adjustsFontSizeToFitWidth = true
let width = toolbarLabel.textRect(forBounds: CGRect(x: 0, y: 0, width: maxWidthForLabel, height: 0), limitedToNumberOfLines: 1).size.width
toolbarLabel.frame = CGRect(x: 0, y: 0, width: width, height: 22)
toolbarLabel.textColor = .black
toolbarLabel.tag = 666
//rebuild the specific tolbar item
let customView = UIBarButtonItem(customView: toolbarLabel)
toolBar.items![0] = customView
}
Note: simply changing the text of the label did not work for me either, I had to reinitialize it.
Hope it helps.