为什么一个标签更新比另一个更快?

时间:2015-10-29 19:10:53

标签: macos performance applescript swift2

我正在创建自己的Spotify控制器,以学习如何与AppleScript和Swift交互(使用Objective-C作为桥梁)以便稍后制作更大的项目。唯一的问题是当前进度时间似乎比剩下的时间稍微快一些。

这就是我的应用程序的样子:

enter image description here

左边的时间似乎比右边的时间略快,这意味着它不准确,看起来有点奇怪。我怎样才能解决这个问题,以便进度时间和时间同时更新?

这是我的代码:

ViewController.swift

import Cocoa


class ViewController: NSViewController {


    @IBOutlet weak var statusLabel: NSTextField!
    @IBOutlet weak var songProgress: NSProgressIndicator!
    @IBOutlet weak var lblCurrentProgress: NSTextField!
    @IBOutlet weak var lblTrackLength: NSTextField!

    //let debugger = Debug(appName:"Spotify Menu", debugable: )

    var previousScript:String = ""
    var toggleScript:String = ""
    var nextScript:String = ""
    var statusScript:String = ""
    var artistScript:String = ""
    var songNameScript:String = ""
    var trackPosScript:String = ""
    var trackLengthScript:String = ""
    var trackIDscript:String = ""


    var trackName:String = "unknown"
    var artistName:String = "unknown"
    var playerStatus:String = "unknown"
    var trackID:String = "unknown"
    var playerPosistion:Double = -1.0
    var trackLength:Double = -1.0
    var percentThrough:Double = -1.0

    let timeFormatter = twoDiffrentTimes()


    func main()
    {

        getStatus()
        getSongName()
        getArtist()
        getTrackLength()
        getPlayerPos()
        getID()
        percentThrough = (playerPosistion/trackLength)*100

        if(playerStatus == "playing" && trackName != "unknown" && artistName != "unknown")
        {
            statusLabel.stringValue = "Spotify is currently playing the song \"\(trackName)\" by \"\(artistName)\""
        } else if(playerStatus == "paused"){
            statusLabel.stringValue = "Spotify is currently paused"
        } else if(playerStatus == "stopped") {
            statusLabel.stringValue = "Spotify is not playing any music"
        } else {
            statusLabel.stringValue = "There is currently an error"
        }

        //NSLog("The song is currently \(percentThrough.toDecimalPlace("2"))% the way in")
        songProgress.doubleValue = percentThrough

        timeFormatter.update(playerPosistion, timeTwo: trackLength-playerPosistion)
        lblCurrentProgress.stringValue = timeFormatter.timeOneString
        lblTrackLength.stringValue = timeFormatter.timeTwoString
    }




    override func viewDidLoad() {
        super.viewDidLoad()
        previousScript = readFile("previousTrack")
        if(previousScript == "")
        {
            NSLog("Error finding previous track script")
            exit(1)
        }

        toggleScript = readFile("playPause")
        if(toggleScript == "")
        {
            NSLog("Error finding toggle script")
            exit(1)
        }

        nextScript = readFile("nextTrack")
        if(nextScript == "")
        {
            NSLog("Error going forwared a track")
            exit(1)
        }

        statusScript = readFile("playerStatus")
        if(statusScript == "")
        {
            NSLog("Error going back a track")
            statusLabel.stringValue = "Spotify is in an unknown status"
            exit(1)
        }

        artistScript = readFile("getArtist")
        if(artistScript == "")
        {
            NSLog("Cannot get artist script")
            exit(1)
        }

        songNameScript = readFile("getSongName")
        if(songNameScript == "")
        {
            NSLog("Cannot get song name script")
            exit(1)
        }

        trackPosScript = readFile("playerPosition")
        if(trackPosScript == "")
        {
            NSLog("Error getting track posistion script")
            exit(1)
        }

        trackLengthScript = readFile("durationOfSong")
        if(trackLengthScript == "")
        {
            NSLog("Error getting track length script")
            exit(1)
        }

        trackIDscript = readFile("trackID")
        if(trackIDscript == "")
        {
            NSLog("Error getting")
        }


        main()
        NSTimer.scheduledTimerWithTimeInterval(0.3, target: self, selector: Selector("main"), userInfo: nil, repeats: true)
    }

    override var representedObject: AnyObject? {
        didSet {
        // Update the view, if already loaded.
        }
    }

    @IBAction func previous(sender: AnyObject)
    {
        runAppleScript(previousScript)
    }

    @IBAction func toggle(sender: AnyObject)
    {
        runAppleScript(toggleScript)
    }

    @IBAction func next(sender: AnyObject)
    {
        let nextFile = readFile("nextTrack")
        if(nextFile == "")
        {
            NSLog("Error going forwared a track")
        } else {
            runAppleScript(nextFile)
        }
    }



    func getPlayerPos()
    {
        playerPosistion = runAppleScript(trackPosScript).toDouble()
    }

    func getTrackLength()
    {
        trackLength = runAppleScript(trackLengthScript).toDouble()
    }

    func getSongName()
    {
        trackName = runAppleScript(songNameScript)
    }

