OC—UI學習-2

導航控制器和導航工具欄

導航控制器

  • UINAvigationController與UIViewController的關系

UIViewController是什么?

  1. 它是一個普通的視圖控制器,負責管理一個頁面

UINavigationController是什么?

  1. 它是一個容器控制器,專門用來管理一組UIviewController的堆棧結構

UINavigationController是iOS中用于管理一系列視圖控制器(UIViewController)的容器控制器

它提供了:

  1. 層級導航:類似于網頁中的前進、后退
  2. 導航欄:頂部的標題區域,包含返回按鈕、標題、右邊的按鈕
  3. push/pop動畫

他們之間的關系

  1. UINavigationController是一個特殊的UIViewController,內部維護了一個控制器棧
  • 在創建一個UIViewController子類的時候,系統會自動聲明一個只讀的UINavigationController屬性

導航控制器:UINavigationController

導航欄:navigationBar

導航欄引入項:UINavigationItem

導航棧:viewControllers

在導航控制器中也控制一個視圖控制器,每個視圖控制器中對應一個導航引入項,導航引入項就是顯示在導航欄上的內容,包括leftBarButton(導航欄左側按鈕)、titleView(導航欄中間標題)、rightBarButton(導航欄右側按鈕)

繼承關系:NSObject -> UIrespounder -> UIViewController -> UINavigationController
請添加圖片描述

  • 管理多個視圖的控制器(UIViewController)的棧式導航

  • 提供默認的返回按鈕(Back Button )和導航欄 (UINavigationBar)

  • 初始化并設置根視圖控制器

//創建視圖控制器
VCRoot* rootVC = [[VCRoot alloc] init];
//將視圖控制器賦給導航控制器
UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:rootVC];
//將導航控制器設為窗口的根視圖控制器
self.window.rootViewController = nav;
  • push操作
// 在當前控制器中創建下一級控制器(例如:VCSecond)
VCSecond *secondVC = [[VCSecond alloc] init];
// 設置跳轉時的過渡動畫(默認 YES)
[self.navigationController pushViewController:secondVC animated:YES];
  • pop操作
    1. popViewControllerAnimated::返回上一級(當前控制器出棧)
[self.navigationController popViewControllerAnimated:YES];

? 2. popToRootViewControllerAnimated::直接返回根控制器(棧中所有中間控制器出棧)

[self.navigationController popToRootViewControllerAnimated:YES];

? 3. popToViewController:animated::返回指定的控制器(需傳入控制器實例)

VCRoot *rootVC = [self.navigationController.viewControllers firstObject];
[self.navigationController popToViewController:rootVC animated:YES];

VCRoot:

#import <UIKit/UIKit.h>NS_ASSUME_NONNULL_BEGIN@interface VCRoot : UIViewController@endNS_ASSUME_NONNULL_END
#import "VCRoot.h"
#import "VCSecond.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {/*barStyle:導航欄風格顏色barTintColor:導航欄顏色tintColor:導航欄風格顏色toolbarItems:工具欄元素數組UIBarItemFlexibleSpace:自動調整按鈕距離*/[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor yellowColor];/*設置導航欄文字內容*/self.title = @"根視圖";// 創建外觀配置UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];// 設置背景圖片UIImage *bgImage = [UIImage imageNamed:@"photo04.jpg"];appearance.backgroundImage = bgImage;// 隱藏陰影線//appearance.shadowImage = [UIImage new];//appearance.shadowColor = nil;// 應用外觀配置self.navigationController.navigationBar.standardAppearance = appearance;self.navigationController.navigationBar.scrollEdgeAppearance = appearance;//appearance.backgroundColor = [UIColor yellowColor];//appearance.shadowImage = [UIImage new];//appearance.shadowColor = nil;/*設置導航元素項的標題,它和上一條的區別是如果沒有設置navigationItem的title,為nil,系統會自動使用self.title作為標題如果兩個都為nil則沒有標題*/self.navigationItem.title = @"title";UIBarButtonItem* leftbutton = [[UIBarButtonItem alloc] initWithTitle:@"左側" style:UIBarButtonItemStyleDone target:self action:@selector(pressleft)];self.navigationItem.leftBarButtonItem = leftbutton;/*UIBarButtonItem* rightbutton = [[UIBarButtonItem alloc] initWithTitle:@"右側" style:UIBarButtonItemStyleDone target:self action:@selector(pressright)];*/UIBarButtonItem* rightbutton = [[UIBarButtonItem alloc] initWithTitle:@"進入下一級" style:UIBarButtonItemStyleDone target:self action:@selector(pressright)];self.navigationItem.rightBarButtonItem = rightbutton;UIImageView* imageview = [[UIImageView alloc] init];imageview.frame = [[UIScreen mainScreen] bounds];imageview.alpha = 1;imageview.image = [UIImage imageNamed:@"photo02.jpg"];[self.view insertSubview:imageview atIndex:0];UILabel* label = [[UILabel alloc] init];label.frame = CGRectMake(10, 10, 50, 40);label.text = @"test";label.textAlignment = NSTextAlignmentCenter;label.textColor = [UIColor blueColor];UIBarButtonItem* item3 = [[UIBarButtonItem alloc] initWithCustomView:label];NSArray* arrayofbutton = [NSArray arrayWithObjects:rightbutton,item3, nil];self.navigationItem.rightBarButtonItems = arrayofbutton;//隱藏導航欄的兩個方法self.navigationController.navigationBar.hidden = NO;//繼承與UIViewself.navigationController.navigationBarHidden = NO;//屬性}- (void)pressleft {NSLog(@"leftbutton is pressed");
}- (void)pressright {NSLog(@"rightbutton is pressed");
}

在SceneDelegate中創建根視圖與導航控制器

#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).self.window.frame = [UIScreen mainScreen].bounds;VCRoot* root = [[VCRoot alloc] init];UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:root];self.window.rootViewController = nav;[self.window makeKeyAndVisible];}- (void)sceneDidDisconnect:(UIScene *)scene {// Called as the scene is being released by the system.// This occurs shortly after the scene enters the background, or when its session is discarded.// Release any resources associated with this scene that can be re-created the next time the scene connects.// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}- (void)sceneDidBecomeActive:(UIScene *)scene {// Called when the scene has moved from an inactive state to an active state.// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}- (void)sceneWillResignActive:(UIScene *)scene {// Called when the scene will move from an active state to an inactive state.// This may occur due to temporary interruptions (ex. an incoming phone call).
}- (void)sceneWillEnterForeground:(UIScene *)scene {// Called as the scene transitions from the background to the foreground.// Use this method to undo the changes made on entering the background.
}- (void)sceneDidEnterBackground:(UIScene *)scene {// Called as the scene transitions from the foreground to the background.// Use this method to save data, release shared resources, and store enough scene-specific state information// to restore the scene back to its current state.
}@end

