web-dev-qa-db-ja.com

カスタム画像付きの活動インジケーター

私はUIWebViewをロードしていますが、当面はこれで空白のページを表示したくありませんspinner 回転する活動インジケーター(siri活動インジケーター)。私が理解していることから、画像を変更することはできませんが、その画像を使用して、360度回転してループするアニメーションを作成することはできませんか?それともバッテリーが消耗しますか?

このようなもの?:

- (void)webViewDidStartLoad:(UIWebView *)webView {
    //set up animation        
    [self.view addSubview:self.loadingImage];
    //start animation
}

- (void)webViewDidFinishLoad:(UIWebView *)webView
{   
    //stop animation
    [self.loadingImage removeFromSuperview];
}

私は何をすべきか?

前もって感謝します!

14
Tibbe

これのほとんどはスタックオーバーフローにあります。要約させてください:

アクティビティインジケーターとして機能するUIImageViewを作成します(ストーリーボードシーン、NIB、コード内など...どこでも)。 _activityIndicatorImageとしましょう

画像を読み込みます:_activityIndicatorImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"activity_indicator"]];

アニメーションを使用して回転させる必要があります。これが私が使う方法です:

+ (void)rotateLayerInfinite:(CALayer *)layer
{
    CABasicAnimation *rotation;
    rotation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
    rotation.fromValue = [NSNumber numberWithFloat:0];
    rotation.toValue = [NSNumber numberWithFloat:(2 * M_PI)];
    rotation.duration = 0.7f; // Speed
    rotation.repeatCount = HUGE_VALF; // Repeat forever. Can be a finite number.
    [layer removeAllAnimations];
    [layer addAnimation:rotation forKey:@"Spin"];
}

LayoutSubviewsメソッド内で、ローテーションを開始します。 webViewDidStartLoadwebViewDidFinishLoadに配置できます。

- (void)layoutSubviews
{
    [super layoutSubviews];

    // some other code 

    [Utils rotateLayerInfinite:_activityIndicatorImage.layer];
}

[_activityIndicatorImage.layer removeAllAnimations];を使用すると、いつでも回転を停止できます

35
demosten

Tumblr appから着想を得た、この美しいローダーを使用できます。
Asich/AMTumblrHud

4
Almas Adilbek

Swift 4 Sweet And Simply Just Extension Extension UIView {}

@ gandhi Menaの修正された回答

独自のカスタム読み込みインジケーターを作成する場合

ブランドロゴをカスタムインジケーターとして作成およびカスタマイズするUIView拡張機能を作成し、このコードをグローバル宣言ファイルに配置します。

extension UIView{
func customActivityIndicator(view: UIView, widthView: CGFloat?,backgroundColor: UIColor?, textColor:UIColor?, message: String?) -> UIView{

    //Config UIView
    self.backgroundColor = backgroundColor //Background color of your view which you want to set

    var selfWidth = view.frame.width
    if widthView != nil{
        selfWidth = widthView ?? selfWidth
    }

    let selfHeigh = view.frame.height
    let loopImages = UIImageView()

    let imageListArray = ["image1", "image2"] // Put your desired array of images in a specific order the way you want to display animation.

    loopImages.animationImages = imageListArray
    loopImages.animationDuration = TimeInterval(0.8)
    loopImages.startAnimating()

    let imageFrameX = (selfWidth / 2) - 30
    let imageFrameY = (selfHeigh / 2) - 60
    var imageWidth = CGFloat(60)
    var imageHeight = CGFloat(60)

    if widthView != nil{
        imageWidth = widthView ?? imageWidth
        imageHeight = widthView ?? imageHeight
    }

    //ConfigureLabel
    let label = UILabel()
    label.textAlignment = .center
    label.textColor = .gray
    label.font = UIFont(name: "SFUIDisplay-Regular", size: 17.0)! // Your Desired UIFont Style and Size
    label.numberOfLines = 0
    label.text = message ?? ""
    label.textColor = textColor ?? UIColor.clear

    //Config frame of label
    let labelFrameX = (selfWidth / 2) - 100
    let labelFrameY = (selfHeigh / 2) - 10
    let labelWidth = CGFloat(200)
    let labelHeight = CGFloat(70)

    // Define UIView frame
    self.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width , height: UIScreen.main.bounds.size.height)


