Reputation: 37
OK, so all this app should do far is show a clock on the screen that is updated via a timer every second. Im using Xcode 8/Swift 3.
Below is the code from the viewcontroller:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
let clock = clockClass()
clock.startTimer()
//currentTime.text = "It Works Here!"
}
func updateClockView(updatedTime : String) {
print("new time is: \(updatedTime)")
//currentTime.text = updatedTime
}
/*
ACTIONS AND LABELS BELOW HERE PLEASE
*/
@IBOutlet weak var currentTime: UILabel!
}
If I rearrange the code so that all of it is within the viewcontroller file, then it works perfectly. In trying to maintain an MVC like appearance, I moved the timer code to another class and then just passed the updated time back to viewcontroller.
Below is the code from the other class, called clockClass.
import Foundation
class clockClass{
let view = ViewController()
public func startTimer(){
var timer = Timer()
timer = Timer.scheduledTimer(timeInterval: 1,
target:self,
selector: #selector(clockClass.updateClock),
userInfo: nil,
repeats: true)
timer.fire()
}
/*
updateClock CONSTRUCTS THE CURRENT TIME BY EXTRACTING THE HOURS, MINUTES AND SECONDS COMPONENTS FROM THE CALENDAR OBJECT AND THEN FORMATTING THAT DATE INTO STRING FORMAT. THE CLOCK ON THE SCREEN IS THEN UPDATED IN REAL TIME.
*/
@objc func updateClock(){
let dateObject = NSDate()
let calendar = NSCalendar.current
let components = calendar.dateComponents([.hour, .minute,.second], from: dateObject as Date )
let formatter = DateFormatter()
formatter.timeStyle = .medium
let theDateIWant = calendar.date(from: components)!
let timeString = formatter.string(from: theDateIWant)
view.updateClockView(updatedTime: timeString)
}
}
I can see via the debugger that everything works fine right up until the assignment of "updatedTime" to the UILabel! within updateClockView() in the viewcontroller. It crashes at the point of assignment with "fatal error: unexpectedly found nil while unwrapping an Optional value". The variable "updatedTime", upon checking, returns as a normal string, not an optional string. Oddly enough, I can update the UILabel! via "currentTime.text = stringVariable/textString" if I do so from within viewDidLoad(). This, however, is not updated every second though.
If, when running the program as normal, I print to the console instead of updating the UILabel!, the new time prints out nicely every second.
I have tried rearranging the code in various ways as well as using dispatchQueue.main.async() to update the main thread (I assume I was doing it correctly as the program ran with no compilation or runtime errors but the clock did not display, nevermind update itself).
Other googling resulted only in references to older versions of swift with deprecated functions or posts/articles that seemed way over my head.
Can anyone spot the error that I am missing that is preventing this program from working properly? I have been at this for over 10 hours now and don't have much hair left to spare....
Many thanks in advance!
edit: see screenshot here: [1]: https://i.sstatic.net/rgQgd.png
Upvotes: 0
Views: 194
Reputation: 511
Looking at your code, it seems like you are missing basic concept of delegation.
This whole thing can be done via delegation
pattern or this can be done by just adding two lines of code. Just create a property of ViewController
in your clockClass
class
Changes you need to make in clockClass
let view = ViewController()
to var view: ViewController
Replace these lines in ViewController
let clock = clockClass()
clock.startTimer()
With these lines
let clock = clockClass()
clock.view = self
clock.startTimer()
Upvotes: 2