導航控制器切換

  • navigationBar:導航欄對象
  • navigationItem:導航元素項對象
  • translucent:導航欄透明度
  • pushViewController:推入視圖控制器
  • popViewController:彈出視圖控制器

根視圖:

#import "VCRoot.h"
#import "VCSecond.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {/*barStyle:導航欄風格顏色barTintColor:導航欄顏色tintColor:導航欄風格顏色toolbarItems:工具欄元素數組UIBarItemFlexibleSpace:自動調整按鈕距離*/[super viewDidLoad];// Do any additional setup after loading the view.self.view.backgroundColor = [UIColor yellowColor];/*設置導航欄文字內容*/self.title = @"根視圖";// 創建外觀配置UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];// 設置背景圖片UIImage *bgImage = [UIImage imageNamed:@"photo04.jpg"];appearance.backgroundImage = bgImage;// 隱藏陰影線//appearance.shadowImage = [UIImage new];//appearance.shadowColor = nil;// 應用外觀配置self.navigationController.navigationBar.standardAppearance = appearance;self.navigationController.navigationBar.scrollEdgeAppearance = appearance;//appearance.backgroundColor = [UIColor yellowColor];//appearance.shadowImage = [UIImage new];//appearance.shadowColor = nil;/*設置導航元素項的標題,它和上一條的區別是如果沒有設置navigationItem的title,為nil,系統會自動使用self.title作為標題如果兩個都為nil則沒有標題*/self.navigationItem.title = @"title";UIBarButtonItem* leftbutton = [[UIBarButtonItem alloc] initWithTitle:@"左側" style:UIBarButtonItemStyleDone target:self action:@selector(pressleft)];self.navigationItem.leftBarButtonItem = leftbutton;/*UIBarButtonItem* rightbutton = [[UIBarButtonItem alloc] initWithTitle:@"右側" style:UIBarButtonItemStyleDone target:self action:@selector(pressright)];*/UIBarButtonItem* rightbutton = [[UIBarButtonItem alloc] initWithTitle:@"進入下一級" style:UIBarButtonItemStyleDone target:self action:@selector(pressright)];self.navigationItem.rightBarButtonItem = rightbutton;UIImageView* imageview = [[UIImageView alloc] init];imageview.frame = [[UIScreen mainScreen] bounds];imageview.alpha = 1;imageview.image = [UIImage imageNamed:@"photo02.jpg"];[self.view insertSubview:imageview atIndex:0];UILabel* label = [[UILabel alloc] init];label.frame = CGRectMake(10, 10, 50, 40);label.text = @"test";label.textAlignment = NSTextAlignmentCenter;label.textColor = [UIColor blueColor];UIBarButtonItem* item3 = [[UIBarButtonItem alloc] initWithCustomView:label];NSArray* arrayofbutton = [NSArray arrayWithObjects:rightbutton,item3, nil];self.navigationItem.rightBarButtonItems = arrayofbutton;//隱藏導航欄的兩個方法self.navigationController.navigationBar.hidden = NO;//繼承與UIViewself.navigationController.navigationBarHidden = NO;//屬性 
}- (void)pressleft {NSLog(@"leftbutton is pressed");
}- (void)pressright {VCSecond* vc2 = [[VCSecond alloc] init];[self.navigationController pushViewController:vc2 animated: YES];
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

第二個視圖

#import "VCSecond.h"
#import "VCThird.h"
@interface VCSecond ()@end@implementation VCSecond- (void)viewDidLoad {[super viewDidLoad];UIImageView* imageView = [[UIImageView alloc] init];imageView.image = [UIImage imageNamed:@"photo01.jpg"];imageView.frame = [[UIScreen mainScreen] bounds];[self.view insertSubview:imageView atIndex:0];// Do any additional setup after loading the view.//默認透明度為yes:可透明的self.navigationController.navigationBar.translucent = YES;//設置導航控制欄風格,默認為Defaultself.navigationController.navigationBar.barStyle = UIBarStyleDefault;self.title = @"視圖二";self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"下一個視圖" style:UIBarButtonItemStylePlain target:self action:@selector(pressright)];self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"上一個視圖" style:UIBarButtonItemStylePlain target:self action:@selector(pressleft)];
}- (void)pressright {VCThird* vc3 = [[VCThird alloc] init];[self.navigationController pushViewController:vc3 animated:YES];
}- (void)pressleft {[self.navigationController popViewControllerAnimated:YES];
}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

第三個視圖

#import "VCThird.h"
#import "VCRoot.h"
#import "VCSecond.h"
@interface VCThird ()@end@implementation VCThird- (void)viewDidLoad {[super viewDidLoad];UIImageView* imageview = [UIImageView new];imageview.frame = [[UIScreen mainScreen] bounds];imageview.image = [UIImage imageNamed:@"photo05.jpg"];[self.view insertSubview:imageview atIndex:0];// Do any additional setup after loading the view.self.navigationItem.title = @"視圖三";self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"上一級頁面" style:UIBarButtonItemStylePlain target:self action:@selector(pressleft)];self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"回到主頁面" style:UIBarButtonItemStylePlain target:self action:@selector(pressright)];}- (void)pressleft {[self.navigationController popViewControllerAnimated:YES];
}- (void)pressright {[self.navigationController popToRootViewControllerAnimated:YES];
}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

SceneDelegate.m:

#import "SceneDelegate.h"
#import "VCRoot.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).self.window.frame = [UIScreen mainScreen].bounds;VCRoot* root = [[VCRoot alloc] init];UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:root];self.window.rootViewController = nav;[self.window makeKeyAndVisible];}- (void)sceneDidDisconnect:(UIScene *)scene {// Called as the scene is being released by the system.// This occurs shortly after the scene enters the background, or when its session is discarded.// Release any resources associated with this scene that can be re-created the next time the scene connects.// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}- (void)sceneDidBecomeActive:(UIScene *)scene {// Called when the scene has moved from an inactive state to an active state.// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}- (void)sceneWillResignActive:(UIScene *)scene {// Called when the scene will move from an active state to an inactive state.// This may occur due to temporary interruptions (ex. an incoming phone call).
}- (void)sceneWillEnterForeground:(UIScene *)scene {// Called as the scene transitions from the background to the foreground.// Use this method to undo the changes made on entering the background.
}- (void)sceneDidEnterBackground:(UIScene *)scene {// Called as the scene transitions from the foreground to the background.// Use this method to save data, release shared resources, and store enough scene-specific state information// to restore the scene back to its current state.
}@end

