使用Xcode6-Beta5我已经构建了一个部署目标为7.0的Universal Swift应用程序 . 我构建了一个包含UIActionSheet和UIAlertController的测试应用程序 - 一个按钮选择在运行时调用哪一个 .

首先总结一下:1 . 将8.0内容放入应用程序会导致7.1设备启动失败,即使不执行8.0代码也是如此 . 8.0调用会污染应用程序 . 2. UIActionSheet和UIAlertController都不能在iPad 8.0设备上运行 .

在模拟器中运行:
所有iPhone 8.0目标都可以成功显示UIActionSheet和UIAlertController . 所有iPhone 7.1目标都无法启动UIAlertAction或UIAlertController的符号未找到错误 . 这是一个dyld_fatal_error .

所有iPad 7.1目标都无法启动,就像iPhone 7.1目标失败一样 .
如果我注释掉UIActionController和UIActionAlert代码,那么该应用程序适用于运行UIActionSheet的7.1设备 .

在所有运行UIActionSheet的iPad 8.0目标中都没有显示任何内容,并产生大约80行NSLayoutConstraint问题 . 在所有运行UIActionController的iPad 8.0目标中,将SIGABRT抛出到AppDelegate中:

2014-08-15 10:21:51.799 AlertControllerTest [1828:246107] *由于未捕获的异常终止应用'NSGenericException',原因:'UIPopoverPresentationController (<_UIAlertControllerActionSheetRegularPresentationController: 0x78651780>) should have a non-nil sourceView or barButtonItem set before the presentation occurs.'

  • 这些在Xcode6-Beta5中是否仍然被破坏或者我做错了什么?

  • 只要不调用8.0函数,是否可以在使用8.0函数构建的7.1应用程序上运行?早期版本曾经以这种方式工作 .

在有人要求查看源代码之前(现在通过GM修改最佳):

@IBAction func tapHereTapped(sender: AnyObject) {
    if sheetOrControllerButton.selectedSegmentIndex == 0 {
        var actionSheet = UIActionSheet()
        actionSheet.addButtonWithTitle("Choice 1")
        actionSheet.addButtonWithTitle("Choice 2")
        actionSheet.addButtonWithTitle("Choice 3")
        actionSheet.addButtonWithTitle("Choice 4")
        actionSheet.addButtonWithTitle("Cancel")
        if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
            actionSheet.addButtonWithTitle("Dummy")
            let systemVersion = UIDevice.currentDevice().systemVersion
            if NSString(string: UIDevice.currentDevice().systemVersion).doubleValue >= 8 {
                //actionSheet.cancelButtonIndex = 4
                //actionSheet.cancelButtonIndex = 5
            } else {
                actionSheet.cancelButtonIndex = 4
            }
        } else {
            actionSheet.cancelButtonIndex = 4
        }
        actionSheet.title = "Pick a Number"
        actionSheet.delegate = self
        actionSheet.showInView(self.view)
    } else {
        var actionSheet:UIAlertController

        if sheetOrControllerButton.selectedSegmentIndex == 1 {
            actionSheet = UIAlertController(title: "Pick a Number", message: "Why?", preferredStyle: UIAlertControllerStyle.Alert)
        } else {
            actionSheet = UIAlertController(title: "Pick a Number", message: "Why?", preferredStyle: UIAlertControllerStyle.ActionSheet)
            if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
                var button = sender as UIButton
                actionSheet.popoverPresentationController?.sourceRect = button.bounds
                actionSheet.popoverPresentationController?.sourceView = button.viewForBaselineLayout()
            }
        }
        actionSheet.addAction(UIAlertAction(title: "Choice 1", style: UIAlertActionStyle.Default, handler: { (action :UIAlertAction!)in
            println("Picked 1")
        }))
        actionSheet.addAction(UIAlertAction(title: "Choice 2", style: UIAlertActionStyle.Default, handler: { (action :UIAlertAction!)in
            println("Picked 2")
        }))
        actionSheet.addAction(UIAlertAction(title: "Choice 3", style: UIAlertActionStyle.Default, handler: { (action :UIAlertAction!)in
            println("Picked 3")
        }))
        if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
            actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Default, handler: { (action :UIAlertAction!)in
                println("Canceled")
            }))
        } else {
            actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: { (action :UIAlertAction!)in
                println("Canceled")
            }))
        }
        self.presentViewController(actionSheet, animated: true, completion: nil)
    }
}

