push pop 和 present dismiss

push/pop 和 present/dismiss

文章目錄

  • push/pop 和 present/dismiss
  • 前言
  • push / pop
  • present
    • 普通的present
    • 多層present
      • 多層present后的父子關系問題
      • 多層彈出會遇到的問題
    • showViewController 和 showDetailViewController
      • showViewController
      • showDetailViewController
  • dismiss
  • 模態化

前言

之前曾經在網易云仿寫總結中,使用過present制作抽屜視圖的展示,在這里再次詳細對比一下push和present的區別

想象一下你正在看一本書,隨著你讀書的進度不斷增加,你的頁數也越來越多,這就是導航欄帶來的逐層深入。

突然,你需要查一個重要的詞語解釋。你會從桌上拿起一本字典,把它放在你正在看的書頁上,然后開始查找。這本字典就是你的模態視圖,它暫時遮住了你正在看的書頁(在iOS13之后,present出的頁面的模態樣式變為了UIModelPresentationAutomatic,新的頁面將不再完全覆蓋之前的頁面,而只會部分遮擋,并且允許你向下拖動關閉)

push / pop

push的操作必須在一個UINavigationController的上下文中進行,導航控制器會維護一個棧,當push后,一個新的view會被壓入到棧頂,同時導航控制器會自動添加一個按鈕用于返回

因為push的彈出新界面是由于視圖棧的頂部有更換,所以你對視圖的添加和刪除要完全符合棧的操作

你可以pop到指定視圖,蘋果也提供了相關方法(實際上用戶只要長按返回按鈕就可以返回到之前的指定頁面)

請添加圖片描述

popToViewController:animated: pop到指定的界面

popToRootViewControllerAnimated: 一直pop到根視圖停止

但是你無法只刪除棧中的某一頁面

在pop時,對應的新視圖會先調用viewDidLoad 方法,然后是viewWillAppear 最后是viewDidAppear

present

普通的present

從iOS13開始,present為了適配卡片風格展示,模態默認樣式變為UIModelpresentationAutomatic 新的視圖為部分覆蓋

present本質是在新的視圖上重新呈現了一個視圖,當前的視圖只能通過自己dismiss來返回原來的視圖,同時,新舊視圖之間是有層級關系的

源碼:

// The view controller that was presented by this view controller or its nearest ancestor.
@property(nullable, nonatomic,readonly) UIViewController *presentedViewController  API_AVAILABLE(ios(5.0));// The view controller that presented this view controller (or its farthest ancestor.)
@property(nullable, nonatomic,readonly) UIViewController *presentingViewController API_AVAILABLE(ios(5.0));

可以看出,兩個屬性都沒有加入內存類的屬性關鍵字,所以都為strong強引用

所以在present視圖之后,父視圖和子視圖會形成循環強引用,只有在新的視圖被dismiss之后,才會斷開循環引用

- (void)presentBlueBlackThenRed {UIViewController *vcBlue = [[UIViewController alloc] init];vcBlue.view.backgroundColor = [UIColor systemBlueColor];NSLog(@"準備呈現藍色視圖...");[self presentViewController:vcBlue animated:YES completion:^{UIViewController *vcBlack = [[UIViewController alloc] init];vcBlack.view.backgroundColor = [UIColor blackColor];[vcBlue presentViewController:vcBlack animated:YES completion:^{UIViewController *vcRed = [[UIViewController alloc] init];vcRed.view.backgroundColor = [UIColor systemRedColor];[vcBlack presentViewController:vcRed animated:YES completion:nil];}];}];NSLog(@"vcBlue的父視圖是否為self? %@", [vcBlue.presentingViewController isEqual:self] ? @"YES" : @"NO");NSLog(@"self的子視圖是否為vcBlue? %@", [self.presentedViewController isEqual:vcBlue] ? @"YES" : @"NO");
}

控制臺輸出!:
請添加圖片描述