    //ImageFrame
    loopImages.frame = CGRect(x: imageFrameX, y: imageFrameY, width: imageWidth, height: imageHeight)

    //LabelFrame
    label.frame = CGRect(x: labelFrameX, y: labelFrameY, width: labelWidth, height: labelHeight)

    //add loading and label to customView
    self.addSubview(loopImages)
    self.addSubview(label)
    return self }}

このようなインジケーターを非表示にすると、サブビュースタックから一番上のサブビューを削除できます。このコードを同じグローバルに宣言されたSwiftファイルに配置します。

func hideLoader(removeFrom : UIView){
removeFrom.subviews.last?.removeFromSuperview()
}

これで、このコードでマークを撃つことができます。ビューコントローラーにアクティビティインジケーターを表示するには、表示するときにこのコードを挿入します。

 self.view.addSubview(UIView().customActivityIndicator(view: self.view, widthView: nil, backgroundColor:"Desired color", textColor: "Desired color", message: "Loading something"))

アニメーションローダーを非表示にするには、グローバルに定義した上記の関数を使用できます。非表示にしたいViewController.Swiftに、このコード行を挿入します。

hideLoader(removeFrom: self.view)

imageListArrayは次のようになります。

enter image description here

enter image description here

enter image description here

3

Swift 5

完璧に機能する別の答え

ステップ1。

Swift file "CustomLoader.Swift"を作成し、このファイルにこのコードを挿入します

import UIKit
import CoreGraphics
import QuartzCore

class CustomLoader: UIView
{
    //MARK:- NOT ACCESSABLE OUT SIDE

    fileprivate var duration : CFTimeInterval! = 1
    fileprivate var isAnimating :Bool = false
    fileprivate var backgroundView : UIView!

    //MARK:- ACCESS INSTANCE ONLY AND CHANGE ACCORDING TO YOUR NEEDS   *******
    let colors : [UIColor] = [.red,  .blue,  .orange, .purple]
    var defaultColor : UIColor = UIColor.red
    var isUsrInteractionEnable : Bool = false
    var defaultbgColor: UIColor = UIColor.white
    var loaderSize : CGFloat = 80.0
    /// **************** ******************  ////////// **************

    //MARK:- MAKE SHARED INSTANCE
    private static var Instance : CustomLoader!
    static let sharedInstance : CustomLoader = {

        if Instance == nil
        {
            Instance = CustomLoader()
        }

        return Instance
    }()

    //MARK:- DESTROY TO SHARED INSTANCE
    @objc fileprivate func destroyShardInstance()
    {
        CustomLoader.Instance = nil
    }

    //MARK:- SET YOUR LOADER INITIALIZER FRAME ELSE DEFAULT IS CENTER
    func startAnimation()
    {
        let win = UIApplication.shared.keyWindow

        backgroundView = UIView()
        backgroundView.frame = (UIApplication.shared.keyWindow?.frame)!
        backgroundView.backgroundColor = UIColor.init(white: 0, alpha: 0.4)
        win?.addSubview(backgroundView)

        self.frame = CGRect.init(x: ((UIScreen.main.bounds.width) - loaderSize)/2, y: ((UIScreen.main.bounds.height) - loaderSize)/2, width: loaderSize, height: loaderSize)

        self.addCenterImage()
        self.isHidden = false
        self.backgroundView.addSubview(self)

        self.layer.cornerRadius = loaderSize/2
        self.layer.masksToBounds = true
        backgroundView.accessibilityIdentifier = "CustomLoader"

        NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NSExtensionHostDidBecomeActive, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(CustomLoader.ResumeLoader), name: NSNotification.Name.NSExtensionHostDidBecomeActive, object: nil)

