Generic struct "WindowGroup" requires that "ViewController confirm to "View" - swift

I'm trying to build a simple Pomodoro timer and Swift is complaining with two errors:
Generic struct 'WindowGroup' requires that 'ViewController' conform to 'View'
Static method 'buildBlock' requires that 'ViewController' conform to 'View'
ContentView.swift
import UIKit
class ViewController: UIViewController {
// MARK: - Properties
let pomodoroDuration = 25 * 60 // 25 minutes
var timer = Timer()
var remainingSeconds = 0
// MARK: - Outlets
#IBOutlet weak var timeLabel: UILabel!
#IBOutlet weak var startButton: UIButton!
#IBOutlet weak var stopButton: UIButton!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
stopButton.isEnabled = false
}
// MARK: - Actions
#IBAction func startTimer(_ sender: Any) {
remainingSeconds = pomodoroDuration
startButton.isEnabled = false
stopButton.isEnabled = true
timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { [weak self] timer in
guard let self = self else { return }
if self.remainingSeconds > 0 {
self.remainingSeconds -= 1
self.updateTimeLabel()
} else {
timer.invalidate()
self.resetTimer()
// Add code to track completed pomodoros here
}
}
}
#IBAction func stopTimer(_ sender: Any) {
timer.invalidate()
resetTimer()
}
// MARK: - Helper Methods
func updateTimeLabel() {
let minutes = remainingSeconds / 60
let seconds = remainingSeconds % 60
timeLabel.text = String(format: "%02d:%02d", minutes, seconds)
}
func resetTimer() {
startButton.isEnabled = true
stopButton.isEnabled = false
timeLabel.text = "25:00"
}
}
The build error show in below file
TomatoApp.swift
import SwiftUI
#main
struct TomatoApp: App {
var body: some Scene {
WindowGroup {
ViewController()
}
}
}

Related

reduce the cell background based on time swift

I would like to make sure that my cell has a background related to the remaining time. in the sense that the closer I get to 0, the more I would like it to be reduced, so that we understand that the timer is about to expire.
according to the elapsed time it automatically reduces from right to left.
this is the code I use in managing the Cell
class TimerCell: UITableViewCell {
#IBInspectable var defaultBackgroundColor: UIColor = .white
#IBInspectable var runningBackgroundColor: UIColor = .white
#IBInspectable var pausedBackgroundColor: UIColor = .white
#IBInspectable var animationDuration: Double = 0
#IBOutlet var timeLabel: UILabel!
#IBOutlet var nameLabel: UILabel!
#IBOutlet var startButton: UIButton!
#IBOutlet var pauseButton: UIButton!
#IBOutlet var stopButton: UIButton!
weak var timer: Timer? {
didSet {
guard let timer = timer else {
updater?.invalidate()
return
}
if case .running = timer.state {
startUpdater()
}
configure(animated: false)
}
}
private weak var updater: Foundation.Timer?
override func awakeFromNib() {
super.awakeFromNib()
}
override func setEditing(_ editing: Bool, animated: Bool) {
print("*** \(Date()) setEditing(\(editing), animated: \(animated)) (timer?.name: \(String(describing: timer?.name)))")
super.setEditing(editing, animated: animated)
configure(animated: animated)
}
func configure(animated: Bool = true) {
guard let timer = timer else {
return
}
UIView.animate(withDuration: animated ? animationDuration : 0) {
guard !self.isEditing else {
self.timeLabel.text = timer.initialTime.hmsString
self.startButton.safelySetIsHidden(true)
self.pauseButton.safelySetIsHidden(true)
self.stopButton.safelySetIsHidden(true)
self.backgroundColor = self.defaultBackgroundColor
return
}
self.timeLabel.text = ceil(timer.timeForState).hmsString
self.nameLabel.text = timer.name
switch timer.state {
case .stopped:
self.stopButton.safelySetIsHidden(true)
self.pauseButton.safelySetIsHidden(true)
self.startButton.safelySetIsHidden(false)
self.backgroundColor = self.defaultBackgroundColor
case .running:
self.startButton.safelySetIsHidden(true)
self.stopButton.safelySetIsHidden( ceil(timer.timeForState) == 0 ? true : false )
self.pauseButton.safelySetIsHidden( ceil(timer.timeForState) == 0 ? true : false )
self.backgroundColor = self.runningBackgroundColor
case .paused:
self.pauseButton.safelySetIsHidden(true)
self.startButton.safelySetIsHidden(false)
self.stopButton.safelySetIsHidden(false)
self.backgroundColor = self.pausedBackgroundColor
}
}
}
#IBAction private func startTimer() {
timer?.state = .running
configure()
startUpdater()
}
#IBAction private func pauseTimer() {
timer?.state = .paused
configure()
}
#IBAction private func stopTimer() {
timer?.state = .stopped
configure()
}
private func startUpdater() {
guard let timer = timer else {
return
}
let date = Date(timeIntervalSinceNow: timer.timeForState.truncatingRemainder(dividingBy: 1))
let updater = Foundation.Timer(fire: date, interval: 1, repeats: true) {
[weak timer] updater in
self.configure()
if timer?.state != .running {
updater.invalidate()
}
}
self.updater = updater
RunLoop.main.add(updater, forMode: .common)
}
}
I think you're after something like this:
That's not trivial to achieve. I did it by adding a CAGradientLayer to the view and animating its locations property. At the same time, I ran the timer to change the label value.
So you might do it that way; you would probably want to tweak the values, of course. This is just a proof-of-concept demo.

