简体   繁体   English

为什么我的应用程序仍然冻结,即使我使用Alamofire提出请求?

[英]why my app still freezing even though I use Alamofire to make a request?

I am new in programming, but I usually I have no issue to make request to get JSON data from server. 我是编程新手,但我通常没有问题要求从服务器获取JSON数据。

I have tried some similar thread in here: Alamofire network calls not being run in background thread but the solution doesn't solve my problem! 我在这里尝试了一些类似的线程: Alamofire网络调用没有在后台线程中运行,但解决方案并没有解决我的问题!

so I want to implement pagination, so when the user reach bottom of the screen, then I will make a request to the server. 所以我想实现分页,所以当用户到达屏幕底部时,我会向服务器发出请求。

but unfortunately, even though I can get the JSON data from server, but it will freeze the app. 但不幸的是,即使我可以从服务器获取JSON数据,但它会冻结应用程序。 it seems that this is not performed in the background (still on the main thread). 似乎这不是在后台执行(仍然在主线程上)。

but I don't understand why. 但我不明白为什么。 I assume that if I use Alamofire to make a request, it will automatically perform it asynchronously. 我假设如果我使用Alamofire发出请求,它将自动异步执行。 because usually I make a request on viewDidLoad or viewWillAppear and my app never freezing. 因为通常我在viewDidLoadviewWillAppear上发出请求,我的应用程序永远不会冻结。

here is the code triggered when the scroll view reach the bottom: 这是滚动视图到达底部时触发的代码:

extension HomeVC : UIScrollViewDelegate {

    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {


        let currentOffset = scrollView.contentOffset.y
        let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height


            if maximumOffset - currentOffset <= 10.0 {

            // load more product data when reaching the bottom of main scroll view

            pageNumberTracker += 1
            SVProgressHUD.show(withStatus: "Please Wait")

            Product.getProducts(searchType: "newest", pageNumber: pageNumberTracker, categoryID: selectedCategoryID) { (errorWhileMakingRequest, errorMessageFromServer, products) in

                if errorWhileMakingRequest != nil || errorMessageFromServer != nil {
                    SVProgressHUD.dismiss()
                    return
                }



                guard let products = products else {self.activityIndicator.stopAnimating(); return}

                self.thirdProducts += products
                self.updateLocalDataToBeTheSameAsRealmDatabase()
                self.setThirdListProductCollectionViewHeight()
                self.thirdListProductCollectionView.reloadData()
                SVProgressHUD.dismiss()


            }




        }
    }



}

here is the getProduct() method : 这是getProduct()方法:

static func getProducts(searchType: String, pageNumber: Int = 0, categoryID: Int = 0, completion: @escaping(_ errorWhileMakingRequest: Error?, _ errorMessageFromServer: String?,_ productsData: [Product]?) -> Void) {

        let urlProducts = URLService.products.endPoint
        let headers = ["Content-Type": "application/x-www-form-urlencoded"]

        let parameters : [String:Any] = [
            "type": searchType,
            "language_id": 1,
            "page_number": pageNumber,
            "minPrice": 0,
            "maxPrice":10000000,
            "categories_id": categoryID
        ]

        AlamofireManager.shared.request(urlProducts,
                          method: .post,
                          parameters: parameters,
                          encoding: URLEncoding.default,
                          headers:headers)
            .validate()
            .responseJSON { response in

                switch response.result {

                case .failure(let error) :

                    completion(error,nil,nil)

                case .success(let value) :

                    let json = JSON(value)
                    let successStatus = json["success"].stringValue

                    if successStatus == "0" {
                        let errorMessage = json["message"].stringValue
                        completion(nil,errorMessage,nil)
                    } else if successStatus == "1" {

                        let productsArrayJSON = json["product_data"].arrayValue
                        var productsData = [Product]()

                        for productJSON in productsArrayJSON {
                            if let productDictionary = productJSON.dictionaryObject {
                                let product = Product(dictionary: productDictionary)
                                productsData.append(product)
                            } else {
                                completion(nil,nil,nil)
                                break
                            }
                        }

                        completion(nil,nil,productsData)



                    }

                }

        }




    }