        self.layoutSubviews()
    }

    //MARK:- AVOID STUCKING LOADER WHEN CAME BACK FROM BACKGROUND
    @objc fileprivate func ResumeLoader()
    {
        if isAnimating
        {
            self.stopAnimation()
            self.AnimationStart()
        }
    }

    override func layoutSubviews()
    {
        super.layoutSubviews()

        self.backgroundColor = defaultbgColor
        UIApplication.shared.keyWindow?.isUserInteractionEnabled = isUsrInteractionEnable
        self.AnimationStart()
    }

    @objc fileprivate func addCenterImage()
    {
        /// add image in center
        let centerImage = UIImage(named: "Logo")
        let imageSize = loaderSize/2.5

        let centerImgView = UIImageView(image: centerImage)
        centerImgView.frame = CGRect(
            x: (self.bounds.width - imageSize) / 2 ,
            y: (self.bounds.height - imageSize) / 2,
            width: imageSize,
            height: imageSize
        )

        centerImgView.contentMode = .scaleAspectFit
        centerImgView.layer.cornerRadius = imageSize/2
        centerImgView.clipsToBounds = true
        self.addSubview(centerImgView)

    }


    //MARK:- CALL IT TO START THE LOADER , AFTER INITIALIZE THE LOADER
    @objc fileprivate func AnimationStart()
    {
        if isAnimating
        {
            return
        }

        let size = CGSize.init(width: loaderSize , height: loaderSize)

        let dotNum: CGFloat = 10
        let diameter: CGFloat = size.width / 5.5   //10

        let dot = CALayer()
        let frame = CGRect(
            x: (layer.bounds.width - diameter) / 2 + diameter * 2,
            y: (layer.bounds.height - diameter) / 2,
            width: diameter/1.3,
            height: diameter/1.3
        )

        dot.backgroundColor = colors[0].cgColor
        dot.cornerRadius = frame.width / 2
        dot.frame = frame

        let replicatorLayer = CAReplicatorLayer()
        replicatorLayer.frame = layer.bounds
        replicatorLayer.instanceCount = Int(dotNum)
        replicatorLayer.instanceDelay = 0.1

        let angle = (2.0 * M_PI) / Double(replicatorLayer.instanceCount)

        replicatorLayer.instanceTransform = CATransform3DMakeRotation(CGFloat(angle), 0.0, 0.0, 1.0)

        layer.addSublayer(replicatorLayer)
        replicatorLayer.addSublayer(dot)

        let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
        scaleAnimation.toValue = 0.4
        scaleAnimation.duration = 0.5
        scaleAnimation.autoreverses = true
        scaleAnimation.repeatCount = .infinity
        scaleAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        dot.add(scaleAnimation, forKey: "scaleAnimation")

        let rotationAnimation = CABasicAnimation(keyPath: "transform.rotation")
        rotationAnimation.toValue = -2.0 * Double.pi
        rotationAnimation.duration = 6.0
        rotationAnimation.repeatCount = .infinity
        rotationAnimation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear)
        replicatorLayer.add(rotationAnimation, forKey: "rotationAnimation")

        if colors.count > 1 {

            var cgColors : [CGColor] = []
            for color in colors {
                cgColors.append(color.cgColor)
            }

            let colorAnimation = CAKeyframeAnimation(keyPath: "backgroundColor")
            colorAnimation.values = cgColors
            colorAnimation.duration = 2
            colorAnimation.repeatCount = .infinity
            colorAnimation.autoreverses = true
            dot.add(colorAnimation, forKey: "colorAnimation")

        }

        self.isAnimating = true
        self.isHidden = false

    }


    //MARK:- CALL IT TO STOP THE LOADER
    func stopAnimation()
    {
        if !isAnimating
        {
            return
        }
        UIApplication.shared.keyWindow?.isUserInteractionEnabled = true
        let winSubviews = UIApplication.shared.keyWindow?.subviews
        if (winSubviews?.count)! > 0
        {
            for viw in winSubviews!
            {
                if viw.accessibilityIdentifier == "CustomLoader"
                {
                    viw.removeFromSuperview()
                    //  break
                }
            }
        }

        layer.sublayers = nil

        isAnimating = false
        self.isHidden = true

        self.destroyShardInstance()
    }
    //MARK:- GETTING RANDOM COLOR , AND MANAGE YOUR OWN COLORS
    @objc fileprivate func randomColor()->UIColor
    {
        let randomRed:CGFloat = CGFloat(drand48())
        let randomGreen:CGFloat = CGFloat(drand48())
        let randomBlue:CGFloat = CGFloat(drand48())
        return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
    }
    override func draw(_ rect: CGRect)
    {
    }
}