How Can I Make A Timer Using String In xCode

So I'm trying to make a chess timer. I'm using string to make the 00:00 in a variable called storeTimed. Is there a way possible to make that used an timer to count down from that?
Here's my code:
The part I need help with is the updateTimer() function. Since the storedTime is a string trying to pass as a Int, xCode isn't liking it. I'm honestly not very sure what I could do. Mostly at the else statement, but the whole part in general
class ChessTimer: UIViewController {
#IBOutlet weak var playerTimer1: UILabel!
#IBOutlet weak var playerTimer2: UILabel!
var timer = Timer()
var time = 10
var isTimerRunning = false
var storedTime = "00:00"
override func viewDidLoad() {
super.viewDidLoad()
if isTimerRunning == false {
runTimer()
}
}
#IBAction func restartButton(_ sender: UIButton) {
}
#IBAction func pausePressed(_ sender: UIButton) {
timer.invalidate()
}
#IBAction func settingsPressed(_ sender: UIButton) {
performSegue(withIdentifier: "goToSettings", sender: self)
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self,selector: (#selector(ChessTimer.updateTimer)),userInfo: nil, repeats: true)
isTimerRunning = true
}
#objc func updateTimer() {
if Int(storedTime) < 1 {
timer.invalidate()
playerTimer1.text = "00:00"
playerTimer2.text = "00:00"
}
else {
Int(storedTime)! -= 1
playerTimer1.text = prodTimeString(time: TimeInterval(storedTime)!)
}
}
func prodTimeString(time: TimeInterval) -> String {
let prodMinutes = Int(time) / 60 % 60
let prodSeconds = Int(time) % 60
return String(format: "%02d:%02d", prodMinutes, prodSeconds)
}
#IBAction func playerButton1(_ sender: UIButton) {
}
#IBAction func playerButton2(_ sender: UIButton) {
}
#IBAction func unwindToVC1(sender: UIStoryboardSegue) {
if let settingsController = sender.source as? SettingsController {
playerTimer1.text = settingsController.storedTime
playerTimer2.text = settingsController.storedTime
storedTime = settingsController.storedTime
}
}
}
To keep things simple, here's the code. I have removed the functions that aren't relevant to the discussion - non-implemented buttons, etc.,
The simple idea is that you use numbers (Int / Double / whatever) to store variables that you are counting with, and then have helper functions to present the variable in different formats
import UIKit
class ChessTimer: UIViewController {
var timer = Timer()
var isTimerRunning = false
var storedTime : Int = 0 // use an integer to store the time
override func viewDidLoad() {
super.viewDidLoad()
if isTimerRunning == false {
runTimer()
}
}
func runTimer() {
timer = Timer.scheduledTimer(timeInterval: 1, target: self,selector: (#selector(ChessTimer.updateTimer)),userInfo: nil, repeats: true)
isTimerRunning = true
}
#objc func updateTimer() {
// because we're storing the value in an Int, we don't need to convert it here
storedTime -= 1
if storedTime < 1 {
timer.invalidate()
// use the helper function to format the result for zero time as well as everything else
// that way, if you ever change it, you only have to change in one place
playerTimer1.text = prodTimeString(0)
playerTimer2.text = prodTimeString(0)
}
else {
playerTimer1.text = prodTimeString(storedTime)
}
}
func prodTimeString(_ time: Int) -> String {
// because there's only one parameter, and it's obvious, add '_' then you don't need the label when you call it
let prodMinutes = time / 60 % 60
let prodSeconds = time % 60
return String(format: "%02d:%02d", prodMinutes, prodSeconds)
}
}

Swift: another timer starting when application enters background

I've been struggling to figure this out for a few days: I need to create a timer that the user can't kill, so once they start it, even if they kill the app or it enters background, it will pick up where it left off, and to achieve this I am saving the date when the app terminated and then calculating the difference, so that part works fine.
The problem I keep running into however is that a second timer seems to start if I minimise the app and bring it back. I'm not sure how timers are managed in the background, but nothing of what I tried (calling timer.invalidate() when applicationWillResignActive gets called, calling it in deinit() ) seems to work. The behaviour I see after this is that the timer will count like this: 80 - 78 - 79 - 76 - 77..
There's also a problem where the timer will sometime run past the time it's supposed to run for after killing the app, but I can't find the exact cause for that because it doesn't always happen.
Any idea what I'm doing wrong?
Thanks a lot.
class Focus: UIViewController {
// MARK: Variables
var timer = Timer()
let timeToFocus = UserDefaults.standard.double(forKey: "UDTimeToFocus")
let currentFocusedStats = UserDefaults.standard.integer(forKey: "UDFocusStats")
// MARK: Outlets
#IBOutlet weak var progress: KDCircularProgress!
#IBOutlet weak var timeLabel: UILabel!
#IBOutlet weak var focusTimeLabel: UILabel!
#IBOutlet weak var stepNameLabel: UILabel!
#IBOutlet weak var focusAgain: UIButton!
#IBOutlet weak var allDone: UIButton!
#IBOutlet weak var help: UIButton!
#IBOutlet weak var dottedCircle: UIImageView!
// MARK: Outlet Functions
#IBAction func helpTU(_ sender: Any) { performSegue(withIdentifier: "ToFocusingHelp", sender: nil) }
#IBAction func helpTD(_ sender: Any) { help.tap(shape: .rectangle) }
#IBAction func allDoneTU(_ sender: Any) {
UserDefaults.standard.set(false, forKey: "UDFocusIsRunning")
UserDefaults.standard.set(false, forKey: "UDShouldStartFocus")
completeSession()
hero(destination: "List", type: .zoomOut)
}
#IBAction func allDoneTD(_ sender: Any) { allDone.tap(shape: .rectangle) }
#IBAction func focusAgainTU(_ sender: Any) {
UserDefaults.standard.set(currentFocusedStats + Int(timeToFocus), forKey: "UDFocusStats")
UserDefaults.standard.set(true, forKey: "UDShouldStartFocus")
initFocus()
}
#IBAction func focusAgainTD(_ sender: Any) { focusAgain.tap(shape: .rectangle) }
// MARK: Class Functions
#objc func initFocus() {
var ticker = 0.0
var angle = 0.0
var duration = 0.0
if UserDefaults.standard.bool(forKey: "UDShouldStartFocus") == true {
UserDefaults.standard.set(Date(), forKey: "UDFocusStartDate")
UserDefaults.standard.set(false, forKey: "UDShouldStartFocus")
ticker = timeToFocus
duration = timeToFocus
angle = 0.0
print("starting")
} else {
let elapsedTime = difference(between: UserDefaults.standard.object(forKey: "UDFocusStartDate") as! Date, and: Date())
let timeLeft = timeToFocus - elapsedTime
ticker = timeLeft
duration = timeLeft
angle = elapsedTime / (timeToFocus / 360)
}
// Timer
let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { timer in
if ticker > 0 {
self.timeLabel.text = "\(Int(ticker))s"
ticker -= 1
}
}
timer.fire()
// Progress Circle
progress.animate(fromAngle: angle, toAngle: 360, duration: duration) { completed in
if completed { self.completeSession() }
}
// UI Changes
allDone.isHidden = true
focusAgain.isHidden = true
help.isHidden = false
}
func completeSession() {
// The timer gets fired every time, but this will invalidate it if it's complete
timer.invalidate()
timeLabel.text = "Done"
help.isHidden = true
allDone.isHidden = false
focusAgain.isHidden = false
}
// MARK: viewDidLoad
override func viewDidLoad() {
initFocus()
allDone.isHidden = true
focusAgain.isHidden = true
if timeToFocus < 3600 { focusTimeLabel.text = "Focusing for \(Int(timeToFocus/60)) minutes" }
else if timeToFocus == 3600 { focusTimeLabel.text = "Focusing for \(Int(timeToFocus/60/60)) hour" }
else { focusTimeLabel.text = "Focusing for \(Int(timeToFocus/60/60)) hours" }
stepNameLabel.text = UserDefaults.standard.string(forKey: "UDSelectedStep")
// This resumes the timer when the user sent the app in the background.
NotificationCenter.default.addObserver(self, selector: #selector(self.initFocus), name: NSNotification.Name(rawValue: "WillEnterForeground"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(self.fadeProgress), name: NSNotification.Name(rawValue: "WillEnterForeground"), object: nil)
}
#objc func fadeProgress(){
// This function is called both when the view will enter foreground (for waking the phone or switching from another app) and on viewWillAppear (for starting the app fresh). It will fade the progress circle and buttons to hide a flicker that occurs.
timeLabel.alpha = 0
dottedCircle.alpha = 0
progress.alpha = 0
allDone.alpha = 0
focusAgain.alpha = 0
DispatchQueue.main.asyncAfter(deadline: .now() + 0.2, execute: {
UIButton.animate(withDuration: 0.5, animations: {
self.timeLabel.alpha = 1
self.dottedCircle.alpha = 1
self.progress.alpha = 1
self.allDone.alpha = 1
self.focusAgain.alpha = 1
})
})
}
// MARK: viewWillAppear
override func viewWillAppear(_ animated: Bool) { fadeProgress() }
}
It seems the problem is that you create a local timer variable inside initFocus() but you call invalidate inside completeSession for another timer defined there:
class Focus: UIViewController {
// MARK: Variables
var timer = Timer()

How can I get the game to show the word after all guesses have been used up?

so I'm new to coding and I've been doing practice games a such to build my skills. I've created this word guessing game and I'm trying to make the game show the word after all guesses have been used up. However, the program doesn't read the code I write to set the label to display the answer. Here is the code I've written so far:
class ViewController: UIViewController {
var listOfWords = ["ladybug", "program", "computer", "language", "glorious", "incandescent"]
let incorrectMovesAllowed = 7
var totalWins = 0 {
didSet {
newRound()
}
}
var totalLosses = 0 {
didSet {
newRound()
}
}
#IBOutlet var letterButtons: [UIButton]!
#IBAction func buttonPressed(_ sender: UIButton) {
sender.isEnabled = false
let letterString = sender.title(for: .normal)!
let letter = Character(letterString.lowercased())
currentGame.playerGuessed(letter: letter)
updateUI()
updateGameState()
}
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet weak var correctWordLabel: UILabel!
#IBOutlet weak var treeImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
newRound()
// Do any additional setup after loading the view, typically from a nib.
}
func enableLetterButtons (_enable: Bool){
for button in letterButtons {
button.isEnabled = _enable
}
}
var currentGame : Game!
func newRound() {
if !listOfWords.isEmpty{
let newWord = listOfWords.removeFirst()
currentGame = Game (word: newWord, incorrectMovesRemaining: incorrectMovesAllowed, guessedLetters: [])
enableLetterButtons(_enable: true)
updateUI()
} else {
enableLetterButtons (_enable: false)
}
}
func updateUI() {
var letters = [String] ()
for letter in currentGame.formattedWord.characters {
letters.append(String(letter))
}
let wordWithSpacing = letters.joined(separator: " ")
correctWordLabel.text = wordWithSpacing
scoreLabel.text = "Wins: \(totalWins), Losses:\(totalLosses)"
treeImageView.image = UIImage (named: "Tree \(currentGame.incorrectMovesRemaining)")
}
func updateGameState(){
var letters = [String] ()
for letter in currentGame.word.characters {
letters.append(String(letter))
}
let theAnswer = letters.joined(separator: " ")
if currentGame.incorrectMovesRemaining == 0 {
correctWordLabel.text = theAnswer
Thread.sleep(forTimeInterval: 3)
totalLosses += 1
} else if currentGame.word == currentGame.formattedWord {
totalWins += 1
} else {
updateUI()
}
}
}
In addition, I have a structure that is written like this:
import Foundation
struct Game {
var word : String
var incorrectMovesRemaining : Int
var guessedLetters: [Character]
mutating func playerGuessed (letter: Character){
guessedLetters.append(letter)
if !word.characters.contains(letter){
incorrectMovesRemaining -= 1
}
}
var formattedWord: String {
var guessedWord = ""
for letter in word.characters {
if guessedLetters.contains(letter) {
guessedWord += "\(letter)"
} else {
guessedWord += "_"
}
}
return guessedWord
}
}
You need to redraw your UI, this is done with self.setNeedsDisplay(). It notifies the system that the view's contents needs to be redrawn. In your updateUI() you can add this.
Regarding setNeedsDisplay you can get more information here
class ViewController: UIViewController {
var listOfWords = ["ladybug", "program", "computer", "language", "glorious", "incandescent"]
let incorrectMovesAllowed = 7
var totalWins = 0 {
didSet {
newRound()
}
}
var totalLosses = 0 {
didSet {
newRound()
}
}
#IBOutlet var letterButtons: [UIButton]!
#IBAction func buttonPressed(_ sender: UIButton) {
sender.isEnabled = false
let letterString = sender.title(for: .normal)!
let letter = Character(letterString.lowercased())
currentGame.playerGuessed(letter: letter)
updateUI()
updateGameState()
}
#IBOutlet weak var scoreLabel: UILabel!
#IBOutlet weak var correctWordLabel: UILabel!
#IBOutlet weak var treeImageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
newRound()
// Do any additional setup after loading the view, typically from a nib.
}
func enableLetterButtons (_enable: Bool){
for button in letterButtons {
button.isEnabled = _enable
}
}
var currentGame : Game!
func newRound() {
if !listOfWords.isEmpty{
let newWord = listOfWords.removeFirst()
currentGame = Game (word: newWord, incorrectMovesRemaining: incorrectMovesAllowed, guessedLetters: [])
enableLetterButtons(_enable: true)
updateUI()
} else {
enableLetterButtons (_enable: false)
}
}
func updateUI() {
var letters = [String] ()
for letter in currentGame.formattedWord.characters {
letters.append(String(letter))
}
let wordWithSpacing = letters.joined(separator: " ")
correctWordLabel.text = wordWithSpacing
scoreLabel.text = "Wins: \(totalWins), Losses:\(totalLosses)"
treeImageView.image = UIImage (named: "Tree \(currentGame.incorrectMovesRemaining)")
self.setNeedsDisplay()
}
func updateGameState(){
var letters = [String] ()
for letter in currentGame.word.characters {
letters.append(String(letter))
}
let theAnswer = letters.joined(separator: " ")
if currentGame.incorrectMovesRemaining == 0 {
correctWordLabel.text = theAnswer
Thread.sleep(forTimeInterval: 3)
totalLosses += 1
} else if currentGame.word == currentGame.formattedWord {
totalWins += 1
} else {
updateUI()
}
}
}
Create a variable that will keep track of how many times you have guessed wrong. Then you can do this:
Use a while statement:
while numberOfTimesGuessedWrong <= 7{
}
//when you have guessed incorrectly 7 times, the compiler will move here:
wordLabel.text = "\(correctAnswer)"
So when you guess incorrectly 7 times, on the 8th time, it will then show the correct answer.