請添加圖片描述

請添加圖片描述

導航工具欄:

在OC中,設置導航欄的風格顏色等樣式,只要通過UINavigationBar的屬性或UINavigationBarAppearance來實現

  • barStyle:導航欄風格
  • barTintColor:導航欄顏色
  • tintColor:導航欄風格顏色
  • toolBarItems:工具欄元素數組
  • UIBarItemFlexibleSpace:自動調整距離按鈕
  1. 設置導航欄背景顏色(通過barTintColor)
// 方式 1:直接修改當前導航欄(推薦在視圖控制器中使用)
self.navigationController.navigationBar.barTintColor = [UIColor yellowColor];// 方式 2:全局設置(所有導航欄生效,推薦在 AppDelegate 中使用)
[[UINavigationBar appearance] setBarTintColor:[UIColor yellowColor]];
  1. 設置導航欄標題樣式(通過titleTextAttributes配置顏色、字體等)
// 方式 1:修改當前導航欄
NSDictionary *titleAttrs = @{NSForegroundColorAttributeName: [UIColor whiteColor],  // 標題顏色NSFontAttributeName: [UIFont boldSystemFontOfSize:18]  // 標題字體
};
[self.navigationController.navigationBar setTitleTextAttributes:titleAttrs];// 方式 2:全局設置
[[UINavigationBar appearance] setTitleTextAttributes:titleAttrs];
  1. 設置導航欄按鈕顏色(通過tintColor統一控制導航欄按鈕的顏色
// 方式 1:修改當前導航欄
self.navigationController.navigationBar.tintColor = [UIColor blueColor];// 方式 2:全局設置
[[UINavigationBar appearance] setTintColor:[UIColor blueColor]];
  1. 隱藏導航欄底部陰影線(默認存在一條分割線)
// 方式 1:使用 shadowImage
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
[self.navigationController.navigationBar setShadowImage:[UIImage new]];// 方式 2:iOS 13+ 推薦用 UINavigationBarAppearance
if (@available(iOS 13.0, *)) {UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];appearance.shadowColor = nil;  // 隱藏陰影線self.navigationController.navigationBar.standardAppearance = appearance;
}
  • UINavigationBarAppearance可更細粒度控制導航欄樣式,支持標準狀態和滾動狀態的差異化設置
  1. 全局設置(AppleDelegate中)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {if (@available(iOS 13.0, *)) {UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];// 1. 設置背景appearance.backgroundColor = [UIColor yellowColor];  // 背景色// 2. 設置標題appearance.titleTextAttributes = @{};// 3. 隱藏陰影線appearance.shadowColor = nil;// 4. 應用到所有導航欄UINavigationBar *navBar = [UINavigationBar appearance];navBar.standardAppearance = appearance;         // 標準狀態navBar.scrollEdgeAppearance = appearance;       // 滾動到頂部時的狀態}return YES;
}
  1. 局部配置
- (void)viewDidLoad {[super viewDidLoad];   if (@available(iOS 13.0, *)) {UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];appearance.backgroundColor = [UIColor orangeColor];appearance.titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor blackColor]};// 應用到當前導航欄self.navigationController.navigationBar.standardAppearance = appearance;self.navigationController.navigationBar.scrollEdgeAppearance = appearance;}
}
  1. 自定義配置
// 在 viewDidLoad 中
UIView *customTitleView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 120, 30)];// 添加標題文字
UILabel *titleLabel = [[UILabel alloc] initWithFrame:customTitleView.bounds];
titleLabel.text = @"Custom Title";
titleLabel.font = [UIFont boldSystemFontOfSize:17];
titleLabel.textAlignment = NSTextAlignmentCenter;
[customTitleView addSubview:titleLabel];// 添加標題圖片
UIImageView *titleImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 20, 20)];
titleImageView.image = [UIImage imageNamed:@"logo"];
[customTitleView addSubview:titleImageView];// 設置到導航欄
self.navigationItem.titleView = customTitleView;
  • 常見問題:

    • 導航欄顏色不生效:檢查是否開啟了半透明效果,需要關閉
    • 如何讓導航欄延伸到狀態欄?
 // 在視圖控制器中self.edgesForExtendedLayout = UIRectEdgeTop;  // 視圖延伸到導航欄下方self.extendedLayoutIncludesOpaqueBars = YES;  // 包含不透明的導航欄

self.edgesForExtendedLayout = UIRectEdgeTop;

  1. 控制視圖控制器的根視圖可以延伸到屏幕的哪些邊緣
  2. 默認是全部,如果導航欄是半透明的,會看到視圖與導航欄重合

self.extendedLayoutIncludesOpaqueBars = YES;

  1. 決定延伸布局是否包含不透明的導航欄與工具欄
  2. 默認NO:如果導航欄不透明,根視圖會從導航欄底部開始布局