func名と "addCenterImage"を見つけて、イメージ名をカスタムイメージに置き換えます。

ステップ2

このようにAppDelegateクラスの外側にAppDelegateクラスインスタンスを作成します。

var AppInstance: AppDelegate!
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate
{    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool
{
    AppInstance = self
}

ステップ3。

これら2つの関数をAppDelegateに配置します

//MARK: - Activity Indicator -
    func showLoader()
    {
        CustomLoader.sharedInstance.startAnimation()
    }
    func hideLoader()
    {
        CustomLoader.sharedInstance.stopAnimation()
    }

ステップ4.ローダーをアニメーション化して停止したいときはいつでも、このような関数を使用してください。

AppInstance.showLoader()
AppInstance.hideLoader()

HAPPY LOADING ...

1

最近、同様の問題に直面しています。そして、これが私の解決策です。基本的に、それはトピックスターターが最初に欲しかったものです:カスタムアクティビティインジケーターが付いた空白のページ。
@ Azharhussain Shaikhの回答を一部使用しましたが、フレームを使用する代わりに自動レイアウトを実装し、使用をできるだけ簡単にするために他のいくつかの改良を追加しました。

したがって、これは2つのメソッドaddActivityIndi​​cator()およびremoveActivityIndi​​cator()を持つUIViewの拡張機能です。

extension UIView {

func addActivityIndicator() {
    //    creating a view (let's call it "loading" view) which will be added on top of the view you want to have activity indicator on (parent view)
    let view = UIView()
    //    setting up a background for a view so it would make content under it look like not active
    view.backgroundColor = UIColor.white.withAlphaComponent(0.7)

    //    adding "loading" view to a parent view
    //    setting up auto-layout anchors so it would cover whole parent view
    self.addSubview(view)
    view.translatesAutoresizingMaskIntoConstraints = false
    view.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
    view.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
    view.leftAnchor.constraint(equalTo: self.leftAnchor).isActive = true
    view.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true

    //    creating array with images, which will be animated
    //    in my case I have 30 images with names activity0.png ... activity29.png
    var imagesArray = [UIImage(named: "activity\(0)")!]
    for i in 1..<30 {
        imagesArray.append(UIImage(named: "activity\(i)")!)
    }

    //    creating UIImageView with array of images
    //    setting up animation duration and starting animation
    let activityImage = UIImageView()
    activityImage.animationImages = imagesArray
    activityImage.animationDuration = TimeInterval(0.7)
    activityImage.startAnimating()

    //    adding UIImageView on "loading" view
    //    setting up auto-layout anchors so it would be in center of "loading" view with 30x30 size
    view.addSubview(activityImage)
    activityImage.translatesAutoresizingMaskIntoConstraints = false
    activityImage.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    activityImage.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    activityImage.widthAnchor.constraint(equalToConstant: 30).isActive = true
    activityImage.heightAnchor.constraint(equalToConstant: 30).isActive = true
}

func removeActivityIndicator() {
    //    checking if a view has subviews on it
    guard let lastSubView = self.subviews.last else { return }
    //    removing last subview with an assumption that last view is a "loading" view
    lastSubView.removeFromSuperview()
} }

「回転」効果は、imagesArrayに配置した30個の画像によって実現されます。各画像は回転インジケーターの新しいフレーム (like this )です。

使用法。アクティビティインジケーターを表示するためのビューコントローラーには、次のように記述します

    view.addActivityIndicator()

アクティビティインジケーターを削除するには:

    view.removeActivityIndicator()

たとえば、(私と同じように)テーブルビューで使用する場合は、次のように使用できます。

func setLoadingScreen() {
    view.addActivityIndicator()
    tableView.isScrollEnabled = false
}

func removeLoadingScreen() {
    view.removeActivityIndicator()
    tableView.isScrollEnabled = true
}

Swift 4。

1
Alex D

Imageがなくても、サードパーティのライブラリを使用できます

objective C(iOS 6でもサポート) https://github.com/shebinkoshy/UIControllsRepo

Swift https://github.com/shebinkoshy/Activity-Indicator-Swift の場合

利点

->スピナーの色を設定できる

->小型、小型、中型、大型、超大型などのさまざまなサイズで利用可能

->中、大、超大サイズのタイトル(中央と下部)を設定できる

1
Shebin Koshy

imagesactivityIndicatorに設定できます。 カスタム画像を追加の関数をactivityIndi​​catorに作成しました。これが私が作成したものです。

public func showProgressView(view: UIView) -> UIImageView {
    let containerView = UIView()
    let progressView = UIView()
    var activityIndicatorImageView = UIImageView()

    if let statusImage = UIImage(named: Constants.ActivityIndicatorImageName1) {
        let activityImageView = UIImageView(image: statusImage)
        containerView.frame = view.frame
        containerView.backgroundColor = UIColor(hex: 0xffffff, alpha: 0.3)
        progressView.frame = CGRectMake(0, 0, 80, 80)
        progressView.center = CGPointMake(view.bounds.width / 2, view.bounds.height / 2)
        progressView.backgroundColor = UIColor(hex: 0x18bda3, alpha: 0.7)
        progressView.clipsToBounds = true
        progressView.layer.cornerRadius = 10
        activityImageView.animationImages = [UIImage(named: Constants.ActivityIndicatorImageName1)!,
            UIImage(named: Constants.ActivityIndicatorImageName2)!,
            UIImage(named: Constants.ActivityIndicatorImageName3)!,
            UIImage(named: Constants.ActivityIndicatorImageName4)!,
            UIImage(named: Constants.ActivityIndicatorImageName5)!]
        activityImageView.animationDuration = 0.8;
        activityImageView.frame = CGRectMake(view.frame.size.width / 2 - statusImage.size.width / 2, view.frame.size.height / 2 - statusImage.size.height / 2, 40.0, 48.0)
        activityImageView.center = CGPointMake(progressView.bounds.width / 2, progressView.bounds.height / 2)
        dispatch_async(dispatch_get_main_queue()) {
            progressView.addSubview(activityImageView)
            containerView.addSubview(progressView)
            view.addSubview(containerView)
            activityIndicatorImageView = activityImageView
        }
    }
    return activityIndicatorImageView
}

このメソッドは、コードのどこにでも呼び出すことができます。そして、startAnimatingメソッドを呼び出すだけです。非表示にする場合は、stopAnimatingメソッドを呼び出します。

0
emresancaktar

Swift 3&4で、これを使用してカスタムアクティビティインジケーターを作成できます。

名前がUIViewExtension.Swiftの新しいファイルを作成し、このコードをコピーして、新しいファイルファイルに貼り付けます。

import UIkit

extension UIView{
   func customActivityIndicator(view: UIView, widthView: CGFloat? = nil,backgroundColor: UIColor? = nil, message: String? = nil,colorMessage:UIColor? = nil ) -> UIView{

    //Config UIView
    self.backgroundColor = backgroundColor ?? UIColor.clear
    self.layer.cornerRadius = 10


    var selfWidth = view.frame.width - 100
    if widthView != nil{
        selfWidth = widthView ?? selfWidth
    }

    let selfHeigh = CGFloat(100)
    let selfFrameX = (view.frame.width / 2) - (selfWidth / 2)
    let selfFrameY = (view.frame.height / 2) - (selfHeigh / 2)
    let loopImages = UIImageView()

    //ConfigCustomLoading with secuence images
    let imageListArray = [UIImage(named:""),UIImage(named:""), UIImage(named:"")]
    loopImages.animationImages = imageListArray
    loopImages.animationDuration = TimeInterval(1.3)
    loopImages.startAnimating()
    let imageFrameX = (selfWidth / 2) - 17
    let imageFrameY = (selfHeigh / 2) - 35
    var imageWidth = CGFloat(35)
    var imageHeight = CGFloat(35)

    if widthView != nil{
        imageWidth = widthView ?? imageWidth
        imageHeight = widthView ?? imageHeight
    }

    //ConfigureLabel
    let label = UILabel()
    label.textAlignment = .center
    label.textColor = .gray
    label.font = UIFont.boldSystemFont(ofSize: 17)
    label.numberOfLines = 0
    label.text = message ?? ""
    label.textColor = colorMessage ?? UIColor.clear

    //Config frame of label
    let labelFrameX = (selfWidth / 2) - 100
    let labelFrameY = (selfHeigh / 2) - 10
    let labelWidth = CGFloat(200)
    let labelHeight = CGFloat(70)

    //add loading and label to customView
    self.addSubview(loopImages)
    self.addSubview(label)

    //Define frames
    //UIViewFrame
    self.frame = CGRect(x: selfFrameX, y: selfFrameY, width: selfWidth , height: selfHeigh)

    //ImageFrame
    loopImages.frame = CGRect(x: imageFrameX, y: imageFrameY, width: imageWidth, height: imageHeight)

    //LabelFrame
    label.frame = CGRect(x: labelFrameX, y: labelFrameY, width: labelWidth, height: labelHeight)

    return self

}

}

そして、次のようにViewControllerで使用できます。

import UIKit


class ExampleViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        self.view.addSubview(UIView().customActivityIndicator(view: self.view,backgroundColor: UIColor.green))

    }

   //function for stop and desappear loading
   func deseappearLoading(){
      self.view.subviews.last?.removeFromSuperview()
   }
}