func actionSheet(theActionSheet: UIActionSheet!, clickedButtonAtIndex buttonIndex: Int) {
    if (buttonIndex == 0) {
        println("Picked 1")
    } else if buttonIndex == 1 {
        println("Picked 2")
    } else if buttonIndex == 2 {
        println("Picked 3")
    } else if buttonIndex == 3 {
        println("Picked 4")
    } else if buttonIndex == 4 {
        println("Canceled")
    } else {
        println("What??")
    }
}

我在物理iPhone 4 - 7.1,iPad 2 - 7.1上得到了相同的行为所有8.0测试都在模拟器中 - 我没有在任何设备上放置8.0但又不想让它变硬 .

谢谢大家 .

更新为Beta6:
注意 - 这仍然是模拟器测试 .
我们现在有完整的解决方法来构建一个适用于7.1和8.0的通用应用程序 .
iPhone - 测试iOS版本并根据需要使用UIActionSheet或UIAlertController . .ActionSheet和.Alert样式都适用于8.0 .

iPad 7.1 - UIActionSheet现在"works",但你需要添加一个虚拟的额外按钮 - 它无法显示添加的最后一个按钮 .
iPad 8.0 - UIAlertController .Alert工作,但看起来很糟糕,而.ActionSheet仍然像UIActionSheet一样崩溃 .

更新为Beta7:
没有变化 . iPhone按预期工作 . iPad仍然如上所述 .

通用汽车更新:iPad 8.0的一些改进 . (或者我之前没想过 . )iPhone仍能正常工作 . 包括iPhone 6和iPhone 6 Plus在模拟器中 .

iPad 7.1 - UIActionSheet仍然需要虚拟按钮 . cancelButtonIndex将使文本变暗以指示它是取消按钮,但它不会抵消它 .

iPad 8.0 - UIActionSheet不会崩溃,但不要使用它 . 如果cancelButtonIndex不是-1,则表示列表末尾的按钮显示有问题 . 它可能仍然需要一个虚拟按钮 . 但现在必须将cancelButtonIndex设置为虚拟按钮(不会显示) . 但更糟糕的是,clickedButtonAtIndex被调用两次,一次使用单击按钮,一次使用cancelButtonIndex . 就好像它在行动表关闭时检测到一个虚假 .

iPad 8.0 - 带有.Alert的UIAlertController仍然可以 .
iPad 8.0 - 如果设置了popoverPresentationController sourceRect和sourceView,带有.ActionSheet的UIAlertController现在可以工作 . (之前的情况可能就是这种情况,但是我还有一个问题 - UIAlertActionStyle.Cancel导致按钮消失,所以不要使用它 .

更新为6.0.1:
iPad 7.1 - UIActionSheet仍然需要虚拟按钮 .
iPad 8.0 - 带有.Alert的UIAlertController可以 . 带有UIAlertActionStyle.Cancel的按钮会自动放在按钮列表的底部 .
iPad 8.0 - 带有.ActionSheet的UIAlertController仍然需要设置popoverPresentationController值 . 并且UIAlertActionStyle.Cancel仍然失败 .

总结 - 尚未改进:
iPhone - 所有版本都可以正常工作 - 可以使用UIActionSheet和UIAlertController作为.Alert和.ActionSheet .
iPad 7.1 - UIActionSheet适用于虚拟 .
iPad 8.0 - UIAlertController的工作原理为.Alert和.ActionSheet . 不要使用UIActionSheet .