#import "VCRoot.h"
#import "SecondVC.h"@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor orangeColor];self.title = @"根視圖";UIBarButtonItem *btn = [[UIBarButtonItem alloc] initWithTitle: @"右側按鈕" style: UIBarButtonItemStylePlain target: self action: nil];self.navigationItem.rightBarButtonItem = btn;//UIBarAppearance是iOS13后推出的一個對相應空間設置外觀樣式的類,可以統一配置NavigationBar、TabBar、ToolBar等的外觀樣式//UINavigationBarAppearance可以設置導航欄對象的外觀樣式//創建一個UINavigationBarAppearance對象UINavigationBarAppearance *appearance = [[UINavigationBarAppearance alloc] init];//設置該對象的背景顏色appearance.backgroundColor = [UIColor blueColor];//創建該對象的陰影圖像appearance.shadowImage = [[UIImage alloc] init];//設置該對象的陰影顏色appearance.shadowColor = nil;//設置導航欄按鈕的顏色self.navigationController.navigationBar.tintColor = [UIColor purpleColor];//設置普通樣式導航欄self.navigationController.navigationBar.standardAppearance = appearance;//設置滾動樣式導航欄self.navigationController.navigationBar.scrollEdgeAppearance = appearance;//隱藏導航欄的兩個方法//1、下面這一條的hidden是繼承于UIView的self.navigationController.navigationBar.hidden = NO;//2、下面這一條的navigationBarHidden是一個屬性self.navigationController.navigationBarHidden = NO;//顯示工具欄對象//隱藏工具欄,默認為YES:即隱藏;NO:不隱藏self.navigationController.toolbarHidden = NO;//設置工具欄是否透明,默認為YES:半透明self.navigationController.toolbar.translucent = NO;UIBarButtonItem *btn1 = [[UIBarButtonItem alloc] initWithTitle: @"left" style: UIBarButtonItemStylePlain target: nil action: nil];UIBarButtonItem *btn2 = [[UIBarButtonItem alloc] initWithTitle: @"right" style: UIBarButtonItemStylePlain target: self action: @selector(pressBack)];//設置一個自定義類型的button,使用圖片創建UIButton *btnC = [UIButton buttonWithType: UIButtonTypeCustom];[btnC setImage: [UIImage imageNamed: @"btnC.jpg"] forState: UIControlStateNormal];btnC.frame = CGRectMake(0, 0, 60, 60);UIBarButtonItem *btn3 = [[UIBarButtonItem alloc] initWithCustomView: btnC];//設置一個占位按鈕,放到數組中可以用來分隔開各按鈕//設置寬度固定的占位按鈕,注:此處方法名為UIBarButtonSystemItemFixedSpace(FixedSpace!!!!!)UIBarButtonItem *btnF1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFixedSpace target: nil action: nil];btnF1.width = 110;//設置自動計算寬度的占位按鈕,注:此處方法名為UIBarButtonSystemItemFlexibleSpace (FlexibleSpace!!!!!)UIBarButtonItem *btnF2 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: UIBarButtonSystemItemFlexibleSpace target: nil action: nil];NSArray *arrayBtn = [NSArray arrayWithObjects: btn1, btnF2, btn3, btnF2, btn2, nil];self.toolbarItems = arrayBtn;}- (void)pressBack {SecondVC *vc = [[SecondVC alloc] init];[self.navigationController pushViewController: vc animated: YES];
}/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

分欄控制器

分欄控制器是一種常用的容器視圖控制器,分欄控制器可以包含多個子視圖控制器,并通過底部的分欄菜單UIBar

進行切換

  1. 在sceneDelegate中創建子視圖控制器,同時創建分欄控制器對象,將子視圖控制器添加到分欄控制器中
#import "SceneDelegate.h"
#import "VCFirst.h"
#import "VCSecond.h"
#import "VCThird.h"
#import "VCFourth.h"
#import "VCFifth.h"
#import "VCSixth.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {//創建三個視圖控制器并更改背景顏色和標題VCFirst* vc01 = [VCFirst new];vc01.view.backgroundColor = [UIColor brownColor];vc01.title = @"視圖1";VCSecond* vc02 = [VCSecond new];vc02.view.backgroundColor = [UIColor orangeColor];vc02.title = @"試圖2";VCThird* vc03 = [VCThird new];vc03.view.backgroundColor = [UIColor yellowColor];vc03.title = @"視圖3";VCFourth* vc04 = [VCFourth new];vc04.view.backgroundColor = [UIColor greenColor];vc04.title = @"視圖4";VCFifth* vc05 = [VCFifth new];vc05.view.backgroundColor = [UIColor grayColor];vc05.title = @"視圖5";VCSixth* vc06 = [VCSixth new];vc06.view.backgroundColor = [UIColor purpleColor];vc06.title = @"視圖6";//創建分欄控制器對象UITabBarController* tbc = [UITabBarController new];//創建一個分欄控制器數組對象,并將所有需要被分欄控制器管理的對象添加進數組//分欄控制器的按鈕的位置就取決于在數組中的存放位置NSArray* arrvc = [NSArray arrayWithObjects:vc01, vc02, vc03, nil];//將分欄控制器管理數組賦值tbc.viewControllers = arrvc;//將分欄控制器作為根視圖控制哦self.window.rootViewController = tbc;//設置選中的視圖控制器的索引//通過所以索引來確定打開程序的時候顯示得是哪一個視圖控制器tbc.selectedIndex = 2;if (tbc.selectedViewController == vc03) {NSLog(@"選中的是下標為2的視圖控制器");}//設置分欄控制器透明度tbc.tabBar.translucent = NO;//設置分欄控制器背景顏色tbc.tabBar.backgroundColor = [UIColor whiteColor];//設置分欄控制器工具欄的按鈕選擇時的顏色tbc.tabBar.tintColor = [UIColor redColor];//注意不要忘記設置代理tbc.delegate = self;
}//以下是協議中函數的用法,其中“編輯”是指在分欄控制器中的more中通過拖動更改和交換顯示和折疊的視圖控制器的操作
//即將開始編輯前會調用此協議函數
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers {NSLog(@"編輯前");
}//即將結束前調用該協議函數
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed {NSLog(@"即將結束前");
}//已經結束編輯時調用該協議函數
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed {NSLog(@"%@", viewControllers);if (changed == YES) {NSLog(@"順序發生改變");}NSLog(@"已經結束編輯");
}//選中控制器對象時調用該協議函數
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
//    if (tabBarController.viewControllers[tabBarController.selectedIndex] == viewController) {
//        NSLog(@"選中的視圖索引與當前傳入的視圖索引相同");
//    }NSLog(@"選中控制器對象");
}- (void)sceneDidDisconnect:(UIScene *)scene {// Called as the scene is being released by the system.// This occurs shortly after the scene enters the background, or when its session is discarded.// Release any resources associated with this scene that can be re-created the next time the scene connects.// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}- (void)sceneDidBecomeActive:(UIScene *)scene {// Called when the scene has moved from an inactive state to an active state.// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}- (void)sceneWillResignActive:(UIScene *)scene {// Called when the scene will move from an active state to an inactive state.// This may occur due to temporary interruptions (ex. an incoming phone call).
}- (void)sceneWillEnterForeground:(UIScene *)scene {// Called as the scene transitions from the background to the foreground.// Use this method to undo the changes made on entering the background.
}- (void)sceneDidEnterBackground:(UIScene *)scene {// Called as the scene transitions from the foreground to the background.// Use this method to save data, release shared resources, and store enough scene-specific state information// to restore the scene back to its current state.
}@end