[UIImage(named: "")、UIImage(named: "")、UIImage(named: "")]を画像の名前に置き換えて、TimeInterval(1.3)を調整することを忘れないでください。楽しめ。

0
gandhi Mena

SWIFT 3と4の両方で機能します

var activityIndicator = UIActivityIndicatorView()
var myView : UIView = UIView()

func viewDidLoad() {
    spinnerCreation()
}

func spinnerCreation() {

    activityIndicator.activityIndicatorViewStyle =  .whiteLarge

    let label = UILabel.init(frame: CGRect(x: 5, y: 60, width: 90, height: 20))
    label.textColor = UIColor.white
    label.font = UIFont.boldSystemFont(ofSize: 14.0)
    label.textAlignment = NSTextAlignment.center
    label.text = "Please wait...."

    myView.frame = CGRect(x: (UIScreen.main.bounds.size.width - 100)/2, y: (UIScreen.main.bounds.size.height - 100)/2, width: 100, height: 100)

    myView.backgroundColor = UIColor.init(white: 0.0, alpha: 0.7)
    myView.layer.cornerRadius = 5
    activityIndicator.center = CGPoint(x: myView.frame.size.width/2, y:  myView.frame.size.height/2 - 10)
    myView.addSubview(activityIndicator)
    myView.addSubview(label)

    myView.isHidden = true
    self.window?.addSubview(myView)
}

@IBAction func activityIndicatorStart(_ sender: Any) {
    myView.isHidden = false
    self.activityIndicator.startAnimating()
    self.view.isUserInteractionEnabled = false
    self.view.bringSubview(toFront: myView)
}

@IBAction func activityIndicatorStop(_ sender: Any)() {
    myView.isHidden = true
    self.activityIndicator.stopAnimating()
    self.view.isUserInteractionEnabled = true
}
0
Sai kumar Reddy

承認済み回答のSwift 5.0バージョン

public extension UIImageView {
  func spin(duration: Float) {
    let rotation = CABasicAnimation(keyPath: "transform.rotation")
    rotation.fromValue = 0
    rotation.toValue = 2 * Double.pi
    rotation.duration = 0.7
    rotation.repeatCount = duration
    layer.add(rotation, forKey: "spin")
  }

  func stopSpinning() {
    layer.removeAllAnimations()
  }
}
0
Mocha