    func getArtist()
    {
            artistName = runAppleScript(artistScript)
    }

    func getID()
    {
        trackID = runAppleScript(trackIDscript)
    }

    func getStatus()
    {
        let resultData = runAppleScript(statusScript)
        if(resultData == "playing" || resultData == "paused" || resultData == "stopped")
        {
            playerStatus = resultData
        } else {
            playerStatus = "unknown"
        }
    }

}

classes.swift

import Foundation

class twoDiffrentTimes
{
    var timeOne:Double = 0.0
    var iMinuteOne:Int = 0
    var iSecondsOne:Int = 0
    var minuteOne:String = ""
    var secondsOne:String = ""
    var timeOneString:String = ""
    var uSecondsOne:Double = 0.0
    var temp:Int = 0

    var timeTwo:Double = 0.0
    var iMinuteTwo:Int = 0
    var iSecondsTwo:Int = 0
    var minuteTwo:String = ""
    var secondsTwo:String = ""
    var timeTwoString:String = ""
    var uSecondsTwo:Double = 0.0

    func update(timeOne:Double, timeTwo:Double)
    {
        //First Time
        self.temp = Int(timeOne)
        self.iMinuteOne = temp / 60
        self.iSecondsOne = temp % 60
        self.minuteOne = "\(iMinuteOne)"
        if(self.iSecondsOne < 10)
        {
            self.secondsOne = "0\(self.iSecondsOne)"
        } else {
            self.secondsOne = "\(self.iSecondsOne)"
        }
        self.timeOneString = "\(self.iMinuteOne).\(self.secondsOne)"


        //Second Time
        self.temp = Int(timeTwo)
        self.iMinuteTwo = temp / 60
        self.iSecondsTwo = temp % 60
        self.minuteTwo = "\(iMinuteTwo)"
        if(self.iSecondsTwo < 10)
        {
            self.secondsTwo = "0\(self.iSecondsTwo)"
        } else {
            self.secondsTwo = "\(self.iSecondsTwo)"
        }
        self.timeTwoString = "\(self.iMinuteTwo).\(self.secondsTwo)"

    }
}

extensions.swift

import Foundation

extension String {
    func toDouble() -> Double {
        if let unwrappedNum = Double(self) {
            return unwrappedNum
        } else {
            // Handle a bad number
            print("Error converting \"" + self + "\" to Double")
            return 0.0
        }

    }

}

extension Double {
    func toDecimalPlace(f: String) -> String {
        return NSString(format: "%0.\(f)f", self) as String
    }

    func decimalValue() -> Int
    {
        if let decimalString = String(self).componentsSeparatedByString(".").last, decimal = Int(decimalString) {
            return decimal   // 535
        } else {
            return -1
        }
    }

}

functions.swift

import Foundation

func readFile(fileName: String) -> String{

    if let filepath = NSBundle.mainBundle().pathForResource(fileName, ofType: "txt") {
        do {
            let contents = try NSString(contentsOfFile: filepath, usedEncoding: nil) as String
            print(contents)
            return contents
        } catch {
            NSLog("Content Could Not Be Loaded")
            return ""
        }
    } else {
        NSLog("File \(fileName).\("txt") could not be found")
        return ""
    }
}

func runAppleScript(script:String) -> String
{
    let theResult:String
    let errorInfo = AutoreleasingUnsafeMutablePointer<NSDictionary?>()
    let startAtLoginScript: NSAppleScript = NSAppleScript(source: script)!
    let theDiscriptor:NSAppleEventDescriptor = startAtLoginScript.executeAndReturnError(errorInfo)
    if let _ = theDiscriptor.stringValue
    {
        theResult = theDiscriptor.stringValue!
    } else {
        theResult = ""
    }

    return theResult
}

errorClases.swift

import Foundation

enum MyAppleScriptError: ErrorType {
    case ExecutingScriptFailed
    case GettingStringValueFailed
}

最后但并非最不重要 durationOfSong.txt (AppleScript)

tell application "Spotify"
    set songLength to (duration of current track) / 1000 as string
    return songLength
end tell

playerPosition

tell application "Spotify"
    set currentPosistion to player position as string
    return currentPosistion
end tell

修改:
更新的代码

1 个答案:

答案 0 :(得分:0)

我建议您学习如何通过AppleScript-ObjC桥直接从Swift调用AppleScript处理程序。这比使用代码字符串和NSAppleScript更好地工作,这是缓慢而令人讨厌的,并不是一个好方法。这里的教程:

http://macscripter.net/viewtopic.php?id=43127

-

ETA:

“我已经成功地将NSAppleScript移动到了Swift2。唯一的问题仍然是无法解决问题。它仍处于暂停状态。”

嗯,这太烦人了。 FWIW,我放弃了twoDiffrntTimes类,因为它没有做任何在单行函数中无法完成的事情,并将main()的结尾更改为:

func main() {
    ...

    lblCurrentProgress.stringValue = formatTime(Int(playerPosistion))
    lblTrackLength.stringValue = formatTime(Int(trackLength-playerPosistion))
}

func formatTime(secs: Int) -> String {
    return NSString(format: "%i.%02i", secs / 60, secs % 60) as String
}