The "go button" is not working as it should. When clicked it should hide the subviews. Here's the ViewController. I tried placing the final function in various places.
class timeViewController: UIViewController {
var score = 0
var buttonState: Int = 0;
var gameOver = UIView()
#IBAction func start(sender: AnyObject) {
if(displayTime.text != stoptimer.text){
var gameOver = UIView(frame: CGRectMake(0, 0, 0, 0))
gameOver.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.2)
//gameOver.opaque = false
self.view.addSubview(gameOver)
UIView.animateWithDuration(0, animations:{
gameOver.frame.size = CGSizeMake(667, 667)
})
let gobutton = UIButton()
let image = "button.png"
gobutton.setImage(UIImage(named: image), forState: .Normal)
gobutton.frame = CGRectMake(135, 300, 95, 95)
gobutton.addTarget(self, action: "pressed:" , forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(gobutton)
func pressed(sender: UIButton!){
gameOver.removeFromSuperview()
}
}
}
For removing your "GaneOver" view change to this code:
gameOver.removeFromSuperview()
And I hope you are writing "func pressed" outside of viewDidLoad or viewWillAppear
You will have to make gameOver a global variable by declaring it outside function and then do what you did like this:
class myClass {
var gameOver = UIView()
func myFunction() {/*edit everything including gameOverView's properties*/}
func pressed(sender: UIButton!) {
gameOver.removeFromSuperview()
}
}
Also make sure to write functions outside other functions like viewDidLoad but inside your class as it looks like you created that function inside another one. However you can call a function from within another one using something like myFunction() as separate line as is.
Hope that helps :)
You're re-declaring gameOver inside the if statement. Just remove var. Check this code out:
class ViewController: UIViewController {
var gameOver: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func start(sender: AnyObject) {
if(displayTime.text != stoptimer.text){
gameOver = UIView(frame: CGRectMake(0, 0, 0, 0))
gameOver.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.2)
//gameOver.opaque = false
self.view.addSubview(gameOver)
UIView.animateWithDuration(0, animations:{
self.gameOver.frame.size = CGSizeMake(667, 667)
})
let gobutton = UIButton()
let image = "button.png"
gobutton.setImage(UIImage(named: image), forState: .Normal)
gobutton.frame = CGRectMake(135, 300, 95, 95)
gobutton.addTarget(self, action: "pressed:" , forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(gobutton)
}
}
func pressed(sender: UIButton!){
self.gameOver.removeFromSuperview()
}
}
Related
Note: I created a Test program so I can better understand how ARC works - I am having trouble implementing it in my real project.
I created a Test program to determine how ARC works - it works great! Here it is.
ViewController1:
import UIKit
class ViewController: UIViewController {
weak var vc2:ViewController2?
override func viewDidLoad() {
super.viewDidLoad()
print("VC1 Initialized")
addButton()
}
func addButton() {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
button.backgroundColor = .red
button.setTitle("Go to VC2", for: .normal)
self.view.addSubview(button)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
}
#objc func buttonAction(sender: UIButton!) {
let vx = ViewController2()
vx.VC1 = self
vc2 = vx
self.present(vc2!, animated: false, completion: nil)
}
}
ViewController2:
import UIKit
class ViewController2: UIViewController {
weak var VC1:ViewController?
weak var VC3:ViewController3?
override func viewDidLoad() {
super.viewDidLoad()
print("VC2 Initialized")
addButton()
}
deinit {
print("VC2 Deinitialized")
}
func addButton() {
for i in 0..<2 {
let button = UIButton(frame: CGRect(x: 0, y: self.view.frame.height*0.5*CGFloat(i), width: self.view.frame.width, height: self.view.frame.height*0.5))
button.backgroundColor = i == 0 ? .red : .blue
button.setTitle("Go to VC\(i*2+1)", for: .normal)
self.view.addSubview(button)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
button.tag = i
}
}
#objc func buttonAction(sender: UIButton!) {
let tag = sender.tag
if(tag == 0) {
self.dismiss(animated: true, completion: nil)
}
else {
let vc3 = ViewController3()
vc3.ViewController2 = self
VC3 = vc3
self.present(VC3!, animated: true, completion: nil)
}
}
}
ViewController3:
import UIKit
class ViewController3: UIViewController {
var ViewController2:ViewController2?
override func viewDidLoad() {
super.viewDidLoad()
print("VC3 Initialized")
addButton()
}
deinit {
print("VC3 Deinitialized")
}
func addButton() {
let button = UIButton(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
button.backgroundColor = .red
button.setTitle("Go to VC1", for: .normal)
self.view.addSubview(button)
button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
}
#objc func buttonAction(sender: UIButton!) {
self.ViewController2!.VC1!.dismiss(animated: true, completion: nil)
}
}
What I was looking at was how to remove multiple pages at a time (as indicated by the button push on VC3 and it goes back to the main page) and still remove ARC memory. All goes well. You can see the output below of me doing these operations.
Start program - push to page 2 - push to page. 1 - push to page 2 - push to page 3 - go to page 1
VC1 Initialized
VC2 Initialized
VC2 Deinitialized
VC2 Initialized
VC3 Initialized
VC3 Deinitialized
VC2 Deinitialized
The problem I am incurring is in my actual program - when I use these methods above, it automatically calls deinit on the last object I created when I CREATE my new object. But it doesn't actually delete anything - the memory graph will show x number of items even though the deinit method is called.
import UIKIT
class myClass: UIViewController {
weak var pageController:PageController?
override func viewDidLoad() {
super.viewDidLoad()
print("Initialized PC")
presentThemes()
}
func presentThemes() {
let pg = PageController(x: 1, controller: self)
pageController = pg
self.present(pageController!, animated: true, completion: nil)
}
deinit {
print("Deinit")
}
}
The output I am being provided is:
Initialized PC
On the first instance and is:
Deinit
Initialized PC
On the second instance. Any idea why Deinit is being called but the memory graph shows it there?
Why doesn't this work in swift 3 ? It crashes at runtime saying:
'-[my_app_name.displayOtherAppsCtrl tap:]: unrecognized selector sent
to instance 0x17eceb70'
override func viewDidLoad() {
super.viewDidLoad()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Register cell classes
//self.collectionView!.register(ImageCell.self, forCellWithReuseIdentifier: reuseIdentifier)
// Do any additional setup after loading the view.
let lpgr = UITapGestureRecognizer(target: self, action: Selector("tap:"))
lpgr.delegate = self
collectionView?.addGestureRecognizer(lpgr)
}
func tap(gestureReconizer: UITapGestureRecognizer) {
if gestureReconizer.state != UIGestureRecognizerState.ended {
return
}
let p = gestureReconizer.location(in: self.collectionView)
let indexPath = self.collectionView?.indexPathForItem(at: p)
if let index = indexPath {
//var cell = self.collectionView?.cellForItem(at: index)
// do stuff with your cell, for example print the indexPath
print(index.row)
} else {
print("Could not find index path")
}
}
Selector("tap:") should now be written as #selector(tap(gestureReconizer:))
Also, you should declare tap as func tap(_ gestureRecognizer: UITapGestureRecognizer) as per the new Swift API Guidelines in which case your selector would then become #selector(tap(_:)).
In Swift 3 it works like this:
#IBOutlet var myView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action:#selector(handleTap))
myView.addGestureRecognizer(tap)
}
func handleTap() {
print("tapped")
}
Swift 3 came with new syntax so instead of using Selector("tap:"), #selector(tap(gestureReconizer:)) is
Swift 3:
class MYPTempController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
view.addSubview(btn)
btn.addTarget(self, action: #selector(MYPTempController.btnClick), for: .touchUpInside)
}
#objc fileprivate func btnClick() {
print("--click--")
}
}
//带参数
btn.addTarget(self, action: #selector(MYPTempController.btnClick(_:)), for: .touchUpInside)
//监听方法
func btnClick(_ sender: UIButton) {
print("--click--")
}
I have a class like this,
import UIkit
class One {
let btn = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
btn.frame = CGRectMake(10, 20, 30, 30)
btn.setTitle("Go", forState: UIControlState.Normal)
btn.addTarget(self, action: "goToClassTwo", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(btn)
}
func goToClassTwo(){
if(AppGlobals().getIsFromDiffView()){
let difView = UINavigationController(rootViewController: DiffView())
difView.pushViewController(Two(), animated: true)
}else{
self.navigationController?.pushViewController(Two(), animated: true)
}
}
}
A setter/getter class like this,
class AppGlobals: NSObject {
var isFromDiffView = false
func setIsFromDiffView(val: Bool){
isFromDiffView = val
}
func getIsFromDiffView() -> Bool {
return isFromDiffView
}
}
And I have another class like this,
class DiffView {
let btn = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
btn.frame = CGRectMake(10, 20, 30, 30)
btn.setTitle("Push", forState: UIControlState.Normal)
btn.addTarget(self, action: "btnAction", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(btn)
}
func btnAction(){
AppGlobals().setIsFromDiffView(true)
One().goToClassTwo()
}
}
I am facing a problem here. When the 'Go' button in the class 'One' is tapped, then the 'Two' view controller is shown. But when I tap on the 'Push' button in the class 'DiffView' is tapped, the 'Two' view controller is not being shown.
I have checked setting breakpoints. The control does come to the goToClassTwo function in the class 'One' and the if path is being executed. But the 'Two' view controller is not shown. difView.pushViewController is called. But it is not pushing to the next view.
NOTE: I am not using storyboard
Any help would be appreciated!
This is the updated code.
Code for class 'One':
import UIKit
class One {
let btn = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
btn.frame = CGRectMake(10, 20, 30, 30)
btn.setTitle("Go", forState: UIControlState.Normal)
btn.addTarget(self, action: "goToClassTwo", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(btn)
}
func goToClassTwo(){
if(AppGlobals().getIsFromDiffView()){
//Using the navigation controller of DiffView
AppGlobals().getController().pushViewController(Two(), animated: true)
}else{
self.navigationController?.pushViewController(Two(), animated: true)
}
}
}
setter/getter class:
class AppGlobals: NSObject {
var isFromDiffView = false
var cntrlr: UINavigationController!
func setIsFromDiffView(val: Bool){
isFromDiffView = val
}
func getIsFromDiffView() -> Bool {
return isFromDiffView
}
//Setting and getting DiffView Navigation controller
func setController(cntrl: UINavigationController){
cntrlr = cntrl
}
func getController() -> UINavigationController {
return cntrlr
}
}
DiffView class:
class DiffView {
let btn = UIButton()
override func viewDidLoad(){
super.viewDidLoad()
btn.frame = CGRectMake(10, 20, 30, 30)
btn.setTitle("Push", forState: UIControlState.Normal)
btn.addTarget(self, action: "btnAction", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(btn)
}
func btnAction(){
AppGlobals().setIsFromDiffView(true)
//Setting the navigation controller
AppGlobals().setController(self.navigationController!)
One().goToClassTwo()
}
}
With this updated code, class 'Two' view controller is being displayed.
Thank you #zp_x for your help.
I'm trying to have a custom UIButton become hidden once it's pressed a certain number of times...but I'm at a loss.
Having exhausted my limited knowledge and consulting the Apple's documentation as well as the internet for the better part of 3 hours, I've finally made my way here. I've been learning Swift for a short while now and am making an effort to become more familiar with it. This is my first object-oriented language and it's testing me to say the least. Any help with this more likely than not ridiculously simple problem is very much appreciated.
import UIKit
class ViewController: UIViewController{
#IBOutlet weak var buttonMessageDisplay: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
buttonPressed()
}
var tapcount = 0
let buttonMessage : [String] = [/* long array of strings */]
func buttonPressed() {
let button = UIButton(type:.Custom) as UIButton
button.frame = CGRectMake(0, 0, 100, 100)
button.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2);
button.backgroundColor = UIColor.redColor()
button.layer.borderColor = UIColor.blackColor().CGColor
button.layer.borderWidth = 3
button.layer.cornerRadius = 0.5 * button.bounds.size.width
button.setTitle("", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonPressed", forControlEvents: .TouchUpInside)
view.addSubview(button)
switch tapcount {
case 19...23:
//Hides the button
button.hidden = true
buttonMessageDisplay.text = buttonMessage[tapcount]
case 24...31:
//Unhides the button
button.hidden = false
buttonMessageDisplay.text = buttonMessage[tapcount]
default:
buttonMessageDisplay.text = buttonMessage[tapcount]
}
print("Tap Count: \(tapcount)")
++tapcount
}
Updated with Gesture Recognizer:
import UIKit
class ViewController: UIViewController{
#IBOutlet weak var buttonMessageDisplay: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
buttonMessageDisplay.text = ""
let button = UIButton(type:.Custom) as UIButton
button.frame = CGRectMake(0, 0, 100, 100)
button.center = CGPointMake(self.view.frame.size.width/2, self.view.frame.size.height/2);
button.backgroundColor = UIColor.redColor()
button.layer.borderColor = UIColor.blackColor().CGColor
button.layer.borderWidth = 3
button.layer.cornerRadius = 0.5 * button.bounds.size.width
button.setTitle("", forState: UIControlState.Normal)
button.addTarget(self, action: "buttonPressed", forControlEvents: .TouchUpInside)
self.view.addSubview(button)
}
var tapcount : Int = 0
let buttonMessage : [String] = [/* array of strings */]
#IBAction func userTap(sender: UITapGestureRecognizer) {
print("Tap Received")
if case 19...23 = tapcount {
buttonPressed()
}
}
func buttonPressed() {
switch tapcount {
case 0...18:
buttonMessageDisplay.text = buttonMessage[tapcount]
case 19...23:
//Hides the button
button.hidden = true
buttonMessageDisplay.text = buttonMessage[tapcount]
case 24...32:
//Unhides the button
button.hidden = false
buttonMessageDisplay.text = buttonMessage[tapcount]
case 33...100:
buttonMessageDisplay.text = buttonMessage[tapcount]
default:
print("There are no more messages or an error has been encountered")
}
print("Tap Count: \(tapcount)")
++tapcount
}
}
Your code makes no sense. As #formal says in his answer, you're creating a new button on every tap, which is wrong.
You want to define your button in your Storyboard.
Then you want an IBAction method, which takes the button as a parameter:
#IBAction func buttonPressed(sender: UIButton)
{
++tapcount
if tapcount < 19
{
sender.hidden = true
}
}
Note that if the button you're hiding is the same one the user is tapping, once it is hidden, you're done. The user can't tap a hidden button, so there's no way to un-hide it. (And thus no point in your switch statement)
Your main issue is that you are creating a new button every time you call button pressed. Create an #IBOutlet for your button and just set its hidden property in butPressed (which can be set as an action of the button).
Something like:
class ViewController: UIViewController {
#IBOutlet weak var button: UIButton!
#IBOutlet weak var buttonMessageDisplay: UILabel!
var tapcount = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func butPressed(sender: AnyObject) {
switch tapcount {
case 19...23:
//Hides the button
button.hidden = true
case 24...31:
//Unhides the button
button.hidden = false
default: break
}
print("Tap Count: \(tapcount)")
buttonMessageDisplay.text = "Tap: \(tapcount)"
++tapcount
}
}
The method buttonPressed() creates a new button each time it is called. You should define button as a property similar to buttonMessageDisplay and place the code to initialise it within viewDidLoad().
You should give space between range in case condition:
For example:
(IBAction)buttonTapped:(id)sender {
self.count++;
switch (self.count) {
case 5 ... 23 :
self.button.titleLabel.text = #"disable";
self.button.hidden = true;
break;
default:
break;
}
}
I'm currently tying to familiarise myself with UIKit under Swift and work out the best way of adding UI elements programmatically. However I'm finding that a touch can end way outside the button in which it began yet still register as a TouchUpInside event. The ViewController below is from a single view application and it is straightforward to start a touch on, say, button 17, end it on button 18 and still have buttonAction() declare "Button tapped: 17".
Any idea what I'm missing here?
(Edit: This is under Xcode 6 beta 3 BTW.)
// ViewController.swift
import UIKit
class ViewController: UIViewController {
let scrollView:UIScrollView = UIScrollView()
var GWIDTH:Float = 0.0
var GHEIGHT:Float = 0.0
override func viewDidLoad() {
super.viewDidLoad()
GWIDTH = self.view.bounds.size.width
GHEIGHT = self.view.bounds.size.height
scrollView.frame = CGRectMake(10, 10, GWIDTH-10, GHEIGHT-20)
scrollView.contentSize = CGSize(width:GWIDTH-20, height: 0)
self.view.addSubview(scrollView)
for currentTag in 1...30{
var currentButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
currentButton.frame = CGRectMake(100, scrollView.contentSize.height, 100, 50)
currentButton.backgroundColor = UIColor.greenColor()
currentButton.setTitle("Test Button \(currentTag)", forState: UIControlState.Normal)
currentButton.tag = currentTag
currentButton.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
scrollView.addSubview(currentButton)
scrollView.contentSize = CGSize(width:GWIDTH-20,height:2.0+currentButton.frame.size.height+currentButton.frame.origin.y)
}//next
}// end viewDidLoad()
func buttonAction(sender:UIButton!){
println("Button tapped: \(sender.tag)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}
Okay it's taken a fair bit of digging to get to the bottom of this but a couple of helpful Obj-C links...
UIControlEventTouchDragExit triggers when 100 pixels away from UIButton
How to correctly subclass UIControl?
http://www.bytearray.org/?p=5336 (particularly line 89)
...and it seems that the behaviour is standard due to the touch interface (personally I instinctively find the default zone excessive but I'm sure Apple did its homework) and can be overridden by either sub-classing UIControl or interrogating the position of the control event.
I've opted for the latter and here's an implementation specifically in Swift:
// ViewController.swift
import UIKit
class ViewController: UIViewController {
let buttonCount = 3
override func viewDidLoad() {
super.viewDidLoad()
for currentTag:Int in 1...buttonCount{
var currentButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
currentButton.frame = CGRectMake(50, Float(currentTag*50), 120, 50)
currentButton.backgroundColor = UIColor.greenColor()
currentButton.setTitle("Test Button \(currentTag)", forState: UIControlState.Normal)
currentButton.contentEdgeInsets = UIEdgeInsets(top:3,left:6,bottom:3,right:6)
currentButton.tag = currentTag
currentButton.addTarget(self,
action: "btn_TouchDown:",
forControlEvents: UIControlEvents.TouchDown)
currentButton.addTarget(self,
action: "btn_TouchDragExit:",
forControlEvents: UIControlEvents.TouchDragExit)
currentButton.addTarget(self,
action: "btn_TouchUpInside:event:",
forControlEvents: UIControlEvents.TouchUpInside)
currentButton.sizeToFit()
self.view.addSubview(currentButton)
}//next
}// end viewDidLoad()
func btn_TouchDown(sender:UIButton!){
println("TouchDown event: \(sender.tag)\n")
}
func btn_TouchDragExit(sender:UIButton!){
println("TouchDragExit event: \(sender.tag)\n")
}
func btn_TouchUpInside(sender:UIButton!,event:UIEvent!){
println("TouchUpInside event: \(sender.tag)")
var currentTouch:CGPoint = event.allTouches().anyObject().locationInView(sender)
println( "Point: \(currentTouch.x), \(currentTouch.y)\n" )
if currentTouch.x > sender.frame.width{return}
if currentTouch.x < 0 {return}
if currentTouch.y > sender.frame.height{return}
if currentTouch.y < 0 {return}
println("Event ended within frame!")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prefersStatusBarHidden() -> Bool {
return true
}
}