多層present

在一個已經被present的視圖中再次present一個視圖,是多層的present

之前我們也講過,present的主視圖和新的視圖是強引用,所以如果過多的present視圖,可能會導致內存泄露等等問題

present出的視圖,是模態視圖,在什么時候使用模態視圖會在后面講

但是不管是什么情況,都不建議使用多層的present

多層present后的父子關系問題

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

注意看,這張圖里,VCA present了 VCB,VCB present了 VCC

并且A帶有了導航控制器

- (void)presentBlueBlackThenRed {UIViewController *vcBlue = [[UIViewController alloc] init];vcBlue.view.backgroundColor = [UIColor systemBlueColor];UINavigationController* blueNavi = [[UINavigationController alloc] initWithRootViewController:vcBlue];NSLog(@"準備呈現藍色視圖...");[self presentViewController:blueNavi animated:YES completion:^{NSLog(@"vcBlue的父視圖是否為self? %@", [vcBlue.presentingViewController isEqual:self] ? @"YES" : @"NO");NSLog(@"self的子視圖是否為vcBlue? %@", [self.presentedViewController isEqual:vcBlue] ? @"YES" : @"NO");UIViewController *vcBlack = [[UIViewController alloc] init];vcBlack.view.backgroundColor = [UIColor blackColor];[vcBlue presentViewController:vcBlack animated:YES completion:^{NSLog(@"vcBlack的父視圖是否為vcBlue? %@", [vcBlack.presentingViewController isEqual:vcBlue] ? @"YES" : @"NO");NSLog(@"vcBlack的父視圖是否為vcBlue的導航欄? %@", [vcBlack.presentingViewController isEqual:vcBlue.navigationController] ? @"YES" : @"NO");NSLog(@"vcblue的子視圖是否為vcBlack? %@", [vcBlue.presentedViewController isEqual:vcBlack] ? @"YES" : @"NO");UIViewController *vcRed = [[UIViewController alloc] init];vcRed.view.backgroundColor = [UIColor systemRedColor];[vcBlack presentViewController:vcRed animated:YES completion:^{NSLog(@"vcRed的父視圖是否為vcBlack? %@", [vcRed.presentingViewController isEqual:vcBlack] ? @"YES" : @"NO");NSLog(@"vcblack的子視圖是否為vcRed? %@", [vcBlack.presentedViewController isEqual:vcRed] ? @"YES" : @"NO");}];}];}];[vcBlue dismissViewControllerAnimated:YES completion:nil];}

請問,B的presentingView(即父視圖)是誰?

答案是A的導航控制器

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

重新閱讀presentingViewpresentedView 屬性中給到的注釋:

// The view controller that was presented by this view controller or its nearest ancestor.
// The view controller that presented this view controller (or its farthest ancestor.)

// 由該視圖控制器或其最近的祖先呈現的視圖控制器。
// 展示此視圖控制器(或其最遠祖先)的視圖控制器。

注釋中提到“or its nearest/farthest ancestor”,意思是這兩個屬性的值不一定是和彈操作直接關聯的視圖控制器

Apple官方文檔也顯示

Support for presenting view controllers is built in to the UIViewControllerclass and is available to all view controller objects. You can present any view controller from any other view controller, although UIKit might reroute the request to a different view controller.

UIViewController類中內置了對顯示視圖控制器的支持,并且適用于所有視圖控制器對象。您可以從任何其他視圖控制器呈現任何視圖控制器,盡管UIKit可能會將請求重定向到其他視圖控制器。

所以實際上你的新視圖會根據視圖的層級關系來調整到底是誰去presentingView,誰來當新視圖的presentingView

有的博客提到了UIKit會根據你的新頁面的彈出方式來判斷誰去當presentingView,即如果是全屏,UIKit會尋找父視圖上是全屏的VC作為新視圖的presentingView,但是我這里敲過例子后發現不會,并且即使設置了definesPresentationContext,視圖層級也不會變化

- (void)presentBlueBlackThenRed {UIViewController *vcBlue = [[UIViewController alloc] init];vcBlue.view.backgroundColor = [UIColor systemBlueColor];UINavigationController* blueNavi = [[UINavigationController alloc] initWithRootViewController:vcBlue];NSLog(@"準備呈現藍色視圖...");// 推出導航控制器來讓blue有自己的導航控制器,測試是否會由于導航控制器影響子視圖的presentingView[self presentViewController:blueNavi animated:YES completion:^{NSLog(@"vcBlue的父視圖是否為self? %@", [vcBlue.presentingViewController isEqual:self] ? @"YES" : @"NO");NSLog(@"self的子視圖是否為vcBlue? %@", [self.presentedViewController isEqual:vcBlue] ? @"YES" : @"NO");UIViewController *vcBlack = [[UIViewController alloc] init];vcBlack.view.backgroundColor = [UIColor blackColor];// 這里進行修改// vcBlue.definesPresentationContext = YES;vcBlack.modalPresentationStyle = UIModalPresentationFullScreen;[vcBlue presentViewController:vcBlack animated:YES completion:^{NSLog(@"vcBlack的父視圖是否為vcBlue? %@", [vcBlack.presentingViewController isEqual:vcBlue] ? @"YES" : @"NO");NSLog(@"vcBlack的父視圖是否為vcBlue的導航欄? %@", [vcBlack.presentingViewController isEqual:vcBlue.navigationController] ? @"YES" : @"NO");NSLog(@"vcblue的子視圖是否為vcBlack? %@", [vcBlue.presentedViewController isEqual:vcBlack] ? @"YES" : @"NO");UIViewController *vcRed = [[UIViewController alloc] init];vcRed.view.backgroundColor = [UIColor systemRedColor];[vcBlack presentViewController:vcRed animated:YES completion:^{NSLog(@"vcRed的父視圖是否為vcBlack? %@", [vcRed.presentingViewController isEqual:vcBlack] ? @"YES" : @"NO");NSLog(@"vcblack的子視圖是否為vcRed? %@", [vcBlack.presentedViewController isEqual:vcRed] ? @"YES" : @"NO");//                NSLog(@"推出");
//                [vcRed dismissViewControllerAnimated:YES completion:nil];
//                [vcRed.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];}];}];}];//    [vcBlue dismissViewControllerAnimated:YES completion:nil];}

這里我使用了全屏展示的樣式,但是vcBlack的presentingView還是vcBlue

之后在設置definesPresentationContext屬性為YES,并加入導航控制器后,vcBlack的presentingView也沒有變為vcBlue,而是重新定位到了vcBlue的導航控制器上

這個地方確實找不到其他的博客了,所以我先放在這里,期望會的大佬幫忙解答一下,感謝!

多層彈出會遇到的問題

還是剛剛的例子

在A視圖推出B視圖,如果想呈現C視圖,應該使用B視圖來推出對吧

但是如果我使用A視圖推出會發生什么呢?

- (void)presentBlueBlackThenRed {UIViewController *vcBlue = [[UIViewController alloc] init];vcBlue.view.backgroundColor = [UIColor systemBlueColor];UINavigationController* blueNavi = [[UINavigationController alloc] initWithRootViewController:vcBlue];NSLog(@"準備呈現藍色視圖...");// 推出導航控制器來讓blue有自己的導航控制器,測試是否會由于導航控制器影響子視圖的presentingView[self presentViewController:blueNavi animated:YES completion:^{NSLog(@"vcBlue的父視圖是否為self? %@", [vcBlue.presentingViewController isEqual:self] ? @"YES" : @"NO");NSLog(@"self的子視圖是否為vcBlue? %@", [self.presentedViewController isEqual:vcBlue] ? @"YES" : @"NO");UIViewController *vcBlack = [[UIViewController alloc] init];vcBlack.view.backgroundColor = [UIColor blackColor];// 這里進行修改vcBlue.definesPresentationContext = YES;
//        vcBlack.modalPresentationStyle = UIModalPresentationFullScreen;[vcBlue presentViewController:vcBlack animated:YES completion:^{NSLog(@"vcBlack的父視圖是否為vcBlue? %@", [vcBlack.presentingViewController isEqual:vcBlue] ? @"YES" : @"NO");NSLog(@"vcBlack的父視圖是否為vcBlue的導航欄? %@", [vcBlack.presentingViewController isEqual:vcBlue.navigationController] ? @"YES" : @"NO");NSLog(@"vcblue的子視圖是否為vcBlack? %@", [vcBlue.presentedViewController isEqual:vcBlack] ? @"YES" : @"NO");UIViewController *vcRed = [[UIViewController alloc] init];vcRed.view.backgroundColor = [UIColor systemRedColor];vcRed.modalPresentationStyle = UIModalPresentationFullScreen;[vcBlue presentViewController:vcRed animated:YES completion:^{NSLog(@"vcRed的父視圖是否為vcBlack? %@", [vcRed.presentingViewController isEqual:vcBlack] ? @"YES" : @"NO");NSLog(@"vcblack的子視圖是否為vcRed? %@", [vcBlack.presentedViewController isEqual:vcRed] ? @"YES" : @"NO");//                NSLog(@"推出");
//                [vcRed dismissViewControllerAnimated:YES completion:nil];
//                [vcRed.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];}];}];}];//    [vcBlue dismissViewControllerAnimated:YES completion:nil];}

控制臺輸出

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

并且紅色視圖不會被彈出

外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳

使用present去彈模態視圖的時候,只能用最頂層的的控制器去彈,用底層的控制器去彈會失敗,并拋出警告

(當然是有邪修方法的)

如果一個viewController的view還沒被添加到視圖樹(父視圖)上,那么用這個viewController去present會失敗,并拋出警告。

如果你非要這么寫的話,可以把present的部分放到-viewDidAppear方法中,因為-viewDidAppear被調用時self.view已經被添加到視圖樹中了(強烈不推薦)

正確的做法應該是使用childViewController,你可以用添加子視圖、子控制器的方式來實現類似效果

- (void)viewDidLoad {[super viewDidLoad];_BViewController = [[UIViewController alloc] init];_BViewController.view.frame = self.view.bounds;[self.view addSubview:_BViewController.view];[self addChildViewController:_BViewController];  //這句話一定要加,否則視圖上的按鈕事件可能不響應
}

showViewController 和 showDetailViewController

在閱讀蘋果的《Presenting a View Controller》時,找到了這兩個方法,在這里進行簡單的區分

showViewController

showViewController:sender: 這個方法,可以說是 UIKit 框架為了適應不同尺寸屏幕(尤其是為了 iPad)而設計的一個“智能”導航方法,它和 presentViewController: 的區別,就像是智能導航指定路線的區別

presentViewController: 這個方法就是在對系統下達死命令,不管怎么樣,你的視圖必須以模態視圖的方法彈出,它的行為是固定的,結果是可預期的

showViewController:sender: 這個方法不是在下達死命令,而是在向系統闡述一個需求:我希望把這個視圖控制器展示給用戶,請你根據當前的環境,用最合適的方式把它顯示出來

這個“當前的環境”是什么呢?主要是指當前的視圖控制器層級

  • 如果當前 VC 在 UINavigationController 里:系統會認為“最合適”的方式是 push。所以 showViewController: 的效果就等同于 [self.navigationController pushViewController:vc animated:YES]
  • 如果當前 VC 不在 UINavigationController 里:系統找不到可以 push 的“軌道”,就會認為“最合適”的方式是 present。所以 showViewController: 的效果就等同于 [self presentViewController:vc animated:YES completion:nil]
  • 在 iPad 的 SplitViewController 環境下:情況會更復雜。如果你的 App 在分屏模式下運行,showViewController: 可能會在一個窗格里 push 一個視圖,也可能會在另一個窗格里 present一個視圖,完全取決于 Split View Controller 的當前狀態和結構。它會自動適應,選擇最符合 iPadOS 人機交互規范的方式

showDetailViewController

showDetailViewController: 是一個**專門用于“主從式”界面的、目的性更強的“智能導航”,**它的用處,幾乎完全綁定在 UISplitViewController 這種視圖容器上

它所表達的意思就是,把這個視圖控制器,顯示在‘詳情’區域!

這個基本上只用于ipad,所以這里就不展開描述了,只做了解即可

dismiss

首先需要明確一個事情,A彈出B,然后在B中執行dismissViewControllerAnimated:completion: 這個很常見的流程實際上是錯的

之所以我們可以這么做,實際上是因為UIKit會幫我們自動通知父視圖dismiss

一般,大家也都是這么用的,A彈B,B中調用dismiss消失彈框。沒問題。

那,A彈B,我在A中調用dismiss可以嗎?——也沒問題,B會消失。

那,A彈B,B彈C。A調用dismiss,會有什么樣的結果?是C消失,還是B、C都消失,還是會報錯? ——正確答案是B、C都消失

如果B掉dismiss呢?B會消失嗎?——答案是:只有C會消失,B不會消失

還是上面的代碼

- (void)presentBlueBlackThenRed {UIViewController *vcBlue = [[UIViewController alloc] init];vcBlue.view.backgroundColor = [UIColor systemBlueColor];UINavigationController* blueNavi = [[UINavigationController alloc] initWithRootViewController:vcBlue];NSLog(@"準備呈現藍色視圖...");// 推出導航控制器來讓blue有自己的導航控制器,測試是否會由于導航控制器影響子視圖的presentingView[self presentViewController:blueNavi animated:YES completion:^{NSLog(@"vcBlue的父視圖是否為self? %@", [vcBlue.presentingViewController isEqual:self] ? @"YES" : @"NO");NSLog(@"self的子視圖是否為vcBlue? %@", [self.presentedViewController isEqual:vcBlue] ? @"YES" : @"NO");UIViewController *vcBlack = [[UIViewController alloc] init];vcBlack.view.backgroundColor = [UIColor blackColor];// 這里進行修改
//        vcBlue.definesPresentationContext = YES;
//        vcBlack.modalPresentationStyle = UIModalPresentationFullScreen;[vcBlue presentViewController:vcBlack animated:YES completion:^{NSLog(@"vcBlack的父視圖是否為vcBlue? %@", [vcBlack.presentingViewController isEqual:vcBlue] ? @"YES" : @"NO");NSLog(@"vcBlack的父視圖是否為vcBlue的導航欄? %@", [vcBlack.presentingViewController isEqual:vcBlue.navigationController] ? @"YES" : @"NO");NSLog(@"vcblue的子視圖是否為vcBlack? %@", [vcBlue.presentedViewController isEqual:vcBlack] ? @"YES" : @"NO");UIViewController *vcRed = [[UIViewController alloc] init];vcRed.view.backgroundColor = [UIColor systemRedColor];vcRed.modalPresentationStyle = UIModalPresentationFullScreen;[vcBlack presentViewController:vcRed animated:YES completion:^{NSLog(@"vcRed的父視圖是否為vcBlack? %@", [vcRed.presentingViewController isEqual:vcBlack] ? @"YES" : @"NO");NSLog(@"vcblack的子視圖是否為vcRed? %@", [vcBlack.presentedViewController isEqual:vcRed] ? @"YES" : @"NO");NSLog(@"推出");
//                [vcRed dismissViewControllerAnimated:YES completion:nil];[vcRed.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];}];}];}];//    [vcBlue dismissViewControllerAnimated:YES completion:nil];}

我在彈出vcRed之后,用vcRed的presentingViewController的presentingViewController來進行dismiss操作

vcRed的presentingViewController是vcBlack,vcBlack的presentingViewController是vcBlue的導航控制器

按照理論來說,我們這里應該彈出全部的視圖,也就是整個頁面應該回到白色

但實際上:

在這里插入圖片描述

可以觀察到藍色視圖并沒有彈出

閱讀官方文檔關于這個方法的解釋:

To dismiss a presented view controller, call the dismissViewControllerAnimated:completion: method of the presenting view controller. You can also call this method on the presented view controller itself. When you call the method on the presented view controller, UIKit automatically forwards the request to the presenting view controller.

文檔指出

1. 父節點負責調用dismiss來關閉他彈出來的子節點,你也可以直接在子節點中調用dismiss方法,UIKit會通知父節點去處理

2. 如果你連續彈出多個節點,應當由最底層的父節點調用dismiss來一次性關閉所有子節點;如果中間節點調dismiss,中間節點上面的節點都會消失,但中間幾點本身并不會消失,這里要注意

3. 關閉多個子節點時,只有最頂層的子節點會有動畫效果,下層的子節點會直接被移除,不會有動畫效果

模態化

模態化是一種在單獨的專用模式中呈現內容的設計技術,這種模式可阻止與父視圖交互且需要進行確切的操作來關閉

以模態化方式呈現內容可以:

  • 確保用戶接收關鍵信息,并在必要時對其進行操作
  • 提供選項以讓用戶確認或修改其最近的操作
  • 幫助用戶執行明確的小范圍任務,同時不會忘記其之前的環境
  • 向用戶提供沉浸式體驗,或幫助其專注于復雜任務

使用場景:

僅在必要時使用模態化。模態體驗打斷用戶當前流程且需要額外操作關閉,因此只在需要用戶專注或做出重要選擇時使用

保持模態任務簡短。復雜的模態任務可能導致用戶忘記原任務,尤其是當模態視圖完全覆蓋原界面時

避免"App中的App"體驗。若模態任務需要子視圖,提供單一導航路徑,避免使用可能被誤認為關閉按鈕的元素

復雜任務用全屏模態。全屏模態減少干擾,適用于視頻、照片、相機或多步驟任務。

提供明顯的關閉方式。遵循平臺慣例:iOS/iPadOS/watchOS上通常在頂部工具欄或下滑手勢,macOS和tvOS則在主視圖中

關閉前避免數據丟失。若關閉可能丟失用戶內容,提供解釋和解決方案,如iOS中的存儲選項操作表單

任務目的要清晰。提供清晰標題或描述,幫助用戶理解當前位置和任務目標

避免同時展示多個模態視圖。多模態視圖會造成視覺混亂和認知負擔,尤其是模態視圖疊加時。提醒雖可顯示在其他內容之上,但不應同時顯示多個

參考文獻:

  1. https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/PresentingaViewController.html#//apple_ref/doc/uid/TP40007457-CH14-SW1
  2. https://developer.apple.com/cn/design/human-interface-guidelines/modality
  3. https://www.jianshu.com/p/dd6180bc340a
  4. https://juejin.cn/post/6844903708799533063#heading-4

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:
http://www.pswp.cn/pingmian/95953.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/95953.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/95953.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

服務器異常負載排查手冊 · 隱蔽進程篇

適用范圍 適用于 Linux 3.10 生產環境,發現 load 高但用戶態 CPU 接近 0 % 的場景。1. 現場凍結目標:在 rootkit 干預前保存易失數據。#!/bin/bash # freeze.sh TS$(date %s) mkdir -p /srv/ir/${TS} cd /srv/ir/${TS}# 1.1 進程樹(busybox 靜…

2024理想算法崗筆試筆記

要理解指令微調(Instruction Tuning),需要先將其置于大語言模型(LLM)的訓練框架中 —— 它并非模型訓練的起點,而是針對 “讓模型更懂人類需求” 的關鍵優化步驟。簡單來說,指令微調是通過讓模型…

Oracle 11g離線安裝依賴包完整解決方案

本文還有配套的精品資源,點擊獲取 簡介:Oracle 11g是一款廣泛使用的關系型數據庫管理系統,在離線環境下安裝時需依賴多個系統庫和工具。本“oracle11g依賴包”壓縮文件包含了在CentOS 7.7上安裝Oracle 11g可能缺失的關鍵依賴RPM包&#xf…

VBA數據結構選型:效率差5倍的生死抉擇

VBA性能生死局:Dictionary與Collection效率差5倍!90%開發者用反血虧“你以為Collection是VBA的‘輕量級選手’?大錯特錯!實測數據顯示:在10萬級數據循環中,Dictionary的查詢速度比Collection快5倍&#xff…

電機控制(四)-級聯PID控制器與參數整定(MATLABSimulink)

PID算法 普通PID(Proportional-Integral-Derivative) 通過比例(P)、積分(I)和微分(D)三項來進行控制 比例項(P):根據當前誤差(目標值…

數據結構深度解析:二叉樹的基本原理

在數據結構體系中,樹是一種重要的非線性層次結構,它通過 “節點” 與 “邊” 的連接關系,模擬了現實世界中樹的分支結構,能夠高效地解決數據的查找、插入、刪除等問題。而二叉樹作為樹結構中最簡單、應用最廣泛的類型,…

【React】Ant Design 5.x 實現tabs圓角及反圓角效果

需要實現的效果實現思路 利用tab頁的before和after屬性&#xff0c;添加tab頁前后的圓弧屬性&#xff0c;同時使用tab頁的shadow陰影填充右下角的圓弧空缺部分。<TabsonChange{onChange}type"card"items{getTabItems()}/>.ant-tabs-nav{margin: 0;.ant-tabs-na…

WordPress過濾文章插入鏈接rel屬性noopener noreferrer值

WordPress過濾文章插入鏈接rel屬性noopener noreferrer值在保存文章的時候&#xff0c;WordPress會自動過濾文章內容中的鏈接&#xff0c;具有target屬性的鏈接會自動添加rel"noopener noreferrer"&#xff0c;該屬性是為了預防跨站攻擊&#xff0c;站內鏈接似乎沒有…

make_shared的使用

目錄 1. make_shared 的基本概念 基本用法 2. 引入 make_shared 的主要原因 2.1 解決傳統構造方式的問題 2.2 標準委員會的動機 3. make_shared 的核心優勢 3.1 性能優勢&#xff08;最重要優點&#xff09; 內存分配優化&#xff1a; 性能提升表現&#xff1a; 3.2 異…

基于 Gemini 的 CI/CD 自動化測評 API 集成實戰教程

在現代軟件開發中&#xff0c;CI/CD 集成 已經成為必不可少的流程。它不僅能幫助團隊快速迭代&#xff0c;還能通過自動化手段提升代碼質量。而在編程培訓和團隊內部學習中&#xff0c;如何引入 自動化測評 API&#xff0c;實現提交即測評、即時反饋呢&#xff1f;本文將以 Gem…

SOME/IP-SD(Service Discovery)協議的核心協議

<摘要> 本解析以AutoSAR AP R22-11版本為基準&#xff0c;全面系統地闡述了SOME/IP-SD&#xff08;Service Discovery&#xff09;協議的核心內容。從車載網絡演進背景切入&#xff0c;詳細剖析了面向服務架構&#xff08;SOA&#xff09;下服務發現的必要性&#xff0c;…

視頻串行解串器(SerDes)介紹

視頻串行解串器&#xff08;SerDes&#xff09;是高速數據通信中的核心接口技術&#xff0c;通過串行化與解串行化實現視頻信號的高效傳輸&#xff0c;廣泛應用于汽車電子、數據中心、高清視頻傳輸等領域。 一、技術原理串行化&#xff08;Serializer&#xff09; 功能&#xf…

哈士奇vs網易高級數倉:數據倉庫的靈魂是模型、數據質量還是計算速度?| 易錯題

面試場景 面試官: (微笑,營造輕松但專業的氛圍)嗨,哈士奇,歡迎來參加網易的二面。我看你簡歷上數據倉庫的項目經驗很豐富,我們今天就深入聊聊。我這里有一個經典的問題想聽聽你的看法:在你看來,數據倉庫的靈魂是模型、數據質量還是計算速度? 哈士奇: (不假思索,…

貪心算法應用:3D打印支撐結構問題詳解

Java中的貪心算法應用&#xff1a;3D打印支撐結構問題詳解 1. 問題背景與概述 1.1 3D打印中的支撐結構問題 在3D打印過程中&#xff0c;當模型存在懸空部分&#xff08;overhang&#xff09;時&#xff0c;通常需要添加支撐結構&#xff08;support structure&#xff09;來防止…

Python爬蟲實戰:研究3D plotting模塊,構建房地產二手房數據采集和分析系統

1. 引言 1.1 研究背景 在大數據與人工智能技術快速發展的背景下,數據已成為驅動決策的核心要素。互聯網作為全球最大的信息載體,蘊含海量結構化與非結構化數據,如何高效提取并分析這些數據成為學術界與產業界的研究熱點。 網絡爬蟲技術通過自動化請求與解析網頁,實現數據…

Gradio全解10——Streaming:流式傳輸的音頻應用(7)——ElevenLabs:高級智能語音技術

Gradio全解10——Streaming&#xff1a;流式傳輸的音頻應用&#xff08;7&#xff09;——ElevenLabs&#xff1a;高級智能語音技術10.7 ElevenLabs&#xff1a;高級智能語音技術10.7.1 核心功能與可用模型1. 核心功能與產品2. 三類語音模型10.7.2 文本轉語音API1. 完整操作步驟…

【桃子同學筆記4】PCIE訓練狀態機(LTSSM)基礎

首先&#xff0c;所謂LTSSM&#xff0c;即&#xff1a;Link Training and Status State Machine&#xff08;鏈路訓練及狀態機&#xff09; 下圖為 LTSSM 的狀態機及訓練過程&#xff1a; LTSSM 包含 11 個頂層狀態&#xff1a;Detect、Polling、Configuration、Recovery、L0、…

STM32傳感器模塊編程實踐(十五)DIY語音對話控制+滿溢檢測智能垃圾桶模型

文章目錄 一.概要二.實驗模型原理1.硬件連接原理框圖2.控制原理 三.實驗模型控制流程四.語音控制垃圾桶模型程序五.實驗效果視頻六.小結 一.概要 以前介紹的智能垃圾桶模型都是通過超聲波模塊感知控制&#xff0c;這次介紹一款新的智能垃圾桶&#xff0c;直接使用語音交互模塊…

[bat-cli] docs | 控制器

鏈接&#xff1a;https://github.com/sharkdp/bat 前文傳送&#xff1a; 【探索Linux命令行】從基礎指令到高級管道操作的介紹與實踐【Linux命令行】從時間管理-&#xff1e;文件查找壓縮的指令詳解【Linux】1w詳解如何實現一個簡單的shell docs&#xff1a;bat bat 是一個*…

無線自動信道調整

通過信道調整功能&#xff0c;可以保證每個AP 能夠分配到最優的信道&#xff0c;盡可能地 減少和避免相鄰信道干擾&#xff0c;而且通過實時信道檢測&#xff0c;使AP 實時避開雷達&#xff0c;微波爐等干擾源。 動態信道調整能夠實現通信的持續進行&#xff0c;為網絡的可靠傳…