and here is the Alamofire manager code: 这里是Alamofire经理代码:

struct AlamofireManager {
    static let shared: SessionManager = {
        let configuration = URLSessionConfiguration.default
        configuration.timeoutIntervalForRequest = 15
        let sessionManager = Alamofire.SessionManager(configuration: configuration, delegate: SessionDelegate(), serverTrustPolicyManager: nil)
        return sessionManager
    }()
}

what went wrong in here ? 这里出了什么问题?

The completion of an Alamofire request will execute on the main thread by default. 默认情况下,Alamofire请求的完成将在主线程上执行。 If your response from the server is pretty big, then doing those JSON operations can be pretty expensive and cause some frame drops. 如果您对服务器的响应非常大,那么执行这些JSON操作可能会非常昂贵并导致一些帧丢失。 Alamofire allows you to set the completion queue by calling it like this: Alamofire允许您通过调用它来设置完成队列:

AlamofireManager.shared.request(urlProducts,
                          method: .post,
                          parameters: parameters,
                          encoding: URLEncoding.default,
                          headers:headers)
            .validate()
            .responseJSON(queue: DispatchQueue.someQueue) { response in
                 ...
            }

I think the reason is not related to the threading. 我认为原因与线程无关。 You are not handling the completion block properly in all cases. 在所有情况下,您都没有正确处理完成块。 In case of success you are handling just two scenarios ie when successStatus is either 1 or 0 . 如果成功,您只处理两种情况,即successStatus10 What happens if it is neither of the two? 如果两者都不是,会发生什么? Hence you should add an else block at the end so that the completion block gets called in all cases. 因此,您应该在末尾添加一个else块,以便在所有情况下都调用完成块。 Here's the code: 这是代码:

case .success(let value):

    let json = JSON(value)
    let successStatus = json["success"].stringValue

    if successStatus == "0" {
        let errorMessage = json["message"].stringValue
        completion(nil,errorMessage,nil)
    } else if successStatus == "1" {

        let productsArrayJSON = json["product_data"].arrayValue
        var productsData = [Product]()

        for productJSON in productsArrayJSON {
            if let productDictionary = productJSON.dictionaryObject {
                let product = Product(dictionary: productDictionary)
                productsData.append(product)
            } else {
                completion(nil,nil,nil)
                break
            }
        }

        completion(nil,nil,productsData)
    }
    else {
        // Decide how you should call the completion block
        completion(xx, yy, zz)
    }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 我可以将Alamofire更新到版本4,并且在我的应用程序中仍然支持iOS 8吗? - Can I update Alamofire to version 4 and still support iOS 8 in my app? 为什么我的 Xcode 编译器告诉我我使用的是值类型,即使我使用的是类? - Why does my Xcode compiler tell me I use a value type even though I use classes? 为什么我不能在Alamofire 4.0中使用SessionManager发出请求? - Why can't I make a request with SessionManager in Alamofire 4.0? 即使我要求在后台更新位置,为什么我的iOS应用程序会被杀死? - Why does my iOS app get killed even though I ask for location updates in the background? Alamofire请求在连接速度慢时使我的应用程序崩溃 - Alamofire request crashes my app on slow connection 即使我在NSDateFormatter上设置了时区,为什么stringFromDate NSString仍然具有GMT时间? - Why does stringFromDate NSString still have GMT time even though I set timezone on the NSDateFormatter? 即使我从捆绑软件中删除了图像,为什么Xcode仍会将图像复制到设备上? - Why would Xcode still copies images to device even though I removed them from bundle? 我无法向 Alamofire 提出样品请求 - I cannot make a sample request with Alamofire 为什么我无法在Alamofire 4.0中使用SessionManager初始化或发出请求? (更新) - Why can't I initialize or make a request with SessionManager in Alamofire 4.0? (UPDATED) 我想在我的应用程序中使用ng2-charts。尽管我已正确导入它,但仍然给我一个错误。找不到模块“ ng2-charts / ng2-charts” - I want to use ng2-charts in my app.though I have imported it correctly still it is giving me an error Cannot find module “ng2-charts/ng2-charts”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM