ActivityIndi​​cator(微调器)出现错误在展开可选值时意外发现 nil

Posted

技术标签:

【中文标题】ActivityIndi​​cator(微调器)出现错误在展开可选值时意外发现 nil【英文标题】:ActivityIndicator (spinner) getting error Unexpectedly found nil while unwrapping an Optional value 【发布时间】:2019-03-30 05:19:36 【问题描述】:

在我的共享课程中,我编写了微调器代码,它工作正常,但有时会出错。

Error: Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

我在共享类中的代码:

import UIKit

class SharedClass: NSObject 

static let sharedInstance = SharedClass()

var transparentView:UIView!
var spinner = UIActivityIndicatorView()


//Show activity indicator
func activityIndicator(view:UIView) 

    DispatchQueue.main.async 
        let window = UIApplication.shared.keyWindow! //Error : Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
        self.transparentView = UIView()
        self.transparentView.frame = CGRect(x: 0, y: 0, width: window.frame.width, height: window.frame.height)
        self.transparentView.backgroundColor = UIColor.black.withAlphaComponent(0.4)
        window.addSubview(self.transparentView)

        if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad 
            self.spinner = UIActivityIndicatorView(style: .whiteLarge)
            self.spinner.frame = CGRect(x: 0, y: 0, width: 60, height: 60)
         else 
            self.spinner = UIActivityIndicatorView(style: .white)
            self.spinner.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
        
        self.spinner.center = view.center
        self.transparentView.addSubview(self.spinner)
        self.spinner.startAnimating()

        DispatchQueue.main.asyncAfter(deadline: .now() + 600.0) //Stop spinner after 10 Sec's
            self.stopActivityIndicator()
            //self.transparentView.removeFromSuperview()
        
    


//Stop activity indicator
func stopActivityIndicator() 
    DispatchQueue.main.async 
        self.spinner.stopAnimating()
        self.spinner.removeFromSuperview()
        self.transparentView.removeFromSuperview()
    


//Present alert on top of all windows
func alertWindow(title: String, message: String) 
    //Calling
    //SharedClass.sharedInstance.alertWindow(title:"", message:"")
    DispatchQueue.main.async(execute: 
        let alertWindow = UIWindow(frame: UIScreen.main.bounds)
        alertWindow.rootViewController = UIViewController()
        alertWindow.windowLevel = UIWindow.Level.alert + 1

        let alert2 = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let defaultAction2 = UIAlertAction(title: "OK", style: .default, handler:  action in
        )
        alert2.addAction(defaultAction2)

        alertWindow.makeKeyAndVisible()

        alertWindow.rootViewController?.present(alert2, animated: true, completion: nil)
    )



 private override init() 




我是这样打电话的

SharedClass.sharedInstance.activityIndi​​cator(view: self.view)//播放微调器

SharedClass.sharedInstance.stopActivityIndi​​cator() //停止微调器

这是我的登录 Btn 代码

@IBAction func onClickLoginBtn(_ sender: UIButton) 

    let networkReachability = Reachability.forInternetConnection()
    let networkStatus:Int = (networkReachability?.currentReachabilityStatus())!.rawValue
    print(networkStatus)
    if networkStatus == NotReachable.rawValue 
        let msg = SharedClass.sharedInstance.noNetMsg
        SharedClass.sharedInstance.alertWindow(title: "", message: msg)
     else 

        SharedClass.sharedInstance.activityIndicator(view: self.view)//Play spinner
        let parameters = "imei=\(deviceID)&devid=\(deviceID)&ver=\(ver)"
        print("Parameters : \(parameters)")
        var request = URLRequest(url: URL(string: url)!)

        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"

        print("URL : \(request)")

        request.httpBody = parameters.data(using: .utf8)

        let task = URLSession.shared.dataTask(with: request)  data, response, error in guard let data = data, error == nil else  // check for fundamental networking error
            SharedClass.sharedInstance.stopActivityIndicator() //Stop spinner
            print("error=\(String(describing: error))")
            SharedClass.sharedInstance.alertWindow(title: "", message: "\(String(describing: error!.localizedDescription))")
            return
            

            SharedClass.sharedInstance.stopActivityIndicator() //Stop spinner

            if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode == 500 
                SharedClass.sharedInstance.alertWindow(title: "", message: "Server Error")
             else if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200  // check for http errors
                print("statusCode should be 200, but is \(httpStatus.statusCode)")
                print("response = \(String(describing: response))")
            

            do 
                let response = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: AnyObject]
                print(response!)


                if status == "SUCCESS" 


                 else 
                    let message = res[0]["message"] as! String
                    //Call alert function
                    SharedClass.sharedInstance.alertWindow(title: "", message: message)
                

             catch let error as NSError 
                print(error)
                print(error.localizedDescription)
            
        

        task.resume()

    


在这里,当我第一次单击登录 btn 时,它工作正常。但是当我得到响应请求超时

错误

Error Domain=NSURLErrorDomain Code=-1001 "请求超时。" UserInfo=NSUnderlyingError=0x7f9eab767d60 错误域=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo=_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4

将显示警报。 在这种情况下,当我第二次单击登录 btn 时,应用程序因错误而崩溃:Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

1) 我的代码格式是否正确(指函数调用和 JSON 邮政编码)

2) 如何解决这个错误。

【问题讨论】:

崩溃在哪一行? 在 let window = UIApplication.shared.keyWindow 中!行我收到此错误.. 有条件地解包而不是强制解包 如果这样写 let window = UIApplication.shared.keyWindow 可以吗 不,if let window = UIApplication.shared.keyWindow ... 【参考方案1】:

您可以确保您获得了 keyWindow,就像您没有获得 window 一样,您将在哪里显示您的活动加载器。

按照以下方式进行

guard let window = UIApplication.shared.keyWindow else 
  return

这正是 paulw11 的建议

【讨论】:

其实我跟着 if let window = UIApplication.shared.keyWindow ... 可以吗 实际上它不起作用。我更新了我的问题,添加了警报代码。实际上在我不确切知道的地方是矛盾的。之后显示警报时,它不会显示微调器。 我认为您应该提出一个新问题,提及较少但重要的细节,以及确切的问题。

以上是关于ActivityIndi​​cator(微调器)出现错误在展开可选值时意外发现 nil的主要内容,如果未能解决你的问题,请参考以下文章

Xamarin Forms 两种方式绑定ActivityIndi​​cator

React Native - 将 ActivityIndi​​cator 重新定位到登录按钮

swift UIView的+ ActivityIndi​​cator.swift

动画完成后 React-Native ActivityIndi​​cator 不隐藏

swift RxSwift:基于ActivityIndi​​cator过滤可观察序列的元素。

如何在 UITableView 的 searchBar 上方显示 UIActivityIndi​​cator