UIButton in UIScrollView->UIStackView->UIView not clicking - swift

I am having trouble figuring out why a UIButton will not click. I have a UIScrollView that contains a UIStackView where I am programmatically placing subviews. I am creating the subviews and placing them into the stack view with the following:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var stackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let vc0 = self.storyboard?.instantiateViewControllerWithIdentifier("vc0") as UIViewController!
let vc1 = self.storyboard?.instantiateViewControllerWithIdentifier("vc1") as UIViewController!
self.stackView.addArrangedSubview(vc0.view)
self.stackView.addArrangedSubview(vc1.view)
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
// mulitply by two in order to scale it to the size of each `addArrangedSubview`, subtract the height of the embedded navbar
scrollView.contentSize = CGSize(width: stackView.frame.width * 2, height: stackView.frame.height - 64)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The only other changes I have made are with the constraints:
I should note that vc0 and vc1 are simple UIViews with a UIButton set to show another simple UIView.
Any help would be much appreciated!
EDIT:
I have added a button to vc0 programmatically and the click is working. Why would this button work and one from storyboard not work?
...
let vc0 = self.storyboard?.instantiateViewControllerWithIdentifier("vc0") as UIViewController!
...
let btn=UIButton(type: .System)
btn.frame = CGRectMake(100, 100, 32, 32)
btn.addTarget(self, action: "pressed", forControlEvents: .TouchUpInside)
btn.setTitle("Press Me", forState: .Normal)
vc0.view.addSubview(btw)
...

Related

How to use a button created in XIB custom view to control setContentOffset in viewController.swift?

I followed this tutorial to create a Snapchat-Like Menu: https://www.youtube.com/watch?v=1_daE3IL_1s
In short, the idea was to create custom views with XIB, and add them into a scrollview.
I would like to add a "back" button to one of the custom views so that the scrollview will automatically scroll back to its initial view when the button is tapped. The Idea I had was to write a code inside the custom view's IBAction function to call UIScrollview's content offset delegate function.
the following is the code in View Controller:
class ViewController: UIViewController, UIScrollViewDelegate {
//I'm naming the Scroll View as "scrollView"
#IBOutlet weak var scrollView: UIScrollView! {
didSet{
scrollView.delegate = self
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
var v1 : View1 = View1(nibName: "View1", bundle: nil)
var v2 : View2 = View2(nibName: "View2", bundle: nil)
self.addChild(v1)
self.scrollView.addSubview(v1.view)
v1.didMove(toParent: self)
self.addChild(v2)
self.scrollView.addSubview(v2.view)
v1.didMove(toParent: self)
var v2Frame : CGRect = v2.view.frame
v2Frame.origin.x = self.view.frame.width
v2.view.frame = v2Frame
self.scrollView.contentSize = CGSize(width: self.view.frame.width * 2, height: self.view.frame.height)
// self.scrollView.contentSize = CGSize(self.view.frame.width * 2, self.view.frame.size.height)
}
}
The following ht the code in View2:
class View2: UIViewController {
#IBOutlet weak var buttonHome: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func buttonHomeAction(_ sender: Any) {
//how to access scrollview.setContentOffset from ViewController to scroll the view back to the first view?
}
So my question is how to access scrollview.setContentOffset from ViewController to scroll the view back to the first view? Am I on the right track? Or are there any alternative methods where I can tap a button and scroll the view back to its first page?
Thank you!
I can think of two good options here:
1) Hold a weak reference in View2 of the scrollView. in View2 add:
weak var scrollView: UIScrollView?
and in ViewController, after view2 creation add:
view2.scrollView = self.scrollView
now, in buttonHomeAction you'll have access to the scrollView.
2) If you are familiar with Apple's delegation pattern, you can add a delegate, which can be a weak reference of the presenting view controller.
Create a protocol for the delegate, using named by the view holds the delegate. so, in this case: View2Delegate
and add a method that describes the action.
protocol View2Delegate: AnyObject {
func buttonTapped()
}
so, in View2 add:
weak var delegate: View2Delegate?
and in ViewController, after view2 creation add:
view2.delegate = self
now, in ViewController implement the protocol method and access scrollView:
extension ViewController: View2Delegate {
func buttonTapped() {
// access scrollView as self.scrollView
}
}