VCfirst.m文件中

#import "VCFirst.h"@interface VCFirst ()@end@implementation VCFirst- (void)viewDidLoad {[super viewDidLoad];//創建一個分欄按鈕對象,傳入三個參數//第一個參數表示標題文字內容//第二個參數表示顯示圖片//第三個參數表示對象的標記值UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTitle: @"發現" image: nil tag: 101];self.tabBarItem = tabBarItem;
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

VCSecond.m

#import "VCSecond.h"@interface VCSecond ()@end@implementation VCSecond- (void)viewDidLoad {[super viewDidLoad];//根據系統風格設置分欄控制器按鈕,傳入兩個參數//第一個參數指分欄控制器的按鈕風格,第二個參數是分欄控件對象的標簽值UITabBarItem *tabBarItem = [[UITabBarItem alloc] initWithTabBarSystemItem: UITabBarSystemItemContacts tag: 103];//為分欄按鈕設置提示的標記值信息,是系統的,無法變更//按鈕右上角顯示的提示信息//通常用來提示未讀的信息tabBarItem.badgeValue = @"22";self.tabBarItem = tabBarItem;
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

VCThird.m

#import "VCThird.h"@interface VCThird ()@end@implementation VCThird- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

VCForth.m

#import "VCFourth.h"@interface VCFourth ()@end@implementation VCFourth- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

VCFifth.m

#import "VCFifth.h"@interface VCFifth ()@end@implementation VCFifth- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

VCSixth.m

#import "VCSixth.h"@interface VCSixth ()@end@implementation VCSixth- (void)viewDidLoad {[super viewDidLoad];// Do any additional setup after loading the view.
}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

請添加圖片描述

請添加圖片描述

請添加圖片描述

分欄控制器協議部分的內容

< UITabBarControllerDelegate>

