2017-05-03 15 views
5

काम नहीं करता है मेरे पास मेरे स्विफ्ट ऐप में दो दृश्य हैं। मैं नीचे के रूप में एक segue प्रदर्शन कर रहा हूँ।स्विफ्ट टाइमर.scheduledTimer()

ViewController.swift -----------------> GameViewController.swift

जब GameViewController एक मान सरणी भी ViewController.swift

से GameViewController.swift के लिए पारित लोड हो रहा है

एक टाइमर GameViewController.swift

में प्रारंभ किया जाना चाहिए मैं एक टाइमर प्रारंभ और यह माध्यम से एक विधि कॉल करने की कोशिश की, लेकिन यह काम नहीं करता।

अनुवर्ती मेरे कोड स्निपेट हैं।

ViewController.swift

func signIn(difficultyLvl:String){ 
    let username = usernameTxt.text 
    let password = passwordTxt.text 

    let url = URL(string: "http://192.168.1.106/speed/scoreBoardController.php?username="+username!+"&password="+password!+"&action=SIGNIN") 

    let task = URLSession.shared.dataTask(with: url!) {(data, response, error) in 
     let isPassed = String(data: data!, encoding:.utf8)?.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) 

     var gameViewControllerParams = [Int: [String: String]]() 
     gameViewControllerParams[0] = ["userId" : isPassed!] 
     gameViewControllerParams[1] = ["difficultyLvl" : difficultyLvl] 

     if(isPassed != "null"){ 
      self.performSegue(withIdentifier: "gotoGame", sender: gameViewControllerParams) 
     } 
    } 

    task.resume() 
} 

GameViewController.swift

class GameViewController: UIViewController { 

    var gameViewControllerParams = [Int: [String: String]]() 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     let _ = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(self.setCalculationLs), userInfo:nil,repeats: true) 
    } 

    func setCalculationLs(){ 
     print("Timing") 
    } 

} 
+0

मुझे लगता है कि यह टाइमर में लक्षित ऑब्जेक्ट को सेट करने में एक समस्या है। कोई शर्करा धन्यवाद –

+0

आप 'GameViewController' को सरणी नहीं भेज रहे हैं, इसे 'तैयार करें (प्रेषक:)' में करें। 'प्रेषक' पैरामीटर 'self' – paper1111

+0

होना चाहिए समस्या वास्तव में क्या है? GameViewController लोड किया गया है? क्या ViewDidLoad() कहा जाता है? टाइमर समस्या से संबंधित सरणी कैसे गुजर रही है? - आम तौर पर, आप टाइमर कोड काम करना चाहिए। –

उत्तर

10

टाइमर हाथ से कुछ सफ़ाई रन छोरों बनाने से जुड़े या मैन्युअल रूप से एक मौजूदा चलाने पर यह समय निर्धारण के बिना पृष्ठभूमि कतारों (पर काम नहीं करते पाश)। लेकिन आपको मुख्य कतार के अलावा किसी भी अन्य यूआई अपडेट को कभी भी शुरू नहीं करना चाहिए, वैसे भी।

तो, जब से तुम एक URLSession पूरा होने के बंद होने से performSegue कॉल कर रहे हैं (जो एक पृष्ठभूमि कतार पर चलता है), यह वास्तव में पृष्ठभूमि कतार से viewDidLoad भी चल रहा है। इस प्रकार टाइमर शेड्यूल करने का प्रयास असफल रहा है। इस के आसपास पाने के लिए आपको मैन्युअल रूप से मुख्य कतार में performSegue कोड प्रेषण करने के लिए है:

let task = URLSession.shared.dataTask(with: url!) { data, response, error in 
    ... 

    if isPassed != "null" { 
     DispatchQueue.main.async { 
      self.performSegue(withIdentifier: "gotoGame", sender: ...) 
     } 
    } 
} 

