Swift Timer Loop doesn't trigger but view and controller are connected - swift

I'm trying to print the title "⚡️FlashChat" one letter at a time.
I'm coding along with a video and I've checked my code against the instructor's and it matches.
Right now, the title prints in its entirety when the sim is built.
I've adjusted the withTimeInterval to see fit that was set too quickly.
If I remove the loop and just execute the titleLabel.text = "", the title disappears, so it is connected correctly.
Thanks in advance!
import UIKit
class WelcomeViewController: UIViewController {
#IBOutlet weak var titleLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
titleLabel.text = ""
var charIndex = 0.0
let titleText = "⚡FlashChat"
for letter in titleText {
Timer.scheduledTimer(withTimeInterval: 7.0
* charIndex, repeats: false) {(timer)
in
self.titleLabel.text?.append(letter)}
}
charIndex += 1
}
}

You're incrementing charIndex outside your for loop. So interval will always be equal to 0

Related

Value of type 'SecondPageController' has no member 'miniView'

I got seems similar but little bit different question.
It is about declare size issue, but have small error here.
I think error is related to Main.stroyboard, and tried to change ViewController name and also added 'miniView' to ViewController.
My error is
"Value of type 'SecondPageController' has no member 'miniView'",
Witch is very common error(I looked many of same question with this format), but I think my error is relate to adding some new view or something.
And here is my code.
class SecondPageController: UIViewController {
#IBOutlet weak var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
var currentPage = 0
override func viewDidLoad() {
super.viewDidLoad()
imageArray = [UIImage(named: "bus1")!, UIImage(named: "bus2")!]
for i in 0..<imageArray.count {
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.miniView.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(startAnimating), userInfo: nil, repeats: true)
}
#objc func startAnimating() {
//that line check if the current page is the last one, and set it to the first, otherwise, it increment the currentPage
self.currentPage = (self.currentPage == imageArray.count-1) ? 0 : self.currentPage+1
var newOffset = mainScrollView.contentOffset
newOffset.x = mainScrollView.frame.width * CGFloat(self.currentPage)
self.mainScrollView.setContentOffset(newOffset, animated: true)
}
}
I expecting add something to this error solved.
There is no member miniView in SecondPageController. The error was very precise.
If you wanna use a component named miniView you need a reference to it, you can use 2 approaches:
1 - Storyboard:
Drag a view to your UIViewController and link it to #IBOutlet weak var miniView: UIView!
2 - Programatic:
Instantiate it like: let miniView = UIView()
Since you are using Storyboards, you probably forgot to add an #IBOutletto that view, so use approach 1.

Start a NSTimer when view loads

I have want to make a simple clock app where the colon blinks to make it look better. My code so far is:
#IBOutlet weak var clockLabel: UILabel!
var timerRunning = true
var timer = NSTimer()
var OnOff = 0
var colon = ":"
var hour = 0
var minute = 0
override func viewDidLoad() {
super.viewDidLoad()
clockLabel.text = ("\(hour)\(colon)\(minute)")
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "Counting", userInfo: nil, repeats: true)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func Counting(){
if OnOff == 1 {
OnOff = 0
colon = ":"
clockLabel.text = ("\(hour)\(colon)\(minute)")
}
if OnOff == 0 {
OnOff = 1
colon = ""
clockLabel.text = ("\(hour)\(colon)\(minute)")
}
}
The way I would like this to work is that the timer starts at exactly that moment when the view loads. I don't want to have to press a button to make the colon start blinking.
Thanks in advance
I don't see any issue with your timer (Your question title suggests otherwise), as far as I can tell it should fire every second after the view loads.
One thing I did notice is an issue in your code execution path:
The two consequent if statements overlap if you change the variable (in the first one), so read on to see my solution.
A little improvement I would make -- as the OnOff variable seems to be binary in nature -- let's make that a boolean type:
var colonShown : Bool = false // this is your "OnOff" variable (changed it to be more clear to the reader + made it boolean (you treat it as a boolean, so why not make it boolean?))
And then, in your timing function (I renamed it to tick()):
// renamed your Counting() function, no particular reason for that (sorry if that causes confusion) -- you can replace your Counting() function with this one (also make sure to update your timer selector that references the "Counting()" function on each "tick")
func tick(){
colonShown = !colonShown // toggle boolean value
colon = colonShown ? ":" : "" // neat one-liner for your if statement
clockLabel.text = ("\(hour)\(colon)\(minute)")
}

How to act on the label control of a mouse down in OS X

In my class ViewController: NSViewController
I have the following code:
#IBAction override func mouseDown(theEvent: NSEvent) {
self.myLabel.textColor = NSColor.redColor()
//either of these work to set the labels text value
self.myLabel.objectValue = "Hello World"
self.myLabel.stringValue = "This is a test"
switch(self) {
case self.myLabel:
//change text of myLabel
break;
case self.myLabel1:
//change text of myLabel1
break;
case self.myLabel2:
//change text of myLabel2
break;
}
}
This works to change the text and color of a Label Control called myLabel, but I have 3 Label controls on the View how do I change the color on the one that sends the mouse down event? The only way I can think to do it is with the switch statement as in the code above. But I think there is a better way by some how using the sender of the event?
I'm new to OS X and Mac development and come from the .NET C# world so thanks for helping this Mac noob! Using the latest Swift and Xcode.
I did figure out how to determine if one of my NSTextField controls was clicked on in the mouseDown event of the view:
#IBAction override func mouseDown(theEvent: NSEvent) {
var event_location: NSPoint!
event_location = theEvent.locationInWindow
self.mouseDownEvent = theEvent
var cntrl_id = NSTextField()
var cntrl_frame = NSRect()
var cntrl_name = String()
var cntrl_value = String()
var hit = Bool()
for view in self.view.subviews as [NSView] {
if let ct = view as? NSTextField {
cntrl_name = ct.identifier!
cntrl_id = ct
cntrl_frame = ct.frame
cntrl_value = ct.stringValue
hit = cntrl_frame.contains(event_location)
if hit {
controlToMove = cntrl_id
break
}
}
}
}
There are probably ways to make this more efficient possibly such as keeping a dictionary of all the NSTextField controls on the view, and then
check the dictionary for if I have a "hit" on one of the controls.

