Trouble getting button in custom uiview to respond to touch - ios

So I have a custom UIView with a button in it, called the home button. In other view controllers, this home button within this particular UIView works just fine. In one particular view controller, however, the home button is non responsive to touches- the app acts as though the button is not even there.
class TemplateChooserViewController: UIViewController, HeaderViewDelegate {
...
#IBOutlet weak var myHeader: HeaderView!
override func viewDidLoad() {
super.viewDidLoad()
myHeader.delegate = self
myHeader.Title.text = "Template Chooser"
... //All the rest of this function has been commented out and the home button still didn't work
}
func homeButtonTapped()
{
let home = self.navigationController?.viewControllers.first //code never reaches here
self.navigationController?.popToViewController(home!, animated: false)
}
And the HeaderView file looks like:
protocol HeaderViewDelegate: class {
func homeButtonTapped()
func informationButtonTapped()
}
class HeaderView: UIView {
weak var delegate: HeaderViewDelegate?
#IBOutlet var view: UIView!
#IBOutlet weak var Title: UILabel!
#IBOutlet weak var flameDecal: UIImageView!
#IBOutlet weak var homeButton: UIButton!
required init(coder aDecoder: NSCoder)
{
super.init(coder: aDecoder)!
Bundle.main.loadNibNamed("HeaderView", owner: self, options: nil)
self.addSubview(self.view)
}
#IBAction func homeButtonTouched(_ sender: UIButton)
{
delegate?.homeButtonTapped() //Code also doesn't reach here
}
#IBAction func infoButtonTouched(_ sender: UIButton) {
delegate?.informationButtonTapped()
}
}
Keep in mind the code compiles fine, so I did have the infoButtonTouched function implemented, I just didn't see the point in showing it. I have no idea why the button is unresponsive. Any ideas on how to get the button to respond would be most helpful. Thanks for your consideration of this matter.
Sincerely,
Sean

Related

UISwitch value inside a nib does not being updated

My switch is inside of a nib which is inside of a tableview header. When I click the switch it only does the pushSwitch.isOn and not !pushSwitch.isOn. It only gives me the values inside of the pushSwitch and doesn't seem to go inside of !pushSwitch.isOn
Thanks
protocol PhoneNotificationHeaderViewDelegate: class {
func copyPreferredSettingsRequested()
func textNotificationSwitchTapped()
func pushNotificationSwitchTapped()
}
class PhoneNotificationHeaderView: UITableViewHeaderFooterView {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var textSwitch: UISwitch!
#IBOutlet weak var pushSwitch: UISwitch!
#IBOutlet weak var copyPreferredSettingsButton: UIButton!
#IBOutlet weak var notificationView: UIView!
weak var delegate: PhoneNotificationHeaderViewDelegate?
UIApplication.shared.keyWindow?.rootViewController?.present(alertController, animated: true, completion: nil)
}
#IBAction func textNotificationSwitchTapped(_ sender: AnyObject) {
self.delegate?.textNotificationSwitchTapped()
}
#IBAction func pushNotificationSwitchTapped(_ sender: UISwitch) {
self.delegate?.pushNotificationSwitchTapped()
}
#IBAction func copyPreferredSettingsButtonTapped() {
self.delegate?.copyPreferredSettingsRequested()
}
override var backgroundColor: UIColor? {
didSet {
print("backgroundColor")
}
}
Here is my switch inside my VC:
extension PhoneNotificationViewController: PhoneNotificationHeaderViewDelegate {
func pushNotificationSwitchTapped() {
guard let phoneNotificationHeader = Bundle(for: type(of: self)).loadNibNamed("PhoneNotificationHeaderView", owner: self, options: nil)?.first as? PhoneNotificationHeaderView else {
return
}
if phoneNotificationHeader.pushSwitch.isOn{
//Disable Firebase from sending
Globals.sharedInstance.pushStatus = true
phoneNotificationHeader.pushSwitch.setOn(false, animated: true)
}else{
Globals.sharedInstance.pushStatus = false
phoneNotificationHeader.pushSwitch.setOn(true, animated: true)
}
self.refreshUI()
}
There is no such thing as a "a nib which is inside of a tableview header". Every time you load a nib by saying loadNibNamed, you get a fresh copy of the view that it contains. So every time you call pushNotificationSwitchTapped you are a getting a whole new switch fresh from the nib, and sticking it in your interface. That is probably not what you intend! And of course the switch comes from the nib in only one state, namely the state that you set it in the nib editor: it is On.
You need to abandon completely this incorrect architecture based on a misapprehension about what a nib is. You should load the nib once, and from then on you should refer to the switch by talking to the switch itself, the one that is now in your interface.

Resize a UIView inside a stackview

I need help to accomplish this:
Its a group of 3 photos. The first photo is the button screen before the click, the second photo is the screen after the click and the third photo is the way i've designed in the IB using stackview
I've being trying to create this and this is the result i've got so far. I still haven't created anything as the After button click image shows because of this:
My Result now
As you can see in the gif when i press the button, the UIView height constraint.constant is set to a higher value and the UIView get higher. All i want is the stripped background to get higher as well.
This is the way the view is disposed in IB.
And finally, this is the way i've coded
class LetterScreenViewController: UIViewController, ResizeWordViewDelegate {
#IBOutlet weak var youTubeView: YouTubeView!
#IBOutlet weak var phonemeView: PhonemeView!
#IBOutlet weak var wordView: WordView!
var letterPresenter: LetterPresenter?
#IBOutlet weak var heightWordViewConstraint: NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
delegateWordObj()
if let presenter = letterPresenter {
presenter.setupView()
}
}
#IBAction func dismissLetter(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
func delegateWordObj() {
wordView.resizeWordViewDelegate = self
}
func didPressButton() {
if heightWordViewConstraint.constant <= 0 {
heightWordViewConstraint.constant = 30
}else{
heightWordViewConstraint.constant = 0
}
}
}
import UIKit
protocol ResizeWordViewDelegate {
func didPressButton()
}
class WordView: UIView {
#IBOutlet weak var backgroundListras: UIImageView!
#IBOutlet var WordView: UIView!
#IBOutlet weak var showWordButton: UIButton!
var resizeWordViewDelegate: ResizeWordViewDelegate!
override init(frame: CGRect) {
super.init(frame: frame)
xibInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
xibInit()
}
func xibInit() {
Bundle.main.loadNibNamed("WordView", owner: self, options: nil)
addSubview(WordView)
WordView.frame = self.bounds
WordView.round(corners: [.topLeft,.topRight], radius: 120)
WordView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
}
#IBAction func showWordButtonAction(_ sender: Any) {
resizeWordViewDelegate.didPressButton()
self.frame.size = CGSize(width: 375, height: 200)
self.backgroundListras.frame.size = CGSize(width: 375, height: 200)
}
}
I want to know a way to resize this UIView with all the content in it. After finding a solution to increase the height i'll be able to put all the others components shown when i press the button.
I believe that your goal is to create something like this:
All I had to do was change the height of the constraint programmatically
Check the solution in the project below:
https://gitlab.com/DanielLimaDF/ResizeTest.git
Important: Beware of addSubview, it can remove constraints from a View if the constraints were created before calling addSubview

Distinguish which button was clicked in custom UIView

I have a custom class which inherits from UIView inside of which is a UIImageView and button. I'm adding them to my storyboard as UIView and let's say there are two views. I have a delegate and a function which executes when the button is pressed and it works for both UIViews.
My problem is that I don't know how to tell which one was clicked. I need to pass it to another VC and then display suitable image in the UIView which was clicked. I've been thinking of setting ids or something but it does not seem like a very scalable idea.
And I cannot simply add #IBAction because the view is UIView as a whole.
Inside the ViewController I've added them as #IBOutlets:
#IBOutlet weak var view: CustomImageView!
#IBOutlet weak var view2: CustomImageView!
EDIT:
I'm pretty close to creating reusable and scalable solution - I'm just assigning the tag to every object and than passing it and retrieving it. Problem I've encountered is that I would like to access properties of a tag. I didn't find any solution on how to do it.
Solution with delegates
You could add a custom delegate protocol for your custom view
protocol CustomViewDelegate {
func didSelectCustomView(_ view: CustomView)
}
class CustomView: UIView {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myButton: UIButton!
weak var delegate: CustomViewDelegate?
#IBAction func buttonPressed(sender: UIButton) {
delegate?.didSelectCustomView(self)
}
}
And in your ViewController you have to check from which view to delegate call comes:
class ViewController: UIViewController {
#IBOutlet weak var view1: CustomView!
#IBOutlet weak var view2: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
view1.delegate = self;
view2.delegate = self;
}
}
extension ViewController: CustomViewDelegate {
func didSelectCustomView(_ view: CustomView) {
if view == view1 {
// view1 clicked
} else {
// view2 clicked
}
}
}
Solution with blocks
Instead of a delegate, you could add an optional block that is executed if the button in the view was clicked:
class CustomView: UIView {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myButton: UIButton!
var clicked: ((CustomView) -> Void)?
#IBAction func buttonPressed(sender: UIButton) {
clicked?(self)
}
}
And in your ViewController, you can add the block to your views:
class ViewController: UIViewController {
#IBOutlet weak var view1: CustomView!
#IBOutlet weak var view2: CustomView!
override func viewDidLoad() {
super.viewDidLoad()
view1.clicked = { view in
}
view2.clicked = { view in
}
}
}