//以下是協議中函數的用法,其中“編輯”是指在分欄控制器中的more中通過拖動更改和交換顯示和折疊的視圖控制器的操作
//即將開始編輯前會調用此協議函數
- (void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers {NSLog(@"編輯前");
}//即將結束前調用該協議函數
- (void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed {NSLog(@"即將結束前");
}//已經結束編輯時調用該協議函數
- (void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray<__kindof UIViewController *> *)viewControllers changed:(BOOL)changed {NSLog(@"%@", viewControllers);if (changed == YES) {NSLog(@"順序發生改變");}NSLog(@"已經結束編輯");
}//選中控制器對象時調用該協議函數
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController {
//    if (tabBarController.viewControllers[tabBarController.selectedIndex] == viewController) {
//        NSLog(@"選中的視圖索引與當前傳入的視圖索引相同");
//    }NSLog(@"選中控制器對象");
}

UITabelView

UITabelView是UI組件中 非常重要的一個組件,在實際開發中有非常重要的作用,這里只做簡單介紹,后面筆者會單獨總結一下這部分的內容

在創建UITabelView這個組件的時候,首先需要繼承UITabelViewDelegate,UITabelViewSource

同時需要設置兩個代理:tabelView.delegate、tabelView.dataSource

在協議中必須要實現三個協議函數

  1. -(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section(獲取每組元素的個數)
  2. numberOfSectionsInTableView(設置數據視圖的組數)
  3. tableView: cellForRowAtIndexPath:(創建單元格對象函數)
//
//  SceneDelegate.m
//  UITableView
//
//  Created by xiaoli pop on 2025/6/4.
//#import "SceneDelegate.h"
#import "ViewController.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {self.window.frame = [[UIScreen mainScreen] bounds];ViewController* vc = [ViewController new];UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:vc];self.window.rootViewController = nav;[self.window makeKeyAndVisible];
}- (void)sceneDidDisconnect:(UIScene *)scene {// Called as the scene is being released by the system.// This occurs shortly after the scene enters the background, or when its session is discarded.// Release any resources associated with this scene that can be re-created the next time the scene connects.// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}- (void)sceneDidBecomeActive:(UIScene *)scene {// Called when the scene has moved from an inactive state to an active state.// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}- (void)sceneWillResignActive:(UIScene *)scene {// Called when the scene will move from an active state to an inactive state.// This may occur due to temporary interruptions (ex. an incoming phone call).
}- (void)sceneWillEnterForeground:(UIScene *)scene {// Called as the scene transitions from the background to the foreground.// Use this method to undo the changes made on entering the background.
}- (void)sceneDidEnterBackground:(UIScene *)scene {// Called as the scene transitions from the foreground to the background.// Use this method to save data, release shared resources, and store enough scene-specific state information// to restore the scene back to its current state.
}@end
//
//  ViewController.m
//  UITableView
//
//  Created by xiaoli pop on 2025/6/4.
//#import "ViewController.h"@interface ViewController ()@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];//創建數據視圖,傳入兩個參數//參數一:數據視圖的位置//參數二:數據視圖的風格-UITableViewStylePlain:普通風格 、 UITableViewStyleGrouped:分組風格self.tableview = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];//自動調整子視圖大小self.tableview.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;//創建數據視圖的代理對象self.tableview.delegate = self;//設置數據視圖的代理源對象self.tableview.dataSource = self;//數據視圖的頭部視圖的設定self.tableview.tableHeaderView = nil;//數據視圖的尾部視圖的設定self.tableview.tableFooterView = nil;[self.view addSubview:self.tableview];//創建一個可變數組self.arrayData = [[NSMutableArray alloc] init];for (int i = 'A'; i <= 'Z'; i++) {//定義小數組NSMutableArray* arraySmall = [[NSMutableArray alloc] init];for (int j = 1; j <= 5; j++) {NSString* str = [NSString stringWithFormat:@"%c%d",i,j];[arraySmall addObject:str];}//這里就相當于一個二維數組[self.arrayData addObject:arraySmall];}//當數據的數據源發生變化時,更新數據視圖,重新加載數據[self.tableview reloadData];}- (void)creatButton {self.isEdit = NO;self.buttonOfEdit = [[UIBarButtonItem alloc] initWithTitle:@"編輯" style:UIBarButtonItemStylePlain target:self action:@selector(pressEdit)];self.buttonOfFinish = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStylePlain target:self action:@selector(pressFinish)];self.buttonOfDelete = [[UIBarButtonItem alloc] initWithTitle:@"刪除" style:UIBarButtonItemStylePlain target:self action:@selector(pressDelete)];self.navigationItem.rightBarButtonItem = self.buttonOfEdit;}
- (void)pressEdit {self.isEdit = YES;self.navigationItem.rightBarButtonItem = self.buttonOfFinish;[self.tableview setEditing:YES];self.navigationItem.leftBarButtonItem = self.buttonOfDelete;
}- (void)pressFinish {self.isEdit = NO;self.navigationItem.rightBarButtonItem = self.buttonOfEdit;[self.tableview setEditing:NO];self.navigationItem.leftBarButtonItem = nil;
}/*參數講解:參數一:觸發事件的表格視圖對象參數二:用戶對這個單元格執行的編輯類型參數三:表示當前單元格的位置,包含兩個信息:section(第幾組)、row(第幾行)*/
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyleforRowAtIndexPath:(NSIndexPath *)indexPath {if (editingStyle == UITableViewCellEditingStyleDelete) {// 1. 先刪除數據源中的數據[self.arrayData[indexPath.section] removeObjectAtIndex:indexPath.row];// 2. 更新表格視圖(動畫刪除這一行)[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];}
}//- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//    if (editingStyle == UITableViewCellEditingStyleInsert) {
//        // 1. 創建一個新的數據項(你可以替換成你自己的默認值)
//        NSString *newItem = @"新添加的內容";
//
//        // 2. 往數據源中插入(在指定 section 的對應位置)
//        [self.arrayData[indexPath.section] insertObject:newItem atIndex:indexPath.row];
//
//        // 3. 更新表格界面(帶動畫插入新行)
//        [tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
//    }
//}/*告訴表格視圖每一行在處于編輯狀態時,應該支持什么操作UITableViewCellEditingStyleDeleteUITableViewCellEditingStyleInsertUITableViewCellEditingStyleNone*/
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {return UITableViewCellEditingStyleDelete ;
}- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {NSLog(@"選中單元格!%lu %lu", indexPath.section, indexPath.row);
}- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {NSLog(@"取消 選中單元格!%lu %lu", indexPath.section, indexPath.row);
}
//或取每組元素的個數(行數)
//必須要實現的協議函數
//程序在顯示數據視圖時會調用此函數
//p1:數據視圖對象本身
//p2: 那一組需要的行數
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {NSInteger num = [[self.arrayData objectAtIndex:section] count];return num;
}
//設定數據視圖的組數,默認返回1
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return  self.arrayData.count;
}//創建單元格函數對象
//參數一:調用函數的對象
//參數二:單元格的索引,就是上面的行數與組數
/*//單元格文字賦值cell.textLabel.text = [_arrayData[indexPath.section] objectAtIndex:indexPath.row];//設置子文字標題cell.detailTextLabel.text = @"子標題";//設置圖片NSString* str = [NSString stringWithFormat:@"photo0%ld.jpg",indexPath.row];cell.imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:str]];*/
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {NSString* cellstr = @"cell";//嘗試獲得可復用的單元格,如果得不到就返回空/*當滾動表格時,屏幕上的單元格會離開屏幕,已經滾出屏幕的單元格不會被立刻銷毀,而是存入復用遲中,當需要顯示新的cell時,系統會從復用池中獲取一個單元格重新使用,而不是重新創建*/UITableViewCell* cell = [self.tableview dequeueReusableCellWithIdentifier:cellstr];if (!cell) {//創建一個單元格對象//參數一:單元格樣式//參數二:單元格的復用標記cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellstr];}//NSString* str = [NSString stringWithFormat:@"第%ld組,第%ld行",indexPath.section,indexPath.row];//單元格內容賦值cell.textLabel.text = self.arrayData[indexPath.section][indexPath.row];//調用創建功能按鈕方法[self creatButton];return cell;
}- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {return 100;
}- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {return @"頭部標題";
}- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {return @"尾部標題";
}- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {return 40;
}- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {return 40;
}@end

請添加圖片描述
請添加圖片描述

照片墻案例

userInteractionEnable屬性介紹:

userInteractionEnabled是UIView的一個重要屬性,用于控制用戶是否能與該視圖及其子視圖進行交互(如點擊、滑動、手勢等)。在照片墻案,若需要對圖片進行點擊查看、縮放、刪除等操作,必須將相關視圖的該屬性設為 YES(默認值也是 YES,但某些場景下可能被意外修改)。

這個屬性是屬于UIView的,是BOOL類型的,決定UIView是否接受有關touch和keyBoard的相關操作,然后UIView就可以通過相應的一些方法來處理。

其次我們需要創建一個手勢識別器UITapGestureRecognizer

//給每個控件添加手勢
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(press:)];//創建一個手勢識別器,并且添加相應的方法
tap.numberOfTapsRequired = 1;//設置觸摸次數
tap.numberOfTouchesRequired = 1;//設置觸摸點個數
[iView addGestureRecognizer:tap];//添加手勢識別器到view中
//觸摸后實現方法函數
- (void) press:(UITapGestureRecognizer*) tap {//強制轉換類型UIImageView* imageView = (UIImageView*) tap.view;//創建即將推出的視圖控制器ShowImage* imageShow = [[ShowImage alloc] init];//點擊的圖像視圖賦值imageShow.imageTag = imageView.tag;imageShow.image = imageView.image;//將控制器推出[self.navigationController pushViewController:imageShow animated:YES];
}

在SceneDelegate文件中,設置導航控制器

#import "SceneDelegate.h"
#import "VCRoot.h"
#import "VCImageShow.h"
@interface SceneDelegate ()@end@implementation SceneDelegate- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {//導航控制器照片結構UINavigationController* nav = [[UINavigationController alloc] initWithRootViewController:[VCRoot new]];self.window.rootViewController = nav;[self.window makeKeyAndVisible];
}- (void)sceneDidDisconnect:(UIScene *)scene {// Called as the scene is being released by the system.// This occurs shortly after the scene enters the background, or when its session is discarded.// Release any resources associated with this scene that can be re-created the next time the scene connects.// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}- (void)sceneDidBecomeActive:(UIScene *)scene {// Called when the scene has moved from an inactive state to an active state.// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}- (void)sceneWillResignActive:(UIScene *)scene {// Called when the scene will move from an active state to an inactive state.// This may occur due to temporary interruptions (ex. an incoming phone call).
}- (void)sceneWillEnterForeground:(UIScene *)scene {// Called as the scene transitions from the background to the foreground.// Use this method to undo the changes made on entering the background.
}- (void)sceneDidEnterBackground:(UIScene *)scene {// Called as the scene transitions from the foreground to the background.// Use this method to save data, release shared resources, and store enough scene-specific state information// to restore the scene back to its current state.
}@end

在VCRoot中設置照片墻

#import "VCRoot.h"
#import "VCImageShow.h"
@interface VCRoot ()@end@implementation VCRoot- (void)viewDidLoad {[super viewDidLoad];self.title = @"照片墻";self.view.backgroundColor = [UIColor whiteColor];self.navigationController.navigationBar.translucent = YES;self.navigationController.navigationBar.barTintColor = [UIColor yellowColor];//創建一個滾動視圖并設置位置和畫布大小UIScrollView* sv = [UIScrollView new];sv.frame = CGRectMake(5, 10, 394, 852);sv.contentSize = CGSizeMake(394, 852 * 1.5);sv.showsVerticalScrollIndicator = NO;//打開交互事件sv.userInteractionEnabled = YES;//利用循環給根視圖上添加照片對象for (int i = 0; i < 9; i++) {UIImage* image = [UIImage imageNamed:[NSString stringWithFormat:@"photo0%d.jpg",i + 1]];UIImageView* view = [[UIImageView alloc] initWithImage:image];view.frame = CGRectMake(10 + (i % 3) * 125, (i / 3) * 165, 110, 150);[sv addSubview:view];view.userInteractionEnabled = YES;//創建點擊手勢UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(pressTap:)];//單次點擊tap.numberOfTapsRequired = 1;//單個手指tap.numberOfTouchesRequired = 1;[view addGestureRecognizer:tap];view.tag = 101 + i;}[self.view addSubview: sv];
}//方法3:
- (void)pressTap:(UITapGestureRecognizer* )tap {UIImageView* imageView = (UIImageView*)tap.view;VCImageShow* imageshow = [VCImageShow new];imageshow.imageTag = imageView.tag;[self.navigationController pushViewController:imageshow animated:YES];}//方法2:
//- (void)pressTap:(UITapGestureRecognizer* )tap {
//    UIImageView* imageView = (UIImageView*)tap.view;
//    //創建顯示視圖控制器
//    VCImageShow* imageshow = [[VCImageShow alloc] init];
//    //點擊的圖像視圖賦值
//    //imageshow.imageView = imageView;//不可行
//    imageshow.image = imageView.image;
//    //將視圖控制器推出
//    [self.navigationController pushViewController:imageshow animated:YES];
//    
//    
//}
/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end

接下來需要解決如何將被點擊的視圖傳入到展示圖片的頁面,這里要注意,不可以直接傳視圖對象,因為一個人視圖對象只能有一個根視圖,當我們把視圖添加到新的父視圖上時,會從原來的父親視圖刪除掉

//
//  VCImageShow.m
//  PhotoWall
//
//  Created by xiaoli pop on 2025/6/3.
//#import "VCImageShow.h"@interface VCImageShow ()@end@implementation VCImageShow- (void)viewDidLoad {[super viewDidLoad];self.title = @"圖片展示";self.imageView = [[UIImageView alloc] init];self.imageView.frame = [[UIScreen mainScreen] bounds];//方法2://self.imageView.image = self.image;//方法3:self.imageView.image = [UIImage imageNamed:[NSString stringWithFormat:@"photo0%lu.jpg",(unsigned long)(self.imageTag - 100) ]];/*一個視圖對象只能有一個根視圖當我們把視圖添加到新的父視圖上時會從原來的父親視圖刪除掉*/[self.view addSubview:self.imageView];}/*
#pragma mark - Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {// Get the new view controller using [segue destinationViewController].// Pass the selected object to the new view controller.
}
*/@end
  • 實現效果

