当视图未将自身添加到其子视图时,“无法将自身添加为子视图”崩溃(带有示例代码)
Posted
技术标签:
【中文标题】当视图未将自身添加到其子视图时,“无法将自身添加为子视图”崩溃(带有示例代码)【英文标题】:"Can't add self as subview" crash (with sample code) when view not adding itself to its subview 【发布时间】:2018-03-15 21:04:20 【问题描述】:我可以用一个简单的项目重现这个问题 (Github Project)
主故事板有一个嵌入的ViewController
,由最初的NavigationController
转换为一个segue。 Nav Controller 是初始的根控制器,在故事板视图中也是如此。
AppDelegate 类didFinishLaunchingWithOptions
方法实例化另一个导航控制器并以编程方式添加根视图控制器:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool
let mainvc = MainViewController()
let mainnc = UINavigationController(rootViewController: mainvc)
self.window?.rootViewController = mainnc
self.window?.makeKeyAndVisible()
// Override point for customization after application launch.
return true
上面实例化的 MainViewController 有以下代码。
class MainViewController : UITableViewController, UIAlertViewDelegate
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
convenience init()
self.init(nibName:nil, bundle:nil)
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?)
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
override func viewDidLoad()
super.viewDidLoad()
let tableView = UITableView(frame:CGRect(x:0, y:0, width:self.view.bounds.size.width, height:self.view.bounds.size.height), style:.plain)
self.tableView = tableView
tableView.delegate = self
tableView.dataSource = self
tableView.separatorColor = UIColor(white:0.85, alpha:1)
tableView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
tableView.register(UITableViewCell.self, forCellReuseIdentifier:"nephews")
self.view.addSubview(tableView) // CRASH
运行代码时,我得到:
2018-03-15 13:35:57.083953-0700 CantAddSelfAsSubview[20953:14423557] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“无法将自身添加为子视图”
*** First throw call stack:
(
0 CoreFoundation 0x000000010957912b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x0000000105900f41 objc_exception_throw + 48
2 CoreFoundation 0x00000001095ee245 +[NSException raise:format:] + 197
3 UIKit 0x0000000106267582 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 122
4 UIKit 0x00000001062c6341 -[UITableView _addSubview:positioned:relativeTo:] + 127
5 CantAddSelfAsSubview 0x0000000104fdf310 _T020CantAddSelfAsSubview20MyMainViewControllerC11viewDidLoadyyF + 1312
6 CantAddSelfAsSubview 0x0000000104fdf6c4 _T020CantAddSelfAsSubview20MyMainViewControllerC11viewDidLoadyyFTo + 36
7 UIKit 0x000000010634546c -[UIViewController loadViewIfRequired] + 1235
8 UIKit 0x000000010638cffc -[UINavigationController _updateScrollViewFromViewController:toViewController:] + 68
9 UIKit 0x000000010638d338 -[UINavigationController _startTransition:fromViewController:toViewController:] + 153
10 UIKit 0x000000010638e44f -[UINavigationController _startDeferredTransitionIfNeeded:] + 841
11 UIKit 0x000000010638f6d3 -[UINavigationController __viewWillLayoutSubviews] + 150
12 UIKit 0x00000001065ea4e2 -[UILayoutContainerView layoutSubviews] + 231
13 UIKit 0x000000010626ea6d -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1439
14 QuartzCore 0x000000010cb5e61c -[CALayer layoutSublayers] + 159
15 QuartzCore 0x000000010cb627ad _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 401
16 QuartzCore 0x000000010cae986c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 364
17 QuartzCore 0x000000010cb16946 _ZN2CA11Transaction6commitEv + 500
18 UIKit 0x00000001061b826a __34-[UIApplication _firstCommitBlock]_block_invoke_2 + 141
19 CoreFoundation 0x000000010951c05c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
20 CoreFoundation 0x000000010950083b __CFRunLoopDoBlocks + 203
21 CoreFoundation 0x0000000109500014 __CFRunLoopRun + 1300
22 CoreFoundation 0x00000001094ff889 CFRunLoopRunSpecific + 409
23 GraphicsServices 0x000000010bd069c6 GSEventRunModal + 62
24 UIKit 0x000000010619d5d6 UIApplicationMain + 159
25 CantAddSelfAsSubview 0x0000000104fe2027 main + 55
26 libdyld.dylib 0x000000010a717d81 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
由于我没有向自身添加视图,因此问题似乎出在其他地方。
我在 SO 上阅读了许多类似问题但没有重现代码的 cmets。有些人担心动画未完成时 NavController 中存在错误。我如何控制 segue 的动画,因为它由第一个导航控制器自动管理?
【问题讨论】:
【参考方案1】:由于viewDidLoad
、self.view
、self.tableView
和tableView
中的代码不正确,都是同一个视图。因此出现错误。
这是UITableViewController
。它已经有一个表格视图。不要创建另一个。更新viewDidLoad
如下:
override func viewDidLoad()
super.viewDidLoad()
tableView.separatorColor = UIColor(white:0.85, alpha:1)
tableView.register(UITableViewCell.self, forCellReuseIdentifier:"nephews")
您也不需要添加任何init
方法。
【讨论】:
谢谢。这个tableView.delegate = self
和tableView.dataSource = self
真的不需要吗?
正确。 UITableViewController
使自己成为表视图的数据源并自动委托。您需要更改的另一件事是您在应用程序委托中创建MainViewController
的代码。您应该调用采用表格视图样式的初始化程序,而不是默认的空初始化程序。
@Laurent 虽然您确实需要在MainViewController
中实现各种数据源和委托方法才能使表格视图有用。
+1,我试图简明扼要地指出问题所在。我的主要项目更丰富 :-) 我将使用 MainViewController(style: .plain)
以上是关于当视图未将自身添加到其子视图时,“无法将自身添加为子视图”崩溃(带有示例代码)的主要内容,如果未能解决你的问题,请参考以下文章