diff --git a/App/Tabs/Tab.swift b/App/Tabs/Tab.swift index 63aade9..d048c1d 100644 --- a/App/Tabs/Tab.swift +++ b/App/Tabs/Tab.swift @@ -19,7 +19,6 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate public var tabInfo: TabInfo { get { - updateMetadata() return _tabInfo } } @@ -39,18 +38,14 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate } public var policyManager: ResourcePolicyManager - private var _tabInfo: TabInfo = TabInfo() + // Persisted snapshot of visible tab metadata; do not recompute on read. + var _tabInfo: TabInfo = TabInfo() private var loadedWebView: WKWebView? = nil public var title: String? { get { tabInfo.title } } public var url: URL? { - get { - if let urlString = tabInfo.urlString { - return URL(string: urlString) - } - - return nil - } + if let urlString = tabInfo.urlString { return URL(string: urlString) } + return nil } public var javaScriptEnabled: Bool = false { @@ -110,6 +105,10 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate super.init() bridge.delegate = self + + // Initialize snapshot metadata + _tabInfo.identifier = self.identifier + if let url { _tabInfo.urlString = url.absoluteString } } deinit { @@ -117,6 +116,8 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate } func beginLoadingURL(_ url: URL) { + // Update snapshot immediately so UI keeps URL even if process jettisons. + _tabInfo.urlString = url.absoluteString let request = URLRequest(url: url) webView.load(request) } @@ -150,15 +151,4 @@ class Tab: NSObject, SBRProcessBundleBridgeDelegate .assign(to: \.favicon, on: self) } } - - private func updateMetadata() { - guard contentProcessTerminated == false else { return } - - _tabInfo = TabInfo( - title: loadedWebView?.title, - urlString: loadedWebView?.url?.absoluteString ?? self.homeURL?.absoluteString, - faviconData: self.favicon?.pngData(), - identifier: self.identifier - ) - } } diff --git a/App/Tabs/TabController.swift b/App/Tabs/TabController.swift index 4259646..66112a7 100644 --- a/App/Tabs/TabController.swift +++ b/App/Tabs/TabController.swift @@ -49,16 +49,28 @@ class TabController tabs.append(tab) } - // Title observation + // Title observation: update snapshot and notify delegate. tab.titleObservation = tab.webView.observe(\.title, changeHandler: { [weak tab, weak self] (webView, change) in - if let tab = tab, let self = self, let delegate = self.controllerDelegate { + guard let tab = tab else { return } + if let newTitle = webView.title, !newTitle.isEmpty { + tab._tabInfo.title = newTitle + } + if let self = self, let delegate = self.controllerDelegate { delegate.tabController(self, didUpdateTitle: webView.title ?? "", forTab: tab) } }) + + // URL observation: persist the latest URL in the snapshot. + tab.urlObservation = tab.webView.observe(\.url, changeHandler: { [weak tab] (webView, change) in + guard let tab = tab else { return } + tab._tabInfo.urlString = webView.url?.absoluteString ?? tab._tabInfo.urlString + }) // Favicon Observation tab.faviconObservation = tab.$favicon.receive(on: RunLoop.main).sink { [weak tab, weak self] val in - if let tab = tab, let self = self, let delegate = self.controllerDelegate { + guard let tab = tab else { return } + tab._tabInfo.faviconData = val?.pngData() + if let self = self, let delegate = self.controllerDelegate { delegate.tabController(self, didUpdateFavicon: val, forTab: tab) } } diff --git a/SBrowser.xcodeproj/project.pbxproj b/SBrowser.xcodeproj/project.pbxproj index d8b9e88..50f9656 100644 --- a/SBrowser.xcodeproj/project.pbxproj +++ b/SBrowser.xcodeproj/project.pbxproj @@ -790,7 +790,7 @@ CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 6; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 3SJALV9BQ7; INFOPLIST_FILE = "App/Supporting Files/Info.plist"; @@ -801,7 +801,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.0; + MARKETING_VERSION = 4.1; PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.attractor; PRODUCT_NAME = Attractor; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -825,7 +825,7 @@ CODE_SIGN_ENTITLEMENTS = "App/Supporting Files/SBrowser.entitlements"; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 5; + CURRENT_PROJECT_VERSION = 6; DEAD_CODE_STRIPPING = YES; DEVELOPMENT_TEAM = 3SJALV9BQ7; INFOPLIST_FILE = "App/Supporting Files/Info.plist"; @@ -836,7 +836,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 4.0; + MARKETING_VERSION = 4.1; PRODUCT_BUNDLE_IDENTIFIER = net.buzzert.attractor; PRODUCT_NAME = Attractor; PROVISIONING_PROFILE_SPECIFIER = "";