請添加圖片描述

點擊圖片就會跳轉一個新頁面,內容就是選中的圖片

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

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

相關文章

Microsoft前后端不分離編程新風向:cshtml

文章目錄 什么是CSHTML&#xff1f;基礎語法內聯表達式代碼塊控制結構 布局頁面_ViewStart.cshtml_Layout.cshtml使用布局 模型綁定強類型視圖模型集合 HTML輔助方法基本表單驗證 局部視圖創建局部視圖使用局部視圖 高級特性視圖組件依賴注入Tag Helpers 性能優化緩存捆綁和壓縮…

【SpringBoot+SpringCloud】Linux配置nacos踩坑大全

*建議在開發時使用Linux環境下搭建nacos 1.在nacos官網找到搭配SpringBoot和SpringCloud的版本 2.Nacos 依賴 Java 環境來運行&#xff0c;需要在linux系統中安裝JDK 1.8 3.按照Nacos官網步驟安裝&#xff0c;防火墻配置開放8848和9848端口 客戶端擁有相同的計算邏輯&…

如何在 Java 中優雅地使用 Redisson 實現分布式鎖

分布式系統中&#xff0c;節點并發訪問共享資源可能導致數據一致性問題。分布式鎖是常見的解決方案&#xff0c;可確保操作原子性。Redisson是基于Redis的Java分布式對象庫&#xff0c;提供多種分布式同步工具&#xff0c;包括分布式鎖。Redisson與Redis&#xff08;實時數據平…

pikachu靶場通關筆記20 SQL注入03-搜索型注入(GET)

目錄 一、SQL注入 二、搜索型注入 三、源碼分析 1、滲透思路1 2、滲透思路2 四、滲透實戰 1、滲透準備 2、SQL注入探測 &#xff08;1&#xff09;輸入百分號單引號 &#xff08;2&#xff09;萬能注入語句 3、獲取回顯列orderby 4、獲取數據庫名database 5、獲取…

mac:大模型系列測試