क्या तुमने कभी सुनिश्चित नहीं हैं, कुछ कोड या नहीं मुख्य कतार पर चल रहा है कि क्या करते हैं, तो the documentation को देखें।

dispatchPrecondition(condition: .onQueue(.main)) 

इस तरह यह (में डिबग बनाता है) एप्लिकेशन को अगर आप गलती से एक पृष्ठभूमि कतार से कोड लागू किया है बंद हो जाएगा: या आप एक प्रेषण पूर्व शर्त का उपयोग कर सकते हैं।


अपने वर्तमान समस्या से संबंधित नहीं है, लेकिन एक अलग रूप में के रूप में, टाइमर और दृश्य नियंत्रक के बीच एक मजबूत संदर्भ चक्र से बचने के लिए, आप आम तौर पर टाइमर के लिए एक संदर्भ रखने के लिए इतना है कि आप इसे जब invalidate कर सकते हैं देखें गायब हो जाता है (उदाहरण के लिए viewDidAppear में टाइमर बनाएं और इसे viewDidDisappear में हटा दें)। नहीं तो आप GameViewController को बनाए रखना खत्म कर सकते हैं के बाद यह बर्खास्त कर दिया गया, जैसे:

class GameViewController: UIViewController { 

    var timer: Timer? 

    override func viewDidAppear(_ animated: Bool) { 
     super.viewDidAppear(animated) 

     timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(setCalculationLs), userInfo: nil, repeats: true) 
    } 

    override func viewDidDisappear(_ animated: Bool) { 
     super.viewDidDisappear(animated) 

     timer?.invalidate() 
    } 

    func setCalculationLs() { 
     print("Tick") 
    } 
} 

या आईओएस 10 में, आप self करने के लिए weak संदर्भ के साथ ब्लॉक आधारित प्रकार का उपयोग कर सकते हैं और invalidatedeinit में:

class GameViewController: UIViewController { 

    var timer: Timer? 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { [weak self] timer in 
      self?.setCalculationLs() 
     } 
    } 

    deinit { 
     timer?.invalidate() 
    } 

    func setCalculationLs() { 
     print("Tick") 
    } 

} 
+0

ओह! इसने काम कर दिया। आपके तरह के समर्थन के लिए बहुत बहुत धन्यवाद। यह मेरे जैसे नए त्वरित शिक्षार्थियों के लिए बहुत उपयोगी होगा। और मैं मुख्य कतार के अलावा किसी अन्य चीज़ से यूआई अपडेट शुरू करने के लिए नहीं, बल्कि अपने एप्लिकेशन तर्क को बदलने की कोशिश करूंगा। धन्यवाद फिर से –

+0

रोब, क्या आप [कमजोर स्वयं] विधि पसंद करते हैं या देखते हैंडलोड/देखेंडिडडिस्पर विधि? धन्यवाद। –

+0

मैं '[कमजोर स्वयं] 'पैटर्न पसंद करता हूं, लेकिन कभी-कभी आपको पुरानी एपीआई का उपयोग करना पड़ता है क्योंकि आप पुराने आईओएस संस्करणों का समर्थन कर रहे हैं। और यदि आप उस पुराने एपीआई के साथ फंस गए हैं, तकनीकी रूप से, जबकि मेरा उदाहरण 'viewDidLoad'/'viewDidDisappear' था, तो शायद मैं' viewDidAppear' और 'viewDidDisappear' का सुझाव दूंगा (क्योंकि वे हमेशा संतुलित रहेंगे, जबकि 'viewDidLoad' शायद नहीं 'viewDidDisappear 'कॉल के साथ संतुलित रहें, विशेष रूप से यदि आप वैकल्पिक रूप से एक और दृश्य नियंत्रक प्रस्तुत करते हैं)। मैंने केवल उपरोक्त 'viewDidLoad' का उपयोग किया क्योंकि वह वहीं है जहां ओपी मूल प्रश्न में अपना टाइमर बना रहा था। – Rob