Square Not Appearing - ios

I am Programatically creating a square in swift. Below is my code, but for some reason nothing appears.
let PB1 = UIButton()
func SetUpPB1() {
PB1.bounds = CGRect(x: 0, y: 0, width: 50, height: 50)
PB1.setBackgroundImage(UIImage(named: "RS"), forState:UIControlState.Normal)
PB1.center = CGPoint(x: 200, y: 200)
PB1.addTarget(self, action: Selector("PB1Pressed"), forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(PB1)
}
P.S I need the setup function or the app will crash.

You said "...how do I call the function? I thought I did by writing it?" That is wrong. Functions don't get called unless you call them - nested functions as well.
If SetUpPB1() is a nested function inside your viewDidLoad and you only call it once it's probably cleaner to just get rid of it and put that code inline in viewDidLoad.
Otherwise, you need something like this:
func viewDidLoad() {
let PB1 = UIButton()
func setUpPB1() {
PB1.bounds = CGRect(x: 0, y: 0, width: 50, height: 50)
PB1.setBackgroundImage(UIImage(named: "RS"),
forState:UIControlState.Normal)
PB1.center = CGPoint(x: 200, y: 200)
PB1.addTarget(self, action: Selector("PB1Pressed"),
forControlEvents: UIControlEvents.TouchUpInside)
self.view?.addSubview(PB1)
}
setUpPB1() //Add this line to call the function
}

Related

UIbutton inside UIViewControllers inside UIScrollView not getting triggered on touch

I'v added two UIViewControllers inside of a UIScrollView, and now I'm trying to add targets to the button inside of the UIViewControllers, I've checked the internet but none of those solutions worked for me, this is what I'm doing
inside of the main ViewController
scrollView.contentSize = CGSize(width: view.frame.width * 2, height:0)
let postsViewController = PostsViewController()
postsViewController.scrollView = scrollView
postsViewController.view.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
let chatsViewController = ChatsViewController()
chatsViewController.scrollView = scrollView
chatsViewController.view.frame = CGRect(x: view.frame.width, y: 0, width: view.frame.width, height: view.frame.height)
scrollView.addSubview(postsViewController.view)
scrollView.addSubview(chatsViewController.view)
postsViewController.didMove(toParent: self)
chatsViewController.didMove(toParent: self)
then inside the postsViewController I'm doing this
let a = UIButton()
a.setImage(currentTheme.chat, for: .normal)
a.imageEdgeInsets = UIEdgeInsets(top: 1.5, left: 0.0, bottom: 1.5, right: 0.0)
view.addSubview(a)
view.addConstraint("V:|-200-[v0(80)]-0-|",a)
view.addConstraint("H:|-200-[v0(80)]-0-|",a)
a.addTarget(self, action: #selector(abc), for: .touchUpInside)
the add "addConstraint" is an extension function just to add constraint to views
the abc function
#objc func abc() {
print("hello")
}
you can see the scrollView setting here
https://ibb.co/ZB1LJsy
Try to initialize your button like this
let a : UIButton = UIButton(type: .custom)
And add this after to the initialize of your UIScrollView
scrollView.delaysContentTouches = false
I tested in an xcode project. I can not execute the function (button) in the other UIViewController.
By cons if you sent the #selector it works.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let scrollView : UIScrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width))
scrollView.delaysContentTouches = false
view.addSubview(scrollView)
let TestViewController = TestViewController1()
TestViewController.select = #selector(demande(sender:))
TestViewController.view.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
scrollView.addSubview(TestViewController.view)
print("dd")
}
#objc func demande(sender: UIButton!) {
print("button click", sender.tag)
}
}
class TestViewController1: UIViewController {
var select : Selector!
override func viewDidLoad() {
super.viewDidLoad()
let button : UIButton = UIButton(type: .custom)
button.setImage(#imageLiteral(resourceName: "turn_off_on_power-512"), for: .normal)
button.tag = 2
button.addTarget(self, action: select, for: .touchUpInside)
button.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
view.addSubview(button)
}
}
Hoping that it helps you
okay, I solved my problem, the reason why the button wasn't getting trigger is because I forgot to attach the viewController of the view to the scrollview, so all I had to do is to attach the viewController as well and it worked.
self.addChild(postsViewController)
self.addChild(chatsViewController)
now it is working.

Swift Content Tabs?

I am building an app and I am required to have 3 tabs if you click on the first tab, its a tableview, second tab a different tableview, third tab, TextView, here is an image of what I am trying to do:
Every time I google looking for examples of something like this, I get referred to UITabBarController, I don't think a tab bar is what I am looking for.
What you are looking for is called Segmented Control (UISegmentedControl).
You can see it in Action natively e.g. in both the Apple iTunes and Health App.
Instead of performing segues to different views with the UITabBarController, you can, using Interface Builder, connect it to your UIViewController like so
#IBOutlet weak var segmentedControl: UISegmentedControl!
and in
viewDidLoad() {
switch segmentedControl.selectedIndex {
case 0: // Do something on your first picture
someFunction()
case 1: // Do something on your second picture
performSegue(withIdentifier: "your identifier here", sender: nil)
case 2: // Do something on your third picture
image.isHidden = true
button.isEnabled = false
default: break
}
... etc. You could also initiate different View Controllers instead of manipulating just one View, which you can then access via segues.
Please see official Swift doc # https://developer.apple.com/documentation/uikit/uisegmentedcontrol?changes=_3
I would create this layout programmatically. You want a custom look to it so I do not think the standard controls are your best option.
Here is a playground to get you started on one way this could be achieved:
import UIKit
import PlaygroundSupport
class ViewController: UIViewController {
let view1 = UIView(frame: CGRect(x: 0, y: 100, width: 768, height: 924))
let view2 = UIView(frame: CGRect(x: 0, y: 100, width: 768, height: 924))
let view3 = UIView(frame: CGRect(x: 0, y: 100, width: 768, height: 924))
override func viewDidLoad() {
super.viewDidLoad()
self.view.frame = CGRect(x: 0, y: 0, width: 768, height: 1024)
self.view.backgroundColor = .black
// View to have a border around the buttons
let box = UIView(frame: CGRect(x: 40, y: 20, width: 300, height: 50))
box.layer.borderColor = UIColor.white.cgColor
box.layer.borderWidth = 2
self.view.addSubview(box)
// Tab buttons
let button1 = UIButton(frame: CGRect(x: 40, y: 20, width: 100, height: 50))
button1.setTitle("Orange", for: .normal)
button1.tag = 1
button1.addTarget(self, action: #selector(tabTouched(sender:)), for: .touchUpInside)
self.view.addSubview(button1)
let button2 = UIButton(frame: CGRect(x: 140, y: 20, width: 100, height: 50))
button2.setTitle("Blue", for: .normal)
button2.tag = 2
button2.addTarget(self, action: #selector(tabTouched(sender:)), for: .touchUpInside)
self.view.addSubview(button2)
let button3 = UIButton(frame: CGRect(x: 240, y: 20, width: 100, height: 50))
button3.setTitle("Green", for: .normal)
button3.tag = 3
button3.addTarget(self, action: #selector(tabTouched(sender:)), for: .touchUpInside)
self.view.addSubview(button3)
// Tab Views
view1.backgroundColor = .orange
self.view.addSubview(view1)
view2.backgroundColor = .blue
view2.alpha = 0
self.view.addSubview(view2)
view3.backgroundColor = .green
view3.alpha = 0
self.view.addSubview(view3)
}
// When each of the buttons are tapped we will hide or show the correct tab's view
#objc func tabTouched(sender: UIButton) {
if sender.tag == 1 {
UIView.animate(withDuration: 0.3) {
self.view1.alpha = 1
self.view2.alpha = 0
self.view3.alpha = 0
}
} else if sender.tag == 2 {
UIView.animate(withDuration: 0.3) {
self.view1.alpha = 0
self.view2.alpha = 1
self.view3.alpha = 0
}
} else if sender.tag == 3 {
UIView.animate(withDuration: 0.3) {
self.view1.alpha = 0
self.view2.alpha = 0
self.view3.alpha = 1
}
}
}
}
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = ViewController()
You can copy and paste this into an empty playground to see it in action. Essentially this is showing or hiding the appropriate views based on which button is selected. You can swap out the views for view controllers if you so desire.

Custom view scrolls inside a scroll view

I have made a custom view called SignView and added to another customView called mainSignView which is inside an scrollview called getFormView but when I sign on the signView it scrolls and I cannot do any sign help me to overcome this please!
Here is what I have
#objc func pressedSignViewAction(_ sender: UILabel) {
self.signViewElement = "signView1"
uniY += 60
mainSignView = UIView(frame: CGRect(x: 20, y: uniY, width: 250, height: 250))
mySignViewName = UILabel(frame: CGRect(x: 20, y: 10, width: 200, height: 30))
let signLabel = UILabel(frame: CGRect(x: 20, y: 50, width: 200, height: 30))
signView = YPDrawSignatureView(frame: CGRect(x: 10, y: 90, width: 230, height: 100))
signView.backgroundColor = .white
signLabel.text = "Signature"
mainSignView.backgroundColor = .green
mySignViewName.text = self.signViewNameFD
self.signViewNameElement = self.signViewNameFD
cancelButton = UIButton(frame : CGRect(x: 20, y: 200, width: 100, height: 25))
cancelButton.addTarget(self, action: #selector(pressedSignClearAction(_:)), for: .touchUpInside)
cancelButton.setTitle("Clear",for: .normal)
cancelButton.setTitleColor(UIColor.red, for: .normal)
uniY += 170
self.view.addSubview(getFormView)
//self.getFormView.addSubview(signLabel)
self.getFormView.addSubview(mainSignView)
self.mainSignView.addSubview(signLabel)
self.mainSignView.addSubview(signView)
self.mainSignView.addSubview(mySignViewName)
self.mainSignView.addSubview(cancelButton)
self.enterSignViewTitle()
self.updateScrollY()
}
#objc func pressedSignClearAction(_ sender: UIButton) {
self.signView.clear()
}
From YPDrawSignatureView Documentation:
// MARK: - Delegate Methods
// The delegate functions gives feedback to the instanciating class. All functions are optional,
// meaning you just implement the one you need.
// didStart() is called right after the first touch is registered in the view.
// For example, this can be used if the view is embedded in a scroll view, temporary
// stopping it from scrolling while signing.
func didStart() {
print("Started Drawing")
yourScroll.isScrollEnabled = false
}
// didFinish() is called rigth after the last touch of a gesture is registered in the view.
// Can be used to enable scrolling in a scroll view if it has previous been disabled.
func didFinish() {
print("Finished Drawing")
yourScroll.isScrollEnabled = true
}

Apple Swift Tutorial: Rating buttons layout

I'm currently following this Apple's iOS Swift tutorial for beginner which explain how to create the rating star view and I don't understand something about the layout code. To layout the rating buttons they created from code using a for-in loop, they create another method:
override func layoutSubviews() {
var buttonFrame = CGRect(x: 0, y: 0, width: 44, height: 44)
// Offset each button's origin by the length of the button plus spacing.
for (index, button) in ratingButtons.enumerate() {
buttonFrame.origin.x = CGFloat(index * (44 + 5))
button.frame = buttonFrame
}
}
But in at the initialisation of buttons :
for _ in 0..<5 {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 44, height: 44))
button.backgroundColor = UIColor.redColor()
// Add event listener
button.addTarget(self, action: #selector(RatingControl.rateButtonTapped(_:)), forControlEvents: .TouchDown)
ratingButtons += [button]
addSubview(button)
}
Can't they simply adapt the code and, instead of using a wildcard ( _ ) in the for-in loop, use an index and do something like this ? :
for i in 0..<5 {
let button = UIButton(frame: CGRect(x: (i * 49), y: 0, width: 44, height: 44))
button.backgroundColor = UIColor.redColor()
// Add event listener
button.addTarget(self, action: #selector(RatingControl.rateButtonTapped(_:)), forControlEvents: .TouchDown)
ratingButtons += [button]
addSubview(button)
}
I am learning Swift and I don't understand why they override the layoutSubviews method instead of doing that at initialisation. Tell me which way is the cleaner please. Here is the tutorial link: https://developer.apple.com/library/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/Lesson5.html
Regards,
The issue is that the frame for the containing rect is not known before the viewWillLayoutSubviews method is called. The layoutSubviews method is called after this method, and each time layoutIfNeeded is called for the view.
This means that the layout can be adapted to updates in the view and only called from one method.
Whether one method is cleaner than another is subjective, and really up to each individual to determine, but at least you should write your UI code in a way that follows the lifecycle of the view.

UIButton not calling action function in swift

I have a button created programmatically but for some strange reason when pressed it it doesn't activate the action. There are a few buttons, I've eliminated the other buttons form the code, here is the button that isn't working:
struct Buttons {
var hintButton: UIButton!
let hintBtn = UIButton(frame: CGRect(x: 10, y: 20, width: 70, height: 70))
init() {hintBtn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
hintBtn.tag = 2
hintBtn.setTitle("Hint", forState: .Normal)
hintBtn.setTitleColor(UIColor.whiteColor(), forState: .Normal)
hintButton = hintBtn
}
}
Here is the code in the viewController:
override func viewDidLoad() {
super.viewDidLoad()
AddAllGraphics()
ButtonActions()
self.buttons.hintBtn.enabled = true
}
func AddAllGraphics() {
self.view.addSubview(buttons.hintBtn)
}
func ButtonActions() {
buttons.hintBtn.addTarget(self, action: "giveHint:", forControlEvents: .TouchUpInside)
}
func giveHint(sender:UIButton) {
if(sender.tag == 2){
buttons.hintBtn.enabled = false
print("It Works")
}
}
I've tried putting a break point at the "giveHint" function but it is never called when the button is pressed. I've tried putting self.buttons.btn.userInteractionEnabled = true in the viewDidLoad but it still doesn't work. Any help will be greatly appreciated!
The code above is working for me, but I had to init the struct properly:
struct Buttons {
var hintButton: UIButton!
let hintBtn = UIButton(frame: CGRect(x: 10, y: 50, width: 70, height: 70))
init() {
hintBtn.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
hintBtn.tag = 2
hintBtn.setTitle("Hint", forState: .Normal)
hintBtn.setTitleColor(UIColor.whiteColor(), forState: .Normal)
hintButton = hintBtn
}
}
Found out the issue. The button was behind another view that had user interaction disabled. Since the view was clear I thought I was pressing the button.

Resources