0 MAC 前幾天經過學生優惠以及國補17K入手了mac studio,然后這兩天親自測試其模型行運用能力如何&#xff0c;是否支持微調、推理速度等能力。下面進入正文。 1 mac 與 unsloth 按照下面的進行安裝以及測試&#xff0c;是可以跑通文章里面的代碼。訓練速度也是很快的。 注意…

A Survey on the Memory Mechanism of Large Language Model based Agents

目錄 摘要Abstract1. LLM-Based Agent的Memory1.1 基礎概念1.2 用于解釋Memory的例子1.3 智能體記憶的定義1.3.1 狹義定義(肯定不用這個定義)1.3.2 廣義定義 1.4 記憶協助下智能體與環境的交互過程1.4.1 記憶寫入1.4.2 記憶管理1.4.3 記憶讀取1.4.4 總過程 2. 如何實現智能體記…

搭建 Serverless 架構

? 一、理解 Serverless 架構核心概念 核心理念&#xff1a; 無需管理服務器&#xff1a;只需編寫業務邏輯&#xff0c;部署后由云平臺托管運行環境。 事件驅動&#xff08;Event-driven&#xff09; 按需計費&#xff08;按調用次數/資源消耗&#xff09; 高可擴展性與自動…

Git倉庫的創建

Git服務器準備 假設Git所在服務器為Ubuntu系統&#xff0c;IP地址10.17.1.5。 一. 準備運行git服務的git用戶&#xff0c;這里用戶名就直接設定為git。 1. 創建一個git用戶組&#xff0c;并創建git用戶。 sudo groupadd git sudo useradd git -g git 2. 創建git用戶目錄&…

電腦提示dll文件缺失怎么辦 dll修復方法

當你在使用某些應用程序或啟動電腦時&#xff0c;看到提示“DLL文件缺失”的錯誤信息&#xff0c;這通常意味著某個必要的動態鏈接庫&#xff08;DLL&#xff09;文件無法被找到或加載&#xff0c;導致軟件無法正常運行。本文將詳細介紹如何排查和修復DLL文件缺失的問題&#x…

使用 Rest-Assured 和 TestNG 進行購物車功能的 API 自動化測試

這段代碼使用了 Rest-Assured 進行 API 測試&#xff0c;結合 TestNG 框架執行多個 HTTP 請求并進行斷言驗證。以下是對每個測試方法的詳細解釋&#xff0c;包括代碼邏輯和測試目的。 1. test01() 方法 - 提取響應數據 Test public void test01() {String jsonData "{\&…

【設計模式-4.7】行為型——備忘錄模式

說明&#xff1a;本文介紹行為型設計模式之一的備忘錄模式 定義 備忘錄模式&#xff08;Memento Pattern&#xff09;又叫作快照模式&#xff08;Snapshot Pattern&#xff09;或令牌模式&#xff08;Token Pattern&#xff09;指在不破壞封裝的前提下&#xff0c;捕獲一個對…

2025年滲透測試面試題總結-天融信[社招]滲透測試工程師(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 天融信[社招]滲透測試工程師 一、Java Spring Boot組件漏洞 1. CVE-2018-1270&#xff08;WebSocket RCE&…

華為OD機考-內存冷熱標記-多條件排序

import java.util.*;public class DemoTest5 {public static void main(String[] args) {Scanner in new Scanner(System.in);// 注意 hasNext 和 hasNextLine 的區別while (in.hasNextLine()) { // 注意 while 處理多個 caseint a in.nextInt();int[] arr new int[a];for(int…

PPT轉圖片拼貼工具 v3.0

軟件介紹 這個軟件就是將PPT文件轉換為圖片并且拼接起來。 這個代碼支持導入單個文件也支持導入文件夾 但是目前還沒有解決可視化界面問題。 效果展示 軟件源碼 import os import re import win32com.client from PIL import Image from typing import List, Uniondef con…

NLP學習路線圖(三十):微調策略

在自然語言處理領域,預訓練語言模型(如BERT、GPT、T5)已成為基礎設施。但如何讓這些“通才”模型蛻變為特定任務的“專家”?微調策略正是關鍵所在。本文將深入剖析七種核心微調技術及其演進邏輯。 一、基礎概念:為什么需要微調? 預訓練模型在海量語料上學習了通用語言表…

講述我的plc自學之路 第十三章

我和lora都是那種理想主義者&#xff0c;這是我們的共同之處。但是lora比我要更文藝一些&#xff0c;她讀的書畢竟比我多&#xff0c;上的又是名校。受北大人文氣息的熏陶&#xff0c;她總是對愛情充滿了太多幻想。 “說說你的過往吧&#xff0c;lora。”我給lora倒了一杯啤酒&…

GPU虛擬化

引言 現有如下環境&#xff08;注意相關配置&#xff1a;只有一個k8s節點&#xff0c;且該節點上只有一張GPU卡&#xff09;&#xff1a; // k8s版本 $ kubectl version Client Version: version.Info{Major:"1", Minor:"22", GitVersion:"v1.22.7&…

【免費數據】2005-2019年我國272個地級市的旅游競爭力多指標數據(33個指標)

旅游業是一個城市的重要產業構成。旅游競爭力是一個城市競爭力的重要構成部分。一個城市的旅游競爭力反映了其在旅游市場競爭中的比較優勢。 今日我們分享的是2005-2019年我國272個地級市的旅游競爭力多指標數據&#xff01;該數據集源自2025年4月發表于《地理學報》的論文成果…

AI智能驅動瀏覽器工具Browser Use詳解

前言 在之前關于 AI 測試相關的幾篇文章中,我們分別介紹了通過 playwright-mcp,以及 midscene.js、magentic ui 等幾個不同的 AI 瀏覽器工具,實現 AI 驅動自動化測試的方法介紹。而其實在這些不斷涌現的新工具出現之前,還有一個更早推出(2024.11),也同樣還在不斷完善的…

新成果:GaN基VCSEL動態物理模型開發

作為高速數據傳輸與光電信號處理的核心器件&#xff0c;垂直腔面發射激光器&#xff08;VCSEL&#xff09;在高速光通信、激光雷達等領域應用廣泛&#xff0c;其動態特性直接關聯器件調制速率及穩定性等關鍵參數。近期&#xff0c;天津賽米卡爾科技有限公司技術團隊開發了GaN基…