簡體   English   中英

NSTimer()可以不停地運行嗎? (Xcode v 7.0.1,Swift 2.0)

[英]Can NSTimer() run non-stop? (Xcode v 7.0.1, Swift 2.0)

我正在構建一個iOS應用,該應用使用Google Maps SDK在地圖上顯示我學校的校園班車的位置。 我通過解析每10秒刷新一次的XML文件來了解航天飛機的位置。

我正在使用NSTimer()每10秒運行一次viewDidLoad(),以便在地圖上更新公交車的位置。

我遇到的問題是在運行6或7次viewDidLoad()之后,代碼崩潰了。 這很糟糕,因為我需要我的代碼連續刷新才能更新公交車的位置。

我是否正確使用NSTimer()? NSTimer()是否可以連續運行,或者NSTime()可以運行多長時間有限制?

以下是我的代碼:

import UIKit
import GoogleMaps

class ViewController: UIViewController, NSXMLParserDelegate {

    var parser = NSXMLParser()
    var timer  = NSTimer()

    // viewDidLoad()
    override func viewDidLoad() {
        super.viewDidLoad()

        // runs viewDidLoad() every 10 seconds
        timer = NSTimer.scheduledTimerWithTimeInterval(10.0, target: self, selector: "viewDidLoad", userInfo: nil, repeats: true)

        // XML file
        parser = NSXMLParser(contentsOfURL:(NSURL(string:"http://link.to.xml.file.xml"))!)!

        let coord = Coord2()
        parser.delegate = coord
        parser.parse()
        print("coord has a count attribute of \(coord.count)")
        print("coord has \(coord.markers.count) markers")

        // displays the map adjusted to UC Santa Cruz
        let camera = GMSCameraPosition.cameraWithLatitude(37.0000,
        longitude: -122.0600, zoom: 14)
        let mapView = GMSMapView.mapWithFrame(CGRectZero, camera: camera)
        mapView.mapType = kGMSTypeNormal
        mapView.myLocationEnabled = true
        self.view = mapView

        // loops through all the lats and lngs of the buses and produces a marker
        // for them on our Google Maps app
        for marker in coord.markers {
            print("marker id=\(marker.id), lat=\(marker.lati), lng=\(marker.lngi), route=\(marker.route)")

            // displays the buses
            let buses = GMSMarker()
            buses.position = CLLocationCoordinate2DMake(marker.lati, marker.lngi)
            buses.title = marker.route
            if buses.title == "UPPER CAMPUS" {
                buses.icon = UIImage(named: "uppercampus")
            } else if buses.title == "LOOP" {
                buses.icon = UIImage(named: "innerloop")
            }
            buses.snippet = marker.id
            buses.map = mapView
        }
    }

    // didReceiveMemoryWarning()
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

// ParseBase class
// simple base class that is used to consume foundCharacters
// via the parser
class ParserBase : NSObject, NSXMLParserDelegate  {

    var currentElement:String = ""
    var foundCharacters = ""
    weak var parent:ParserBase? = nil

    func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {
        currentElement = elementName
    }

    func parser(parser: NSXMLParser, foundCharacters string: String) {
        self.foundCharacters = string
    }

}

// Coord2 class
// represents a coord2 tag
// it has a count attribute
// and a collection of markers
class Coord2 : ParserBase {

    var count = 0
    var markers = [Marker]()

    // didStartElement()
    override func parser(parser: NSXMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String]) {

        print("processing <\(elementName)> tag from Coord")

        if elementName == "coord2" {

            // if we are processing a coord2 tag, we are at the root
            // of XML file, extract the count value and set it
            print(attributeDict["count"])
            if let c = Int(attributeDict["count"]!) {
                self.count = c
            }
        }

        // if we found a marker tag, delegate further responsibility
        // to parsing to a new instance of Marker
        if elementName == "marker" {
            let marker = Marker()
            self.markers.append(marker)

            // push responsibility
            parser.delegate = marker

            // let marker know who we are
            // so that once marker is done XML processing
            // it can return parsing responsibility back
            marker.parent = self
        }
    }
}

// Marker class
class Marker : ParserBase {

    var id = ""
    var lat = ""
    var lng = ""
    var route = ""
    var lati = 0.0
    var lngi = 0.0

    // didEndElement()
    func parser(parser: NSXMLParser, didEndElement elementName: String, namespaceURI: String?, qualifiedName qName: String?) {

        print("processing <\(elementName)> tag from Marker")

        // if we finished an item tag, the ParserBase parent
        // would have accumulated the found characters
        // so just assign that to our item variable
        if elementName == "id" {
            self.id = foundCharacters
        }

        // convert the lat to a Double
        else if elementName == "lat" {
            self.lat = foundCharacters
            // cast self.lat as Double
            if let doubleFromlat = Double(self.lat) {
                self.lati = doubleFromlat
            } else { print("foundCharacters for lat does not hold double") }

        }

        // convert the lng to a Double
        else if elementName == "lng" {
            self.lng = foundCharacters
            if let doubleFromlng = Double(self.lng) {
                self.lngi = doubleFromlng
            } else { print("foundCharacters for lng does not hold double") }
        }

        else if elementName == "route" {
            self.route = foundCharacters
        }

        // if we reached the </marker> tag, we do not
        // have anything further to do, so delegate
        // parsing responsibility to parent
        else if elementName == "marker" {
            parser.delegate = self.parent
        }

        // reset found characters
        foundCharacters = ""
    }

}

每次都調用viewDidLoad方法是一個壞主意。

當視圖控制器第一次加載到內存中時,viewDidLoad會被調用一次。 在這里您要實例化任何實例變量並構建在該視圖控制器的整個生命周期中都有效的所有視圖。 但是,此刻該視圖通常不可見。

無需每次都創建另一個方法並將所需的代碼添加到要每10秒運行一次的方法,而不是每次調用viewDidLoad方法,如下所示:

timer = NSTimer.scheduledTimerWithTimeInterval(10.0, target: self, selector: "yourNewMethod", userInfo: nil, repeats: true)

如上所示更新您的timer

下面是輔助方法。

func yourNewMethod() {
    //add your code here which you want to run
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM