2016-05-04 4 views
0

У меня есть некоторые проблемы с моей версией этого однопользовательского режима loadOverlay.остановка асинхронного вызова, когда она вышла в диком состоянии в быстром

Что должно произойти, оно появляется на экране, с видом и этикеткой с текстом «Загрузка, пожалуйста, подождите». или что-то типа того. то, если загрузка длится более 2 секунд (я изменил ее на 10 для отладки), текст меняется на случайную симпатичную фразу.

Прежде всего анимация, которая должна изменить текст, кажется, не происходит. вместо этого текст сразу меняется.

Более важно, если по какой-то причине мой асинхронный блок вызовов выполняется несколько раз, мне нужен только самый последний вызов для его запуска, и я хочу, чтобы предыдущие экземпляры его завершились до запуска.

Я читал о обратных вызовах и обещаниях, которые выглядят многообещающими. Это быстрый выбор?

Кстати, поскольку я изучаю swift и iOS, я экспериментировал, и я пробовал [unowned self], и теперь я экспериментирую с [слабым я], но я не уверен, что это самое подходящее Вот.

// from http://stackoverflow.com/questions/33064908/adding-removing-a-view-overlay-in-swift/33064946#33064946 

import UIKit 

class LoadingOverlay{ 
    static let sharedInstance = LoadingOverlay() 

    //above swifty singleton syntax from http://krakendev.io/blog/the-right-way-to-write-a-singleton 

    var overlayView = UIView() 

    var spring: CASpringAnimation! 
    var springAway: CASpringAnimation! 

    var hidden = false 

    private init() {} //This line prevents others from using the default() initializer for this class 

    func setupSpringAnimation(startY: CGFloat, finishY: CGFloat) { 
     overlayView.layer.position.y = startY 
     spring = CASpringAnimation(keyPath: "position.y") 
     spring.damping = 10 
     spring.fromValue = startY 
     spring.toValue = finishY 
     spring.duration = 1.0 
     spring.fillMode = kCAFillModeBackwards 


    } 

    func showOverlay() { 
     print("show overlay") 
     overlayView.alpha = 1 
     hidden = false 
     if let appDelegate = UIApplication.sharedApplication().delegate as? AppDelegate, 
      let window = appDelegate.window { 

      setupSpringAnimation(-window.frame.height/2, finishY: window.frame.height/2) 
      let overlayViewFramesize = 0.65 * min(window.frame.height, window.frame.width) 
      overlayView.frame = CGRectMake(0, 0, overlayViewFramesize, overlayViewFramesize) 
      overlayView.center = window.center 
      overlayView.backgroundColor = UIColor.greenColor() 
      overlayView.clipsToBounds = true 
      overlayView.layer.cornerRadius = overlayViewFramesize/8 

      let label = UILabel(frame: CGRectMake(0,0,overlayViewFramesize * 0.8 , overlayViewFramesize)) 
      label.text = " \nLoading, please wait\n " 
      label.tag = 12 
      overlayView.addSubview(label) 
      label.lineBreakMode = NSLineBreakMode.ByWordWrapping 
      label.numberOfLines = 0 //as many as needed 


      label.sizeToFit() 
      label.textAlignment = NSTextAlignment.Center 

      label.center = CGPointMake(overlayViewFramesize/2, overlayViewFramesize/2) 
      overlayView.bringSubviewToFront(label) 
      window.addSubview(overlayView) 

      overlayView.layer.addAnimation(spring, forKey: nil) 
      RunAfterDelay(10.0) { 
       if self.hidden == true { return } 

       //strongSelf boilerplate code technique from https://www.raywenderlich.com/133102/swift-style-guide-april-2016-update?utm_source=raywenderlich.com+Weekly&utm_campaign=ea47726fdd-raywenderlich_com_Weekly4_26_2016&utm_medium=email&utm_term=0_83b6edc87f-ea47726fdd-415681129 

       UIView.animateWithDuration(2, delay: 0, options: [UIViewAnimationOptions.CurveEaseInOut, UIViewAnimationOptions.BeginFromCurrentState, UIViewAnimationOptions.TransitionCrossDissolve], animations: { [weak self] in 
        guard let strongSelf = self else { return } 
        (strongSelf.overlayView.viewWithTag(12) as! UILabel).text = randomPhrase() 
        (strongSelf.overlayView.viewWithTag(12) as! UILabel).sizeToFit() 
        print ((strongSelf.overlayView.viewWithTag(12) as! UILabel).bounds.width) 
        (strongSelf.overlayView.viewWithTag(12) as! UILabel).center = CGPointMake(overlayViewFramesize/2, overlayViewFramesize/2) 

        }, completion: { (finished: Bool)in 
         print ("animation to change label occured")}) 

      } 




     } 
    } 
    func hideOverlayView() { 
     hidden = true 
     UIView.animateWithDuration(1.0, delay: 0.0, options: [UIViewAnimationOptions.BeginFromCurrentState], animations: { [unowned self] in 
//I know this is clunky... what's the right way? 
      (self.overlayView.viewWithTag(12) as! UILabel).text = "" 
      self.overlayView.alpha = 0 
     }) { [unowned self] _ in 
//I know this is clunky. what's the right way?     
      for view in self.overlayView.subviews { 
       view.removeFromSuperview() 
      } 

      self.overlayView.removeFromSuperview() 

      print("overlayView after removing:", self.overlayView.description) 

     } 

     //here i have to deinitialize stuff to prepare for the next use 


    } 

    deinit { 
     print("Loading Overlay deinit") 
    } 


} 

ответ

0

Что я в принципе хотел, заключалось в том, чтобы задержать блок кода и, возможно, отменить его до его выполнения. Я нашел ответ здесь:

GCD and Delayed Invoking