CALayer disappears on Custom UITableViewCell NIB after dequeue

I have a UITableView, where each row is a custom XIB. One row has 4 UIButtons, that are choices, like Question, Information, etc. When the UIButton is tapped I display an animation in a CALayer. When the table view scrolls, the CALayer is removed, that is the animation is gone.
When the button is tapped, I crate the CALayer and the animation begins. How can I make sure the CALayer doesn't disappear when the table is scrolled or updated?
class ReasonForSupportTableViewCell: UITableViewCell {
let animationView = AnimationView()
var hasButtonBeenTapped = false
var previousButtonTapped: UIButton? = nil
//IBOutlets
#IBOutlet weak var questionButton: UIButton!
#IBOutlet weak var informationButton: UIButton!
#IBOutlet weak var crashButton: UIButton!
#IBOutlet weak var bugButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
//set initial button
questionButton.sendActions(for: .touchUpInside)
}
func createView(sender: UIButton) {
//draw the frame
animationView.frame = CGRect(x: 0, y: 0, width: 75.0, height: 75.0)
//change the view background color
animationView.backgroundColor = UIColor.clear
animationView.isUserInteractionEnabled = false
//add the view.
sender.addSubview(animationView)
}
#IBAction func buttonTapped(_ sender: UIButton) {
if previousButtonTapped == nil {
//you haven't tapped a button yet
createView(sender: sender)
animationView.animateTo()
previousButtonTapped = sender
} else if previousButtonTapped == sender {
animationView.removeAnimation()
previousButtonTapped = nil
} else {
animationView.removeAnimation()
createView(sender: sender)
animationView.animateTo()
previousButtonTapped = sender
}
}
}
Subclass UIButton to add the CALayer on initialisation, rather than when a button is tapped. You can then use the prepareForReuse() function to stop any animation.

swift Button display

I create a button from my code.
How can I write code to let button change to like Default?
Am I missing some code?
I have tried adjustsImageWhenHighlighted or something ....
I mean when I push Button ..the button will become to transparent(I still push on) and when i push off will become back ...
like down below two images...
import UIKit
class ViewController: UIViewController {
var testButton:UIButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = UIColor.whiteColor()
testButton.frame = CGRect(x: 100, y: 100, width: 100, height: 100)
testButton.backgroundColor = UIColor.whiteColor()
testButton.setTitle("123", forState:.Normal)
testButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
testButton.tag = 1
testButton.addTarget(self, action: #selector(number), forControlEvents: .TouchUpInside)
self.view.addSubview(testButton)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func number(){
print("\("100")")
}
}
You could either add:
testButton.setTitleColor(UIColor.redColor(), forState: .Highlighted)
or have the colour applied in the button's function:
#IBAction func testButton(sender: UIButton) {
testButton.titleLabel.textColor = UIColor.redColor()
}
I've used redColor here for the examples, but you could change that to whatever colour you want to create the desired effect. I've not actually compiled this, so apologies if you need to correct any of the syntax to get it to work.

How to programmatically create UIlabel inside a custom uiView swift

