当任何单元格包含UISwitch

时间:2015-08-18 20:36:14

标签: swift uitableview nsoperationqueue uiswitch

我正在开发一款iPhone应用程序,它可以进行大量的数学计算,大约需要5-6秒,但重复几次(因此,通常需要大约50-60秒)。完整的计算集可以一起重复几次。每个计算都封装在NSOperation

我遇到一个问题,在第一次运行计算期间,如果某个应用尝试显示UITableView,其中任何单元格都有UISwitch,那么所有应用内容都会冻结,直到NSOperationQueue计算变空。 (在我的应用中,如果用户尝试打开包含此类表视图的应用内首选项,则在首次运行计算完成之前,UI会冻结)。

当我发生这种情况时,我花了大约一个星期的时间在冰点到尖点的状态。以下是在我的应用中重现问题的代码。如果你运行它并在所有5个操作完成之前按“显示表”,UI将冻结,直到队列为空(如果操作在你的机器上完成得太快,则减少添加的数字)。

如果我用GCD替换NSOperationQueue,问题就会消失。如果我将UISwitch替换为UIButton,问题也会消失。我正在运行Xcode 6.4(6E35b)。

有时UI不会在此演示代码中冻结(但是,它总是在我的实际应用程序中冻结),但重新运行它会使它最终出现。此外,我发现在我的机器上设置maxConcurrentOperationCount为2(2核心2009 MBP)会使问题消失,但将其设置为更高的数字会使其更频繁地发生。

任何甚至是偏远的建议都将受到高度赞赏。

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    private let queue = NSOperationQueue()

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        let viewController = UIViewController()
        viewController.view.backgroundColor = UIColor.whiteColor()
        viewController.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Show table", style: .Plain, target: self, action: "showTable:")

        let navigationController = UINavigationController(rootViewController: viewController)

        let screenBounds = UIScreen.mainScreen().bounds
        window = UIWindow(frame: screenBounds)
        window?.rootViewController = navigationController
        window?.makeKeyAndVisible()

        setUpComputations()

        return true
    }

    func showTable(sender: UIBarButtonItem!) {
        let tableViewController = TableViewController()
        let navigationController = UINavigationController(rootViewController: tableViewController)
        window?.rootViewController?.presentViewController(navigationController, animated: true, completion: nil)

        println("showed table")
    }

    private func setUpComputations() {
        // queue.maxConcurrentOperationCount = 2

        for i in 0...5 {
            // dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {

            queue.addOperationWithBlock {
                dispatch_async(dispatch_get_main_queue()) {
                    println("starting operation \(i)")
                }

                var sum = 0.0
                for _ in 0...5 {
                    while sum < 1000.0 {
                        sum += 1.0e-6
                    }
                }

                dispatch_async(dispatch_get_main_queue()) {
                    println("finishing operation \(i)")
                }
            }
        }
    }
}

internal final class TableViewController: UITableViewController {
    func dismiss(sender: UIBarButtonItem!) {
        dismissViewControllerAnimated(true, completion: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .Done, target: self, action: "dismiss:")
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
            ?? UITableViewCell(style: .Default, reuseIdentifier: "Cell")
        cell.textLabel?.text = "Some text"

        cell.accessoryView = UISwitch()
        // cell.accessoryView = UIButton.buttonWithType(.InfoLight) as! UIButton

        return cell
    }
}

附录:感谢 Rob 的输入,我注意到在操作上设置qualityOfService = .Background而不是队列,似乎可以解决问题。即,用

替换上面的setUpComputations
private func setUpComputations() {
    for i in 0...5 {
        let operation = NSBlockOperation {
            dispatch_async(dispatch_get_main_queue()) {
                println("starting operation \(i)")
            }

            var sum = 0.0
            for _ in 0...5 {
                while sum < 1000.0 {
                    sum += 1.0e-6
                }
            }

            dispatch_async(dispatch_get_main_queue()) {
                println("finishing operation \(i)")
            }
        }

        operation.qualityOfService = .Background
        queue.addOperation(operation)
    }
}

0 个答案:

没有答案