setTitle for UIButton results in it disappearing

I have changed the alpha of the button successfully so I know I can modify it. But when I use setTitle, the button just disappears.
I have a tableview with collection views in each cell. I have a custom header cell that when tapped, presents options including the button that disappears when tapping on it.
Here is the function in the main view controller that is called properly and works (I know because I can change the alpha of the button and even make it hidden).
func deleteScenes(){
if let header = whichHeaderTapped {
header.deleteScenesOutlet.setTitle("fuckssake", for: .normal)
header.deleteActOutlet.alpha = 0.0
header.editButtonOutlet.alpha = 0.0
}
}
Here is the class for the header cell.
class HeaderCell: UITableViewCell {
static var shared = HeaderCell()
#IBOutlet var headerName: UILabel!
#IBOutlet var newOptions: UIStackView!
#IBOutlet var deleteScenesOutlet: UIButton!
#IBOutlet var deleteActOutlet: UIButton!
#IBOutlet var editButtonOutlet: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
self.newOptions.frame.origin = CGPoint(x: 285, y: 0)
}
override func layoutSubviews() {
super.layoutSubviews()
}
#IBAction func deleteScenesButton(_ sender: UIButton) {
if deleteScenesOutlet.titleLabel?.text == "Delete Scenes" {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "deleteScenesButtonEnabled"), object: nil)
}
else {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "deleteScenesButtonDisabled"), object: nil)
}
}
}
Your code seems to be fine. Can you check what is the color of your button title. If it is white and your background view color is also white then there is a chance you were not able to see the button.

UIView reference error

I have created UIView in storyboard (Xcode 8.2.1). I reference the things inside to UIView class name LoginView. I delete one things by mistake then I got error at the line of Bundle.main.loadNibNamed("LoginView", owner: self, options: nil). EXC_BAD_ACCESS(code=2,....) I read about this in some answer here, they said about referencing missing. I try to reference everything again but still error. I'm now confusing about what should I reference it to. File Owner or View.
EDIT : The bug is happen when this View is render.
LoginView.swift
import UIKit
class LoginView: UIView {
#IBOutlet var view: UIView!
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var forgotPasswordBtn: UIButton!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
Bundle.main.loadNibNamed("LoginView", owner: self, options: nil)
self.addSubview(view)
view.frame = self.bounds
emailField.becomeFirstResponder()
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIInputViewController.dismissKeyboard))
view.addGestureRecognizer(tap)
}
func dismissKeyboard() {
view.endEditing(true)
}
}
This is my components in LoginView StoryBoard
And this is my referencing.
There's a CocoaPod called NibDesignable that not only configures the nib into the view (with constraints), but also makes the view IBDesignable so you can see your nib-based-views in the storyboard.
NibDesignable requires you to change the nib's file owner to the view class rather than the nib's view's custom class. Also, outlet connections must be made from the file's owner and not from the nib's view.
#IBDesignable class LoginView: NibDesignable {
// MARK: Outlets
#IBOutlet weak var emailField: UITextField!
#IBOutlet weak var passwordField: UITextField!
#IBOutlet weak var forgotPasswordBtn: UIButton!
// MARK: Properties
var tap: UITapGestureRecognizer? {
willSet {
tap.flatMap { removeGestureRecognizer($0) }
}
didSet {
tap.flatMap { addGestureRecognizer($0) }
}
}
// MARK: Lifecycle
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
tap = UITapGestureRecognizer(
target: self,
action: #selector(didRecognizeTapGesture)
)
emailField.becomeFirstResponder()
}
// MARK: Actions
#IBAction func didRecognizeTapGesture() {
endEditing(true)
}
}

Resources