how can i create 5 custom uilabel inside a custom UIView. Which will align one after the other. i have tried to create the UILabel inside the custom UIView. but it does not go inside the custom UIView.
//updated with the loop
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var mainView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var getMainViewX = mainView.frame.origin.x
let getMainViewY = mainView.frame.origin.y
for var i = 0; i < 5; i++
{
let label = UILabel(frame: CGRectMake(getMainViewX, getMainViewY, 200, 21))
//label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
label.text = "I'am a test label"
self.mainView.addSubview(label)
getMainViewX+=20
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
If you're using iOS 9, the recently added Stack View has been created for exactly this purpose.
Use a UIStackView for your mainView instead of a default view
You can set the alignment properties of the stack view in Interface Builder
Create the labels in your loop, then add them to the stack view using the addArrangedSubview method of the stack view.
The stack view will take care of the alignment, spacing and layout of it's subviews for you.
Its not clear what you mean by "align".
Assuming you want them one stacked one below another, I have made minor adjustments to your code.
class ViewController: UIViewController {
#IBOutlet weak var mainView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let getMainViewX = mainView.frame.origin.x
//let getMainViewY = mainView.frame.origin.y
for var i = 0; i < 5; i++
{
//let label = UILabel(frame: CGRectMake(getMainViewX, getMainViewY, 200, 21))
let label = UILabel(frame: CGRectMake(getMainViewX, CGFloat(i) * 21, 200, 21))
//label.center = CGPointMake(160, 284)
label.textAlignment = NSTextAlignment.Center
label.text = "I'am a test label"
self.mainView.addSubview(label)
//getMainViewX+=20
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Hopefully this is how you are looking to align the labels

Swift - changing app when banner loads. - xcode 6 GM

I have been working on a mainly text-based application with an Iadbanner in the bottom.
However as we all know, Iads aren't always there. So I would like to be able to dynamically update the height of my textView, so when the banner is hidden, the textView takes up the wasted space. And resize it when a banner is loaded.
Here's what I currently have for the Viewcontroller in question
import UIKit
import iAd
class DetailVC: UIViewController, UITextViewDelegate, ADBannerViewDelegate {
//Our label for displaying var "Items/cellName"
#IBOutlet var imageViewOutlet: UIImageView!
//connect in IB connection inspector with your ADBannerView
#IBOutlet var adBannerView: ADBannerView!
//Receiving variable assigned to our mainVC var "items"
var cellName: String = ""
var imageView: UIImageView = UIImageView()
var image = UIImage(named: "handcuffs.png")
var textViewText: String = ""
var textView: UITextView = UITextView(frame: CGRect(x: 5.0, y: 238.0, width: 315.00, height: 283.00))
//height = 332 for full screen 283 for small
override func viewDidLoad() {
super.viewDidLoad()
println("+--------------------+")
println("| Detail view loaded |")
println("+--------------------+")
// Iad stuff
self.adBannerView.delegate = self
self.canDisplayBannerAds = true
self.adBannerView.hidden = true //hide until ad loaded
//Setting up the textView
textView.text = textViewText
textView.editable = false
textView.backgroundColor = UIColor.clearColor()
textView.font = UIFont(name: "Helvetica", size: 15)
//adding textview as subview
self.view.addSubview(textView)
//ImageViewOutlets
imageViewOutlet.image = image
//Assign your string var to your navbar title
self.title = cellName
func bannerViewWillLoadAd(banner: ADBannerView!) {
NSLog("bannerViewWillLoadAd")
}
func bannerViewDidLoadAd(banner: ADBannerView!) {
NSLog("bannerViewDidLoadAd")
//self.textView.removeFromSuperview()
//textView = UITextView(frame: CGRect(x: 0.0, y: 238.0, width: 320.00, height: 283.00))
//self.view.addSubview(textView)
self.adBannerView.hidden = false //now show banner as ad is loaded
}
func bannerViewActionDidFinish(banner: ADBannerView!) {
NSLog("bannerViewActionDidFinish")
//optional resume paused app code
}
func bannerViewActionShouldBegin(banner: ADBannerView!, willLeaveApplication willLeave: Bool) -> Bool {
NSLog("bannerViewActionShouldBegin")
//optional pause app code
return true
}
func bannerView(banner: ADBannerView!, didFailToReceiveAdWithError error: NSError!) {
NSLog("didFailToReceiveAdWithError")
}
//... your class implementation code
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The commented out code in the function "bannerViewDidLoadAd" is what I thought would have fixed my issue. Sadly that function seems to never run? I'm not very familiar with Iads so hopefully someone out there can give me a hint as to how to change the height of a textView when an ad loads.
CanDisplayBannerAds :
Set this to enable automatic management of banner ad display with the view controller. It's important to note that this will modify the view hierarchy of the view controller by inserting a new container view above the view controller's view. The impact is that the view controller's view property will no longer return the originally provided view, it will return the new container. To access the original view, use the originalContentView property.
So, remove this line :
self.canDisplayBannerAds = true
Everything should work.