AVPlayer loads multiple times before playing - long delay before streaming

I'm facing a very unique situation, AVPlayer is trying to stream a URL that it loads multiple times (I see in control centre) before eventually playing it, after a long delay of about 120 seconds or so (sometimes more). I don't know why that is happening. I use a singleton instance of KDEAudioPlayer - any help would be appreciated.
KDEAudioPlayer Code:
import UIKit
import KDEAudioPlayer
var urlToPlay : NSURL!
var titleTrackBeingPlayed = String?()
class MediaPlayerViewController: FXBlurView, AudioPlayerDelegate {
//MARK: Variables
var seekToTime = NSTimeInterval()
var streaming = true
var timer:NSTimer?
var change:CGFloat = 0.01
//MARK: Connections
#IBOutlet weak var loadingActivityIndicator: UIActivityIndicatorView!
#IBOutlet weak var streamingFromServerLabel: UILabel!
#IBOutlet weak var timelineSlider: UISlider!
#IBOutlet weak var totalTimeLabel: UILabel!
#IBOutlet weak var nowTimeLabel: UILabel!
#IBOutlet weak var toggleButton: UIButton!
#IBOutlet weak var volumeControlSlider: UISlider!
#IBOutlet weak var titleLabel: UILabel!
//MARK: Actions
#IBAction func endTrackPlayerButtonPressed(sender: UIButton) {
//TODO: R&D how to dismiss.
print("media player view to be dismissed")
if let viewWithTag = self.viewWithTag(1089) {
print("Tag 1089")
Singleton.stop()
viewWithTag.removeFromSuperview()
}
}
#IBAction func timelineSliderValueChanged(sender: UISlider) {
Singleton.pause()
Singleton.seekToTime(NSTimeInterval(sender.value))
timelineSlider?.setValue(sender.value, animated: true)
Singleton.resume()
}
#IBAction func playPauseButtonPressed(sender: UIButton) {
toggle()
}
//MARK: Initializer for Class
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.tintColor = UIColor.clearColor()
if Singleton.isPlaying {
Singleton.isPlaying = false
}
playerSetup()
toggle()
}
//MARK: Setup for Audio Player
func playerSetup() {
Singleton.playItemWithUrl(urlToPlay)
Singleton.player.delegate = self
timelineSlider?.continuous = true
self.titleLabel?.text = titleTrackBeingPlayed
}
internal func refreshAudioView(_ :NSTimer) {
}
func toggle(){
if Singleton.isPlaying {
pauseTrack()
toggleButton.setImage(UIImage(named: "Play"), forState: .Normal)
}
else if !Singleton.isPlaying {
playTrack()
toggleButton?.setImage(UIImage(named: "Pause"), forState: .Normal)
}
}
func audioPlayer(audioPlayer: AudioPlayer, willStartPlayingItem item: AudioItem) {
titleLabel.text = titleTrackBeingPlayed
}
func audioPlayer(audioPlayer: AudioPlayer, didFindDuration duration: NSTimeInterval, forItem item: AudioItem) {
totalTimeLabel?.text = makeTimeString(Float(duration))
timelineSlider?.maximumValue = Float(duration)
timelineSlider?.minimumValue = 0.0
self.titleLabel?.text = titleTrackBeingPlayed
}
func audioPlayer(audioPlayer: AudioPlayer, didUpdateProgressionToTime time: NSTimeInterval, percentageRead: Float) {
timelineSlider?.setValue(Float(time), animated: true)
nowTimeLabel?.text = makeTimeString(Float(time))
Singleton.player.volume = volumeControlSlider.value
seekToTime = time
}
override func remoteControlReceivedWithEvent(event: UIEvent?) {
if let event = event {
Singleton.player.remoteControlReceivedWithEvent(event)
self.canBecomeFirstResponder()
}
}
func audioPlayer(audioPlayer: AudioPlayer, didChangeStateFrom from: AudioPlayerState, toState to: AudioPlayerState) {
if to == .Playing {
if streaming {
streamingFromServerLabel.hidden = false
loadingActivityIndicator.hidden = true
toggleButton?.setImage(UIImage(named: "Pause"), forState: .Normal)
}
timer = NSTimer.scheduledTimerWithTimeInterval(0.01, target: self, selector: #selector(TrackMediaPlayerViewController.refreshAudioView(_:)), userInfo: nil, repeats: true)
}
else if to == .Buffering || to == .WaitingForConnection {
loadingActivityIndicator.hidden = false
}
else {
streamingFromServerLabel.hidden = true
}
}
func playTrack() {
if seekToTime > 0.0 {
Singleton.resume()
} else {
Singleton.play()
}
Singleton.isPlaying = true
}
func pauseTrack() {
Singleton.pause()
Singleton.isPlaying = false
}
//MARK: Convert NSTime to String
func makeTimeString(value:Float) -> String
{
if value == 0 || value.isNaN
{
return "00:00"
}
let hr = (Int)(value / 3600)
let min = (Int)((value % 3600) / 60)
let sec = (Int)((value % 3600) % 60)
let timestamp = String(format:"%d:%02d.%02d", hr, min, sec)
return timestamp
}
}
Singleton Code:
import Foundation
import UIKit
import KDEAudioPlayer
class Singleton: AudioPlayerDelegate {
static let shareInstance = DarsPlayerSingleton()
static let player = AudioPlayer()
static var isPlaying = Bool()
private init (){
}
static func playItemWithUrl(url: NSURL) {
let item = AudioItem(mediumQualitySoundURL: url)
player.playItem(item!)
}
static func play() {
player.resume()
isPlaying = true
}
static func pause() {
player.pause()
isPlaying = false
}
static func stop() {
player.stop()
}
static func seekToTime(time: NSTimeInterval){
player.seekToTime(time)
}
static func resume() {
player.resume()
}
}