swift: timer (every second) + gestureRecognizer crashs the GUI

I have a simple gestureRecognizer. When the gesture is "UP" then the menu slides up. "DOWN": The menu slides down. This works.
I have a timer too. It simply counts a number++ every second. This works, too. But together the timer is crashing my GUI.
The animation starts correctly, but when the timer calls my counter-method it's jumping back to the origin GUI.
What kind of problem is that? I found nothing at google, but I think I searched the wrong words. (English isn't my mothertongue and in german there isn't so much literature...)
Here are fragments of my code:
class ViewController: UIViewController, MKMapViewDelegate{
#IBOutlet weak var swipe: UILabel!
var number: Int = 0
#IBOutlet weak var menuView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
var topSwipe = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
var downSwipe = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipes:"))
topSwipe.direction = .Up
downSwipe.direction = .Down
view.addGestureRecognizer(topSwipe)
view.addGestureRecognizer(downSwipe)
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "counter", userInfo: nil, repeats: true)
}
func counter() {
number++
swipe.text = "\(number)"
}
func handleSwipes(sender:UISwipeGestureRecognizer) {
if (sender.direction == .Up) {
print("TOP")
var menuPosition = CGPointMake(self.menuView.frame.origin.x, self.menuView.frame.origin.y - 100.0)
UIView.animateWithDuration(0.65, animations: {
self.menuView.frame = CGRectMake(menuPosition.x,menuPosition.y,self.menuView.frame.size.width,self.menuView.frame.size.height)
})
}
if (sender.direction == .Down) {
menuChoose = true
UIView.animateWithDuration(0.65, animations: {
var menuPosition = CGPointMake(self.menuView.frame.origin.x, self.menuView.frame.origin.y + 100.0)
self.menuView.frame = CGRectMake(menuPosition.x,menuPosition.y,self.menuView.frame.size.width,self.menuView.frame.size.height)
})
}
}
}
I tried to lock the timer. So when the gesture begins, then just count the number without swipe.text = "(number)"
The animation goes to end, but after an "unlock" the GUI jumped back to the origin.
Thank u for some codesnippets or keywords that I can search :)
It seems that whenever a UILabel's text property is set, it redraws the view, resulting in resetting menuView's position (perhaps someone can elaborate on the "why" in a comment). If you use auto layout constraints to manipulate the position of menuView, it works. You can do this by setting spaceConstraint.constant += 100 or spaceConstraint.constant -= 100 and then calling
UIView.animateWithDuration(0.65, animations: {
self.view.layoutIfNeeded()
})

Check text field Live

I have found this answer How to check text field input at real time?
This is what I am looking for. However I am having trouble actually implementing this code. Also my current geographical location makes googling almost impossible.
I want to be able to change the background color of the next text field if the correct number is entered into the previous text field. textfieldTwo background color will change to green if the correct value is entered in textFieldOne. If the value is incorrect then nothing will happen. Please help me out. I have two text fields called textFieldOne and textFieldTwo and nothing else in the code.
Just pop this in your main view controller in an empty project (try using iphone 6 on the simulator)
import UIKit
class ViewController: UIViewController {
var txtField:UITextField!
var txtFieldTwo:UITextField!
var rightNumber = 10
override func viewDidLoad() {
super.viewDidLoad()
//txtFieldOne
var txtField = UITextField()
txtField.frame = CGRectMake(100, 100, 200, 40)
txtField.borderStyle = UITextBorderStyle.None
txtField.backgroundColor = UIColor.blueColor()
txtField.layer.cornerRadius = 5
self.view.addSubview(txtField)
//txtFieldTwo
var txtFieldTwo = UITextField()
txtFieldTwo.frame = CGRectMake(100, 150, 200, 40)
txtFieldTwo.borderStyle = UITextBorderStyle.None
txtFieldTwo.backgroundColor = UIColor.blueColor()
txtFieldTwo.layer.cornerRadius = 5
self.view.addSubview(txtFieldTwo)
txtField.addTarget(self, action: "checkForRightNumber", forControlEvents: UIControlEvents.AllEditingEvents)
self.txtField = txtField
self.txtFieldTwo = txtFieldTwo
}
func checkForRightNumber() {
let number:Int? = self.txtField.text.toInt()
if number == rightNumber {
self.txtFieldTwo.backgroundColor = UIColor.greenColor()
} else {
self.txtFieldTwo.backgroundColor = UIColor.blueColor()
}
}
}
EDIT: Adding a version with IBOutlets and IBActions
Note that in this example the IBAction is connected to txtFieldOne on Sent Events / Editing Changed
Also, make sure your Text Fields border colors are set to None. In the storyboard, the way to do this is to choose the left most option with the dashed border around it. That's so you can color the backgrounds. You can use layer.cornerRadius to set the roundness of the border's edges.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var txtField: UITextField!
#IBOutlet weak var txtFieldTwo: UITextField!
var rightNumber = 10
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func checkForRightNumber(sender: AnyObject) {
let number:Int? = self.txtField.text.toInt()
if number == rightNumber {
self.txtFieldTwo.backgroundColor = UIColor.greenColor()
} else {
self.txtFieldTwo.backgroundColor = UIColor.blueColor()
}
}
}