是编译器错误,还是有人知道代码可能出错? 此单一视图应用程序模板的新项目代码。 要使应用程序崩溃,您可以将AppDelegate.swift中的默认代码替换为以下代码:
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window?.rootViewController = UINavigationController(rootViewController: CrashController())
window?.makeKeyAndVisible()
return true
}
}
//======================================================================================================================
class CrashController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
navigationItem.title = "Optimisation is not always Good"
let button = UIButton(type: .system)
button.setTitle("Crash the App Under Release", for: .normal)
button.frame = CGRect(x: 20, y: 200, width: 300, height: 50)
button.addTarget(self, action: #selector(onCrashButton), for: .touchUpInside)
view.addSubview(button)
}
@IBAction func onCrashButton(_ sender: UIButton) {
let goodItem = SomeItem(text: "1") // This Item will BE stored properly
let badItem = SomeItem(textWithCrash: "2") // This Item will NOT be stored properly
DispatchQueue.main.async() {
print(goodItem.text)
print(badItem.text) // EXC_BAD_ACCESS under Release
}
print(goodItem.text)
print(badItem.text)
}
}
//======================================================================================================================
class SomeItem {
var text = ""
deinit {
print("deinit \(self.text)")
}
// required initializer
required init(textWithoutCrash: String) {
self.text = textWithoutCrash
print("required init \(self.text)")
}
// designated initializer
init(text: String) {
self.text = text
print("designated init \(self.text)")
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DANGEROUS convenience initializer !!! App will BE crashed under Release Build Configeration
//
// calling required initializer inside convenience initializer is DANGEROUS under release with optimization:
// ENABLE_TESTABILITY = NO
// SWIFT_OPTIMIZATION_LEVEL = -Owholemodule
//
// There is NO crash Under Debug Build Configeration without optimisation:
// ENABLE_TESTABILITY = YES
// SWIFT_OPTIMIZATION_LEVEL = -Onone
//
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
convenience init(textWithCrash: String) {
// App will NOT be crashed calling designated initializer
// self.init(text: textWithCrash)
// App will be CRASHED later due to calling required initializer inside convenience initializer
self.init(textWithoutCrash: textWithCrash)
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Optimisation causes crash ONLY if
// - the class has convenience init
// - the required initializer is calling inside the convenience init
// - the class has any children, (anyone inherits from the class) even if children does not use at all
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class SomeChildItem: SomeItem {
// // implementing required initializer does not help - App will be crashed anyway
// required init(textWithoutCrash: String) {
// super.init(textWithoutCrash: textWithoutCrash)
// }
//
// // overriding designated initializer does not help - App will be crashed anyway
// override init(text: String) {
// super.init(text: text)
// }
//
// // implementing convenience initializer does not help - App will be crashed anyway
// convenience init(textWithCrash: String) {
// self.init(textWithoutCrash: textWithCrash)
// }
}
Debug下没有崩溃,但只有在菜单栏中选择Build configuration Release
时才会发生崩溃:Product - &gt;方案 - &gt;编辑方案或只需按下Cmd-Shift-<
热键。或者在生产版本中,如果您创建存档。
我发现该应用程序在发布时默认设置崩溃了
应用程序未在Debug:
下使用默认设置崩溃崩溃的一些条件:
我没有在Apple文档中找到从便捷初始化程序调用所需初始化程序的任何禁忌。此外,Apple的文档&#34; The Swift Programming Language(Swift 3.0.1)&#34;有短语&#34;当覆盖所需的指定初始化程序时,你不会写覆盖修饰符&#34;这意味着还需要指定。因此,可以从便利性中调用它。 我使用Xcode版本8.1(8B62)和Swift 3.0.1。 有什么想法吗?
UPDATE1: 不带DispatchQueue.main.async的onCrashButton版本,所以如果你访问下一个runloop中的坏项,它将是BAD_ACCESS并崩溃。
var someItems = [SomeItem]()
@IBAction func onCrashButton(_ sender: UIButton) {
print("someItems: \(someItems.count)")
if let someItem = someItems.last {
// Any Access to someItem is BAD_ACCESS and crashes the App. Why?
let text = someItem.text
print("text: \(text)")
}
// This Item will BE stored properly.
someItems += [SomeItem(text: "Some text \(someItems.count)")]
// This Item will NOT be stored into array properly. Why?
someItems += [SomeItem(textWithCrash: "Some text \(someItems.count)")]
}