直接把ViewController的view 通过addSubview添加到另一个View,则不会调用viewDidAppear

   如果是直接把ViewController的view 通过addSubview添加到另一个View,则不会调用viewDidAppear,你需要手动发送viewDidAppear给这个View Controller。

苹果的文档是这样描述的:
If the view belonging to a view controlleris added to a view hierarchy directly, the view controller will not receivethis message. If you insert or add a view to the view hierarchy, and it has aview controller, you should send the associated view controller this messagedirectly. Failing to send the view controller this message will prevent anyassociated animation from being displayed.

        那么我们是不是可以这样认为:
pushViewController,或presentModelViewController这个View Controller时,会调用它的viewDidAppear方法呢?苹果文档中未说明。

        事实上即使是用presentModelviewController,viewDidAppear也不一定能被调用。测试的结果表明:如果nib第1次加载的时候,viewDidAppear一定会调用的。但如果第2次加载这个nib则不一定会调用。viewDidLoad则无论何种情况总是调用的,所以要保险得多。另外,在iPad中没有这样的问题,viewDidAppear总是会调用的。

        补充说明,viewWillAppear和viewDidAppear的情况是一样的,在iPhone上,除了第1次加载xib文件时肯定会调用外,其他任何情况都不会自动调用:无论popViewControllerAnimate、presentModalViewController还是addSubviews。但iPad上则相反,除了addSubviews方法外,都一定会调用。此外,测试是在ios4.3设备上进行的。

        btw:viewDidLoad方法只有在initWithNibName时会调用。
如果ViewController是在TabViewController中加载的,则等同于addSubView。当TabViewController第一次显示时,这个ViewController的viewDidLoad方法会调用,而viewDidAppear方法不会调用。但是当点击TabBarItem时则恰巧相反,只会调用ViewController的viewDidAppear而不会调用viewDidLoad。

viewWillAppear和viewDidAppear什么时候被调用

【问】:
当我向一个UINavigationController压入一个视图控制器的时候,
         1.    什么时候会触发viewWillAppear和viewDidAppear?
         2.    什么导致了触发viewWillAppear和viewDidAppear失败?
【答】:
    当你调用pushViewController:animated把一个视图控制器压入UINavigationController的时候,UINavigationController会自动调用这些方法。相似的,当你tabs时,UITabBarController会直接调用这些方法,当你使用presentModalViewController时也会调用方法。当一个视图控制器的视图被添加到一个window中时也会调用这些方法。我在这些情况下没有遇到过这些方法调用失败的情况。

    记住,这些方法只在这些特定的情况下控制器pushed或presented的时候被调用。在其它的情况下不会被调用,比如你添加你的视图控制器的视图作为一个视图的子视图而不是作为window的子视图。苹果官方文档说视图控制器仅用于全屏显示的视图,典型的是使用上面提到的方法。可以忽略苹果的建议使一个视图控制器关联另一个视图控制的的视图作为子视图,但是你需要在作为容器的视图控制器中手动的调用嵌套控制器的viewWillAppear和viewDidAppear。
为什么一开始进入到默认event.view页面就会打印viewWillAppear false日志,然后切换到device alert就会viewWillDisappear false,而在custom和device切换没有日志,event页面是不是切换有逻辑问题?且我并没有打印出这样的日志,系统还会自动打印吗?// // EventCenterViewController.swift import TPBMDesignKit // MARK: - eventcenter主控制器 class TPGuardEventCenterController: TPHomeBaseViewController{ //侧边栏controller private let eventCenterSidebarController = TPGuardSidebarController() private let eventCenterSplitView: TPGuardEventCenterSpliteView = TPGuardEventCenterSpliteView() private var isIniteventCenterPlayerSplitView: Bool = false // 侧边栏是否已收起 private var isSidebarCollapsed :Bool = false // 右侧三个子页面controller private let eventCenterRightView = NSView() private let eventController = TPGuardEventController() private let customAlertController = TPGuardCustomAlertController() private let deviceAlertController = TPGuardDeviceAlertController() //侧边栏的导航栏 private let eventCenterSidebarScrollView : NSScrollView = NSScrollView() private let eventCenterSidebarOutlineView : TPGuardOutlineView = TPGuardOutlineView() //侧边栏收起按钮 private let sidebarButton : TPBButton = TPBButton() //侧边栏的item private var sidebarItems: [SidebarItem] = [] //第一次加载进内存时候 override func viewDidLoad() { super.viewDidLoad() // Do view setup here. } override func setupSubviews() { super.setupSubviews() // MARK: - 主界面splitView分割 /*split添加调用 addArrangedSubview 不仅添加了视图,还让 NSSplitView 知道:“这个视图是我要管理的一个面板”,然后根据 arrangedSubviews 的顺序来决定左右或上下结构*/ eventCenterSplitView.addArrangedSubview(eventCenterSidebarController.view) eventCenterSplitView.addArrangedSubview(eventCenterRightView) //三个右侧页面添加view [eventController.view, customAlertController.view, deviceAlertController.view].forEach{ eventCenterRightView.addSubview($0) $0.translatesAutoresizingMaskIntoConstraints=false $0.snp.makeConstraints{make in make.edges.equalToSuperview()} } // //默认显示event页面 print("默认显示event页面") switchRightView(to: eventController.view) //设置代理 eventCenterSplitView.delegate = self //分割线设置+风格 eventCenterSplitView.isVertical = true eventCenterSplitView.dividerStyle = .thin // 异步设置初始宽度(确保布局已完成) DispatchQueue.main.async { [weak self] in guard let self = self else { return } let initialWidth: CGFloat = self.isSidebarCollapsed ? 48 : 160 self.eventCenterSplitView.setPosition(initialWidth, ofDividerAt: 0) // 根据目标宽度设置状态 self.isSidebarCollapsed = false } // 将 splitView 添加到主视图 view.addSubview(eventCenterSplitView) // MARK: - 侧边栏层级+按钮设置 // 添加收起按钮、配置 TPBButton 样式 sidebarButton.iconImage = .eventCenterSidebarButton sidebarButton.fillColor = .clear //代理 sidebarButton.target = self sidebarButton.action = #selector(hideSidebar) //将侧边栏按钮添加到侧边栏视图 eventCenterSidebarController.view.addSubview(sidebarButton) //将 eventCenterSidebarOutlineView 设置为滚动视图的“文档内容视图”(即可滚动区域的内容) eventCenterSidebarScrollView.documentView = eventCenterSidebarOutlineView //设置滚动视图背景颜色为深灰色(接近黑色) eventCenterSidebarScrollView.backgroundColor = NSColor(hexString: "0x1A1A1A") //关闭系统自动调整内容边距(content insets) eventCenterSidebarScrollView.automaticallyAdjustsContentInsets = false //启用 Auto Layout 布局方式、允许使用约束(constraints)来定位该视图 eventCenterSidebarScrollView.translatesAutoresizingMaskIntoConstraints = false //documentView添加水平方向约束让documentView的左右边缘与scrollView 对齐 eventCenterSidebarScrollView.documentView?.snp.remakeConstraints({ make in make.leading.trailing.equalTo(eventCenterSidebarScrollView) }) eventCenterSidebarOutlineView.backgroundColor = NSColor(hexString: "0x1A1A1A") //delegate 管“怎么展示”,dataSource 管“展示什么”。 eventCenterSidebarOutlineView.delegate = self eventCenterSidebarOutlineView.dataSource = self eventCenterSidebarOutlineView.tpGuardDelegate = self //启用自动行高(Auto Sizing Rows)。 eventCenterSidebarOutlineView.usesAutomaticRowHeights = true //禁用列的自动调整大小行为。默认情况下,AppKit 会尝试平均分配或按内容调整列宽。 eventCenterSidebarOutlineView.columnAutoresizingStyle = .noColumnAutoresizing //关闭选中项的高亮样式。原生默认是蓝色或灰色背景高亮。 eventCenterSidebarOutlineView.selectionHighlightStyle = .none //移除表头(Header View)。默认 NSTableView 顶部有一栏用于显示列标题。 eventCenterSidebarOutlineView.headerView = nil //禁用“轮廓列”(Outline Column)的自动缩放。在 NSOutlineView 中,“outline column”是显示层级结构的那一列(带展开箭头的那列)。 eventCenterSidebarOutlineView.autoresizesOutlineColumn = false //允许子视图(cell 内部的 subviews)随容器自动调整大小。这会影响单元格内部控件是否跟随表格宽度拉伸。 eventCenterSidebarOutlineView.autoresizesSubviews = true //启用 Core Animation Layer(即开启图层支持)。 eventCenterSidebarOutlineView.wantsLayer = true eventCenterSidebarOutlineView.layer?.borderColor = NSColor(hexString: "0xFFFFFF").withAlphaComponent(0.1).cgColor eventCenterSidebarOutlineView.layer?.borderWidth = 1.0 //注册支持接收某种拖拽类型的数据。 eventCenterSidebarOutlineView.registerForDraggedTypes([.dragOutlineItem]) //设置当前视图为拖拽源(source)时允许的操作类型。 eventCenterSidebarOutlineView.setDraggingSourceOperationMask(NSDragOperation.every, forLocal: true) //设置单元格之间的间距 eventCenterSidebarOutlineView.intercellSpacing = NSSize(width: view.bounds.width, height: 30.0) //创建并添加一列到表格中。 let column = NSTableColumn(identifier: NSUserInterfaceItemIdentifier("Column")) eventCenterSidebarOutlineView.addTableColumn(column) // eventCenterSidebarOutlineView.onDoubleClick = { [weak self] item in // if let device = item as? TPGuardDeviceItem, let self { // if device.deviceType == .IPC { // self.selectDevice(for: device) // } // } // } //允许“轮廓列”(Outline Column)根据父视图的大小变化自动调整宽度。 eventCenterSidebarOutlineView.autoresizesOutlineColumn = true //设置每一级子节点相对于父节点的缩进像素值(indentation),这里设为 0 像素。 eventCenterSidebarOutlineView.indentationPerLevel = 0 //将scrollView添加到侧边栏视图 eventCenterSidebarController.view.addSubview(eventCenterSidebarScrollView) eventCenterSidebarOutlineView.target = self eventCenterSidebarOutlineView.action = #selector(handleSidebarClick) } //添加约束 override func makeConstraints() { super.makeConstraints() // 让 eventCenterPlayerSplitView 的 上边、左边、下边、右边 都等于父视图 view 的对应边缘,也就是让这个 splitView 填满整个父视图的客户区(不包括窗口标题栏等系统区域)。 eventCenterSplitView.snp.makeConstraints { make in make.top.leading.bottom.trailing.equalTo(view) } // 添加侧边栏按钮的约束 sidebarButton.snp.makeConstraints { make in make.leading.equalToSuperview().offset(15) make.top.equalToSuperview().offset(15) make.size.equalTo(CGSize(width: 18, height: 18)) } //scrollview添加约束(与侧边栏按钮拉开了距离) eventCenterSidebarScrollView.snp.makeConstraints { make in make.top.equalTo(sidebarButton.snp.bottom).offset(8) make.leading.trailing.bottom.equalToSuperview() } } // MARK: - 初始化数据(后续需要介入拉取未读数) override func setupInitialData() { super.setupInitialData() // 全部事件 let events = SidebarItem(title: "Events", iconImage: .sidebarChooseButton, showsBadge: false) // 自定义告警 let customAlerts = SidebarItem( title: "Custom Alerts", iconImage: .sidebarChooseButton, children: [ SidebarItem( title: "My Alerts", iconImage: .sidebarChooseButton, children: [ SidebarItem(title: "Alert 1", iconImage: .sidebarChooseButton, showsBadge: true, unreadCount: 2), SidebarItem(title: "Alert 2", iconImage: .sidebarChooseButton, showsBadge: true, unreadCount: 1) ], showsBadge: false ), SidebarItem( title: "Shared Alerts", iconImage: .sidebarChooseButton, children: [ SidebarItem(title: "Alert 3", iconImage: .sidebarChooseButton, showsBadge: true, unreadCount: 3) ], showsBadge: false ) ], showsBadge: true, unreadCount: 99 ) // 设备告警 let deviceAlerts = SidebarItem(title: "Device Alerts", iconImage: .sidebarChooseButton, showsBadge: true, unreadCount: 3) sidebarItems = [events, customAlerts, deviceAlerts] } //绑定侧边栏的按钮事件(收起+拉伸) override func bindActions() { super.bindActions() } //侧边栏收起方法 @objc func hideSidebar() { let sidebarIndex = 0 let expandWidth : CGFloat = 160 let collapsedWidth : CGFloat = 48 //当侧边栏收起时 if isSidebarCollapsed{ //收起---展开 NSAnimationContext.runAnimationGroup{ context in context.duration = 0.3 // Set the duration of the animation self.eventCenterSplitView.setPosition(expandWidth, ofDividerAt: sidebarIndex) } }else { //展开--收起 NSAnimationContext.runAnimationGroup{ context in context.duration = 0.3 // Set the duration of the animation self.eventCenterSplitView.setPosition(collapsedWidth, ofDividerAt: sidebarIndex) } } isSidebarCollapsed.toggle() } } // MARK: -侧边栏Controller class class TPGuardSidebarController:TPBaseViewController{ override func viewDidLoad() { super.viewDidLoad() // Do view setup here. view.wantsLayer = true view.layer?.backgroundColor = NSColor.tpBackground.cgColor; } } // MARK: -侧边栏Controller扩展 extension TPGuardEventCenterController: NSSplitViewDelegate { //subview 这个子视图是否允许被折叠(即宽度/高度缩小到 0)?” func splitView(_ splitView: NSSplitView, canCollapseSubview subview: NSView) -> Bool { return false } func splitView(_ splitView: NSSplitView, constrainMinCoordinate proposedMinimumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { return 48 } func splitView(_ splitView: NSSplitView, constrainMaxCoordinate proposedMaximumPosition: CGFloat, ofSubviewAt dividerIndex: Int) -> CGFloat { return 160 } //“当用户拖动分隔条时,询问代理:是否允许系统自动调整 view 这个子视图的大小?” func splitView(_ splitView: NSSplitView, shouldAdjustSizeOfSubview view: NSView) -> Bool { return false } // func splitView(_ splitView: NSSplitView, shouldHideDividerAt dividerIndex: Int) -> Bool { // return deviceListHasHidden // } // func splitView(_ splitView: NSSplitView, effectiveRect proposedEffectiveRect: NSRect, forDrawnRect drawnRect: NSRect, ofDividerAt dividerIndex: Int) -> NSRect { // return deviceListHasHidden ? NSRect.zero : proposedEffectiveRect // } // func splitViewWillResizeSubviews(_ notification: Notification) { // if deviceListViewController.view.frame.size.width > 500 { // deviceListViewController.view.frame.size = NSSize(width: 500, height: deviceListViewController.view.frame.size.height) // } // } } // MARK: - 事件中心split class class TPGuardEventCenterSpliteView: NSSplitView { override var dividerColor: NSColor { return NSColor.tpSeparator } override var dividerThickness: CGFloat { return 1 } } // MARK: outlineview数据与界面 extension TPGuardEventCenterController: NSOutlineViewDelegate, NSOutlineViewDataSource, TPGuardOutlineViewDelegate { func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { guard let sidebarItem = item as? SidebarItem else { return sidebarItems.count } return sidebarItem.children?.count ?? 0 } func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { guard let sidebarItem = item as? SidebarItem else { return false } return sidebarItem.children?.isEmpty == false } func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { guard let sidebarItem = item as? SidebarItem else { return sidebarItems[index] } return sidebarItem.children![index] } func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { guard let sidebarItem = item as? SidebarItem else { return nil } //唯一标记一种类型的表格单元格(cell)实现 NSOutlineView 或 NSTableView 的 cell 复用机制 let identifier = NSUserInterfaceItemIdentifier("SidebarCell") //尝试从复用池中获取一个已经存在的、可重用的单元格 var sidebarCell = outlineView.makeView(withIdentifier: identifier, owner: self) as? NSTableCellView if sidebarCell == nil { sidebarCell = NSTableCellView() sidebarCell?.identifier = identifier // icon let sidebarImageView = NSImageView() sidebarImageView.translatesAutoresizingMaskIntoConstraints = false sidebarCell?.addSubview(sidebarImageView) sidebarImageView.tag = 100 sidebarImageView.snp.makeConstraints { make in make.leading.equalToSuperview().offset(0) make.centerY.equalToSuperview() make.width.height.equalTo(18) } // title let sidebarTextLabel = NSTextField(labelWithString: "") sidebarTextLabel.translatesAutoresizingMaskIntoConstraints = false sidebarTextLabel.textColor = .white // sidebarTextLabel.font = NSFont.systemFont(ofSize: 12) sidebarCell?.addSubview(sidebarTextLabel) sidebarTextLabel.tag = 101 sidebarTextLabel.snp.makeConstraints { make in make.leading.equalTo(sidebarImageView.snp.trailing).offset(8) make.centerY.equalToSuperview() } // unread count // let sidebarBadgeWidth: CGFloat = 20; // let sidebarBadgeHeigth: CGFloat = 14; // let sidebarBadgeLabel = TPBLabel(); // sidebarBadgeLabel.textColor = .white; // sidebarBadgeLabel.wantsLayer = true; // sidebarBadgeLabel.layer?.backgroundColor = NSColor.red.cgColor; // sidebarBadgeLabel.textAlignment = .center; // sidebarBadgeLabel.layer?.cornerRadius = (sidebarBadgeHeigth - 2) / 2; // sidebarBadgeLabel.layer?.masksToBounds = true; // sidebarBadgeLabel.layer?.borderWidth = 1.0; // sidebarBadgeLabel.layer?.borderColor = NSColor.red.cgColor; // unread count let sidebarBadgeLabel = NSTextField(labelWithString: "") sidebarBadgeLabel.translatesAutoresizingMaskIntoConstraints = false sidebarBadgeLabel.wantsLayer = true sidebarBadgeLabel.layer?.backgroundColor = NSColor.systemRed.cgColor sidebarBadgeLabel.layer?.cornerRadius = 6 sidebarBadgeLabel.textColor = .white sidebarBadgeLabel.alignment = .center sidebarBadgeLabel.font = NSFont.systemFont(ofSize: 10) sidebarCell?.addSubview(sidebarBadgeLabel) sidebarBadgeLabel.tag = 102 sidebarBadgeLabel.snp.makeConstraints { make in make.leading.equalTo(sidebarTextLabel.snp.trailing).offset(8) make.centerY.equalTo(sidebarTextLabel.snp.centerY)//对齐文字 make.width.greaterThanOrEqualTo(16) make.height.equalTo(16) } } if let sidebarImageView = sidebarCell?.viewWithTag(100) as? NSImageView { sidebarImageView.image = sidebarItem.iconImage } if let sidebarTextLabel = sidebarCell?.viewWithTag(101) as? NSTextField { sidebarTextLabel.stringValue = sidebarItem.title } if let sidebarBadgeLabel = sidebarCell?.viewWithTag(102) as? NSTextField { if sidebarItem.showsBadge, let unreadCount = sidebarItem.unreadCount, unreadCount > 0 { sidebarBadgeLabel.isHidden = false if unreadCount >= 99 { sidebarBadgeLabel.stringValue = "\(unreadCount)+" }else{ sidebarBadgeLabel.stringValue = "\(unreadCount)" } } else { sidebarBadgeLabel.isHidden = true } } return sidebarCell } // 缩进 func outlineView(_ outlineView: NSOutlineView, indentationForItem item: Any?) -> CGFloat { return 0 } func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool { guard let sidebarItem = item as? SidebarItem else { return true } // My Alerts / Shared Alerts 这类分组节点不可选中 if let parent = outlineView.parent(forItem: sidebarItem) as? SidebarItem, parent.title == "Custom Alerts", sidebarItem.children?.isEmpty == false { return false } // Custom Alerts 主节点和 alert name 子节点都可以选中 return true } func outlineViewSelectionDidChange(_ notification: Notification) { let selectedRow = eventCenterSidebarOutlineView.selectedRow guard selectedRow >= 0, let selectedItem = eventCenterSidebarOutlineView.item(atRow: selectedRow) as? SidebarItem else { return } for i in 0..<eventCenterSidebarOutlineView.numberOfRows { guard let cell = eventCenterSidebarOutlineView.view(atColumn: 0, row: i, makeIfNecessary: false) as? NSTableCellView, let sidebarItem = eventCenterSidebarOutlineView.item(atRow: i) as? SidebarItem, let titleLabel = cell.viewWithTag(101) as? NSTextField, let iconView = cell.viewWithTag(100) as? NSImageView else { continue } var shouldHighlight = false // Events / Device Alerts 高亮 if sidebarItem == selectedItem && (sidebarItem.title == "Events" || sidebarItem.title == "Device Alerts") { shouldHighlight = true } // Custom Alerts 主节点 + 子节点高亮 if sidebarItem.title == "Custom Alerts" { if selectedItem.title == "Custom Alerts" { shouldHighlight = true } else if let parent = eventCenterSidebarOutlineView.parent(forItem: selectedItem) as? SidebarItem, parent.title == "Custom Alerts", (sidebarItem == parent || sidebarItem == selectedItem) { shouldHighlight = true } } // 更新视觉效果 if shouldHighlight { cell.wantsLayer = true cell.layer?.backgroundColor = NSColor.tpTextHover.cgColor titleLabel.textColor = NSColor.tpStatusGreen iconView.image = .sidebarChoosedButton } else { cell.layer?.backgroundColor = NSColor.clear.cgColor titleLabel.textColor = NSColor.tpTextWhite iconView.image = sidebarItem.iconImage } } } // 切换右侧视图 private func switchRightView(to newView: NSView) { [eventController.view, customAlertController.view, deviceAlertController.view].forEach { $0.isHidden = $0 != newView } } @objc func handleSidebarClick() { let row = eventCenterSidebarOutlineView.clickedRow guard row >= 0, let item = eventCenterSidebarOutlineView.item(atRow: row) as? SidebarItem else { return } switch item.title { case "Events": switchRightView(to: eventController.view) collapseCustomAlertsIfNeeded() case "Device Alerts": switchRightView(to: deviceAlertController.view) collapseCustomAlertsIfNeeded() case "Custom Alerts": // 点击主节点才折叠/展开 if eventCenterSidebarOutlineView.isItemExpanded(item) { eventCenterSidebarOutlineView.collapseItem(item, collapseChildren: true) } else { eventCenterSidebarOutlineView.expandItem(item, expandChildren: true) } switchRightView(to: customAlertController.view) default: // 点击 alert 子节点 if let parent = eventCenterSidebarOutlineView.parent(forItem: item) as? SidebarItem, parent.title == "Custom Alerts" { //switchRightView(to: customAlertController.view) // 不折叠父节点 } } // 统一通过 selectRowIndexes 更新选中 if outlineView(eventCenterSidebarOutlineView, shouldSelectItem: item) { eventCenterSidebarOutlineView.selectRowIndexes(IndexSet(integer: row), byExtendingSelection: false) // 触发高亮刷新 outlineViewSelectionDidChange(Notification(name: NSOutlineView.selectionDidChangeNotification)) } } private func collapseCustomAlertsIfNeeded() { if let customAlertsItem = sidebarItems.first(where: { $0.title == "Custom Alerts" }) { eventCenterSidebarOutlineView.collapseItem(customAlertsItem, collapseChildren: true) } } }
10-11
好的,下面是一个从零开始、不使用 Storyboard 或默认的 `ViewController` 的 Swift macOS 项目中,全新创建一个 `NSViewController` 子类,并在其中使用 `WKWebView` 加载网页(例如百度)的完整示例。 --- ### ✅ 步骤一:创建新项目 1. 打开 Xcode。 2. 创建一个新的 macOS App 项目: - Product Name: 比如 `WebViewDemo` - Interface: **None**(因为我们不使用 Storyboard) - Language: **Swift** --- ### ✅ 步骤二:创建新的 NSViewController 子类 1. 新建文件: - File > New > File... - 选择 macOS > Cocoa Class - Class 名为 `WebViewController` - Subclass of: `NSViewController` - 点击 Create 2. 编辑 `WebViewController.swift` 内容如下: ```swift import Cocoa import WebKit class WebViewController: NSViewController { private var webView = WKWebView() override func loadView() { // 设置 view 为 WKWebView 实例 self.view = NSView() view.wantsLayer = true view.layer?.backgroundColor = NSColor.systemBackground.cgColor // 初始化并设置 WKWebView webView.frame = view.bounds webView.autoresizingMask = [.width, .height] webView.navigationDelegate = self // 添加viewview.addSubview(webView) // 加载网页 if let url = URL(string: "https://www.baidu.com") { let request = URLRequest(url: url) webView.load(request) } } override func viewDidLoad() { super.viewDidLoad() // 可选:处理其他视图加载逻辑 } } ``` --- ### ✅ 步骤三:修改 AppDelegate 以显示这个控制器 打开 `AppDelegate.swift`,替换其内容为以下代码: ```swift import Cocoa import WebKit @main class AppDelegate: NSObject, NSApplicationDelegate { var window: NSWindow! func applicationDidFinishLaunching(_ aNotification: Notification) { // 创建窗口 window = NSWindow( contentRect: NSRect(x: 0, y: 0, width: 800, height: 600), styleMask: [.titled, .closable, .miniaturizable, .resizable], backing: .buffered, defer: false ) window.center() window.title = "WebView Demo" window.isReleasedWhenClosed = false // 创建并设置控制器 let viewController = WebViewController() let contentView = viewController.view! contentView.frame = window.contentView!.bounds window.contentView = contentView // 显示窗口 window.makeKeyAndOrderFront(nil) } func applicationWillTerminate(_ aNotification: Notification) { // 插入代码在此处执行应用终止前的操作 } } ``` --- ### ✅ 运行项目 点击运行按钮(或按 ⌘R),你将看到一个全新的 macOS 应用程序窗口,内部展示的是百度网页! --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值