【iOS】3GShare仿寫

【iOS】3GShare仿寫

文章目錄

  • 【iOS】3GShare仿寫
    • 登陸注冊界面
    • 主頁
    • 搜索
    • 文章
    • 活動
    • 我的
    • 總結

登陸注冊界面

這個界面的ui東西不多,主要就是幾個輸入框及對輸入內容的一些判斷

登陸界面

//這里設置了一個初始密碼并儲存到NSUserDefaults中
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];if (![defaults objectForKey: @"UserAccounts"]) {NSDictionary *defaultUser = @{@"a": @"1"};[defaults setObject: defaultUser forKey: @"UserAccounts"];}
self.textFieldUser = [[UITextField alloc] initWithFrame: CGRectMake(70, 320, 250, 46)];self.textFieldUser.placeholder = @"請輸入用戶名";self.textFieldUser.borderStyle = UITextBorderStyleRoundedRect;self.textFieldUser.leftView = [self createLefticonViewWithImageName: @"賬戶.png"];self.textFieldUser.leftViewMode = UITextFieldViewModeAlways;self.textFieldcode = [[UITextField alloc] initWithFrame: CGRectMake(70, 390, 250, 46)];self.textFieldcode.placeholder = @"請輸入密碼";self.textFieldcode.borderStyle = UITextBorderStyleRoundedRect;self.textFieldcode.secureTextEntry = YES;self.textFieldcode.leftView = [self createRighticonViewWithImageName: @"解鎖.png"];self.textFieldcode.leftViewMode = UITextFieldViewModeAlways;UIButton *loginBtn = [UIButton buttonWithType: UIButtonTypeSystem];loginBtn.frame = CGRectMake(85, 470, 90, 40);[loginBtn setTitle: @"登陸" forState: UIControlStateNormal];[loginBtn addTarget: self action: @selector(handleLoginBtn) forControlEvents: UIControlEventTouchUpInside];loginBtn.tintColor = [UIColor whiteColor];loginBtn.layer.borderColor = [UIColor whiteColor].CGColor;loginBtn.layer.borderWidth = 1.0;loginBtn.layer.cornerRadius = 8.0;loginBtn.clipsToBounds = YES;[self.view addSubview: loginBtn];
NSString *username = self.textFieldUser.text;NSString *password = self.textFieldcode.text;if (username.length > 15 || password.length > 15) {UIAlertController *alert2 = [UIAlertController alertControllerWithTitle: @"錯誤" message: @"賬號或密碼過長" preferredStyle: UIAlertControllerStyleAlert];[alert2 addAction: [UIAlertAction actionWithTitle: @"確定" style: UIAlertActionStyleDefault handler: nil]];[self presentViewController: alert2 animated: YES completion: nil];return;}NSDictionary *userDict = [[NSUserDefaults standardUserDefaults] objectForKey: @"UserAccounts"];NSString *savedPassword = userDict[username];if (savedPassword && [savedPassword isEqualToString: password]) {MainTabBarController *mainTabBar = [[MainTabBarController alloc] init];self.view.window.rootViewController = mainTabBar;} else {UIAlertController *alertright = [UIAlertController alertControllerWithTitle: @"錯誤" message: @"賬號或密碼錯誤" preferredStyle: UIAlertControllerStyleAlert];[alertright addAction: [UIAlertAction actionWithTitle: @"確定" style: UIAlertActionStyleDefault handler: nil]];[self presentViewController: alertright animated: YES completion: nil];return;}

主要是通過UITextField代理方法在確認后判斷框中的字符是否符合標準,再用個警告對話框進行提示

注冊界面其他的跟登錄界面差不多,主要是要用一個協議傳值判斷后把新的賬號密碼傳入到前面設置的defaultUser中,關于協議傳值的內容前面博客中有所寫出,不多闡述

主頁

主頁界面大體由上面的輪播圖和下面的自定義單元格組成

請添加圖片描述

里面比較有意思的內容就是點擊下面第一個單元格時可進入其詳情界面,且這里的點贊功能是正常且完善的

請添加圖片描述

這里是同時使用了屬性傳值與協議傳值,屬性往里傳,協議往外傳

詳情界面的部分代碼:

@protocol SendViewControllerDelegate <NSObject>- (void)didUpdateLikeStatus:(BOOL)isLiked likeCount:(NSInteger)likeCount;@end@interface SendViewController : UIViewController@property (nonatomic, copy) NSString *likeCountText;
@property (nonatomic, assign) BOOL isLiked;
@property (nonatomic, weak) id<SendViewControllerDelegate> delegate;
@property (nonatomic, strong) UIButton *like;@property (nonatomic, strong) UILabel *likecount;
@property (nonatomic, strong) UIImageView *looking;
@property (nonatomic, strong) UIImageView *sharing;
@end
self.like = [UIButton buttonWithType:UIButtonTypeCustom];[self.like setImage:[UIImage imageNamed:@"liking.png"] forState:UIControlStateNormal];[self.like addTarget:self action:@selector(toggleLike) forControlEvents:UIControlEventTouchUpInside];self.like.frame = CGRectMake(235, 75, 30, 30);[self.like setImage:[UIImage imageNamed:(self.isLiked ? @"likingred.png" : @"liking.png")] forState:UIControlStateNormal];[scrollView addSubview:self.like];self.likecount = [[UILabel alloc] init];self.likecount.frame = CGRectMake(265, 80, 40, 20);self.likecount.text = self.likeCountText;[scrollView addSubview: self.likecount];scrollView.contentSize = CGSizeMake(self.view.frame.size.width, CGRectGetMaxY(vImage.frame) + 20);
}
- (void)toggleLike {self.isLiked = !self.isLiked;NSInteger currentCount = [self.likecount.text integerValue];if (self.isLiked) {currentCount += 1;[self.like setImage:[UIImage imageNamed:@"likingred.png"] forState:UIControlStateNormal];} else {currentCount -= 1;[self.like setImage:[UIImage imageNamed:@"liking.png"] forState:UIControlStateNormal];}self.likecount.text = [NSString stringWithFormat:@"%ld", (long)currentCount];if ([self.delegate respondsToSelector: @selector(didUpdateLikeStatus:likeCount:)]) {[self.delegate didUpdateLikeStatus: self.isLiked likeCount: currentCount];}
}

搜索

這個界面的內容主要是可以點擊的一些按鈕,可以識別輸入字符跳轉的一個界面還有一個上傳界面

請添加圖片描述

UITextField *searchField = [[UITextField alloc] initWithFrame:CGRectMake(16, 150, self.view.frame.size.width - 32, 36)];searchField.borderStyle = UITextBorderStyleRoundedRect;searchField.placeholder = @"搜索 用戶名 作品分類 文章";searchField.clearButtonMode = UITextFieldViewModeWhileEditing;searchField.returnKeyType = UIReturnKeySearch;searchField.delegate = self;UIImageView *leftImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"搜索.png"]];leftImageView.contentMode = UIViewContentModeScaleAspectFit;leftImageView.frame = CGRectMake(0, 0, 20, 20);UIView *leftViewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 30, 20)];[leftViewContainer addSubview:leftImageView];leftImageView.center = leftViewContainer.center;searchField.leftView = leftViewContainer;searchField.leftViewMode = UITextFieldViewModeAlways;searchField.backgroundColor = [UIColor colorWithWhite:0.9 alpha:1.0];

其實這個界面主要的還是上傳界面

請添加圖片描述

這個上傳界面的圖片墻我使用UICollectionView設置的,若點擊一張圖片則會儲存到一個可變數組當中,再次點擊即會取消其被包含的狀態,最后會把數組中存儲的照片數量和選中的第一張圖片返回代替放在選擇圖片上面

 self.view.backgroundColor = [UIColor whiteColor];self.images = @[@"頭像1.jpg", @"頭像2.jpg", @"頭像3.jpg", @"頭像4.jpg", @"頭像5.jpg", @"頭像6.jpg", @"頭像7.jpg", @"頭像8.jpg", @"頭像9.jpg"];self.selectedIndexes = [NSMutableArray array];//設置collectionview的所處的位置UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];layout.itemSize = CGSizeMake(100, 100);layout.minimumLineSpacing = 20;layout.minimumInteritemSpacing = 10;layout.sectionInset = UIEdgeInsetsMake(20, 20, 20, 20);self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.bounds collectionViewLayout:layout];self.collectionView.delegate = self;self.collectionView.dataSource = self;self.collectionView.backgroundColor = [UIColor whiteColor];[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"cell"];[self.view addSubview:self.collectionView];
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {NSNumber *indexNumber = @(indexPath.item);if ([self.selectedIndexes containsObject:indexNumber]) {[self.selectedIndexes removeObject:indexNumber];} else {[self.selectedIndexes addObject:indexNumber];}[collectionView reloadItemsAtIndexPaths:@[indexPath]];
}- (void)doneAction {UIImage *selectedImage = nil;if (self.selectedIndexes.count > 0) {NSNumber *firstIndex = self.selectedIndexes.firstObject;selectedImage = [UIImage imageNamed:self.images[firstIndex.integerValue]];}if ([self.delegate respondsToSelector:@selector(didSelectImage: andCount:)]) {[self.delegate didSelectImage:selectedImage andCount:self.selectedIndexes.count];}[self dismissViewControllerAnimated:YES completion:nil];[self.navigationController popViewControllerAnimated:YES];
}

文章

這個界面是一個分欄控件管理的三個視圖控制器,每個視圖控制器都是一個分別的自定義cell,并且在其底下有一個橫向的滾動視圖以確保其可以進行左右滑動

請添加圖片描述

self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[@"精選文章", @"熱門推薦", @"全部文章"]];self.segmentedControl.frame = CGRectMake(0, 100, self.view.bounds.size.width , 40);self.segmentedControl.selectedSegmentIndex = 0;[self.segmentedControl addTarget:self action:@selector(segmentChanged:) forControlEvents:UIControlEventValueChanged];self.segmentedControl.backgroundColor = [UIColor whiteColor];UIFont *font = [UIFont systemFontOfSize:18];NSDictionary *attributes = @{NSFontAttributeName: font};[self.segmentedControl setTitleTextAttributes:attributes forState:UIControlStateNormal];[self.segmentedControl setTitleTextAttributes:attributes forState:UIControlStateSelected];[self.view addSubview:self.segmentedControl];self.firstVC = [[FirstVC alloc] init];self.secondVC = [[SecondVC alloc] init];self.thirdVC = [[ThirdVC alloc] init];CGFloat yOffset = CGRectGetMaxY(self.segmentedControl.frame);CGFloat scrollHeight = self.view.bounds.size.height - yOffset;self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, yOffset, self.view.bounds.size.width, scrollHeight)];self.scrollView.pagingEnabled = YES;self.scrollView.showsHorizontalScrollIndicator = NO;self.scrollView.delegate = self;self.scrollView.contentSize = CGSizeMake(self.view.bounds.size.width * 3, scrollHeight);[self.view addSubview:self.scrollView];

活動

這個界面非常簡單,只是一個簡單的三個自定義的單元格

請添加圖片描述

我的

這個界面的東西最多也最繁瑣,但是總的看來也就這么幾個東西:

第一個就是需要跨多個界面進行傳值進行保留

請添加圖片描述

請添加圖片描述

這里使用的是強屬性引用來傳值的方法,即設置下一個視圖控制器為上一個的屬性,若不為空則使用上次創建的那個視圖來保存之前設置的狀態

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {switch (indexPath.row) {case 0: {if (self.setDatavc == nil) {self.setDatavc = [[SetDataViewController alloc] init];[self.navigationController pushViewController: self.setDatavc animated: YES];break;} else {[self.navigationController pushViewController: self.setDatavc animated: YES];break;}}case 1: {ChangeWordVC *vc = [[ChangeWordVC alloc] init];[self.navigationController pushViewController:vc animated:YES];break;}case 2: {if (self.messagesetvc == nil) {self.messagesetvc = [[MessageSetVC alloc] init];[self.navigationController pushViewController: self.messagesetvc animated: YES];break;} else {[self.navigationController pushViewController: self.messagesetvc animated: YES];break;}}case 3: {UIAlertController *alert3 = [UIAlertController alertControllerWithTitle: @"這是一個古老的軟件" message: nilpreferredStyle: UIAlertControllerStyleAlert];[alert3 addAction: [UIAlertAction actionWithTitle: @"確定" style: UIAlertActionStyleDefault handler: nil]];[self presentViewController: alert3 animated: YES completion: nil];break;}case 4: {UIAlertController *alert4 = [UIAlertController alertControllerWithTitle: @"已清理緩存" message: nilpreferredStyle: UIAlertControllerStyleAlert];[alert4 addAction: [UIAlertAction actionWithTitle: @"確定" style: UIAlertActionStyleDefault handler: nil]];[self presentViewController: alert4 animated: YES completion: nil];break;}default:break;}[tableView deselectRowAtIndexPath:indexPath animated:YES];
}

第二個就是一個可以對密碼進行修改并確認兩次密碼是否一樣的,因不需要影響登陸進來的原始密碼,只是對兩次輸入的密碼進行確認就行了,所以沒啥東西掠過

第三個就是里面有關一個簡單的聊天室的內容

請添加圖片描述

即每次發送消息都切換一個發送方,并根據發送方的不同分別進行相應的布局,在前面記得要設置每方氣泡的最大寬度

 if (self.inputField.text.length == 0) {return;}static int count = 0;NSString *text = self.inputField.text;NSString *avatar = (count % 2 == 0) ? @"img03.png" : @"img12.png";MessageType type = (count % 2 == 0) ? MessageTypeSent : MessageTypeReceived;NSString *time = [NSString stringWithFormat: @"10:%02d", count];Message *message = [[Message alloc] initWithText:text time:time avatar:avatar type:type];[self.messages addObject:message];[self.tableView reloadData];[self scrollToBottom];self.inputField.text = @"";count++;
}- (void)keyboardWillShow:(NSNotification *)notification {NSDictionary *userInfo = notification.userInfo;CGRect keyboardFrameInWindow = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];CGRect keyboardFrame = [self.view convertRect:keyboardFrameInWindow fromView:nil];CGFloat keyboardHeight = keyboardFrame.size.height;[UIView animateWithDuration:0.25 animations:^{CGRect inputFrame = self.inputField.superview.frame;CGFloat tabBarHeight = self.tabBarController.tabBar.frame.size.height;inputFrame.origin.y = self.view.bounds.size.height - keyboardHeight - inputFrame.size.height + tabBarHeight;self.inputField.superview.frame = inputFrame;CGRect tableFrame = self.tableView.frame;tableFrame.size.height = inputFrame.origin.y;self.tableView.frame = tableFrame;[self scrollToBottom];}];

同時也要有點擊鍵盤時的上抬,這里記得要考慮減去下面導航欄的高度,否則可能會導致那個輸入框上移過多或者無法回到正常位置,關于聊天室更加具體明確的寫出參考學長的博客,「OC」實現簡單的聊天室界面

總結

這個項目算是暑假中相當繁瑣的一個,能更好的鍛煉我們的各種傳值方式和對各種控件的掌握

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

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

相關文章

從案例學習cuda編程——線程模型和顯存模型

1. cuda介紹CUDA&#xff08;Compute Unified Device Architecture&#xff0c;統一計算設備架構&#xff09;是NVIDIA推出的一種并行計算平臺和編程模型。它允許開發者利用NVIDIA GPU的強大計算能力來加速計算密集型任務。CUDA通過提供一套專門的API和編程接口&#xff0c;使得…

進階向:YOLOv11模型輕量化

YOLOv11模型輕量化詳解:從理論到實踐 引言 YOLO(You Only Look Once)系列模型因其高效的實時檢測能力而廣受歡迎。YOLOv11作為該系列的最新演進版本,在精度和速度上均有顯著提升。然而,原始模型對計算資源的需求較高,難以在邊緣設備或移動端部署。輕量化技術通過減少模…

2025-08 安卓開發面試拷打記錄(面試題)

想跑路了&#xff0c;開始學八股&#xff0c;幾個主動找的大廠試了下水&#xff0c;后續看情況更新。樓主一年經驗&#xff0c;學的c被騙來干安卓&#xff0c;雙非本科。2025-07-31 小鵬匯天 安卓開發一面synchronizedhandler視圖刷新binderjvm垃圾回收內存泄漏排查glide緩…

風丘助力混合動力汽車工況測試:精準采集整車信號解決方案

一、背景 混合動力汽車是介于純電動汽車與燃油汽車兩者之間的一種新能源汽車。它既包含純電動汽車無污染、啟動快的優勢&#xff0c;又擁有燃油車續航便捷、不受電池容量限制的特點。在當前環境下&#xff0c;混合動力汽車比純電動汽車更符合目前的市場需求。 然而&#xff…

??MCU程序的存儲方式與存儲區域大小要求?

程序的段的存儲方式與存儲區域大小要求 程序的存儲和運行涉及 ROM&#xff08;Flash/非易失性存儲器&#xff09; 和 RAM&#xff08;易失性存儲器&#xff09; 的分配&#xff0c;不同段在存儲和運行時具有不同的特性。以下是詳細的分類和計算方式&#xff1a;1. 程序文件的存…

Lesson 31 Success story

Lesson 31 Success story 詞匯 retire v.退休,退役[運動]去睡覺 構成:re-表示重復 tire v.感到累一tried a.累的 tyre n.輪胎 用法:retire from 單位 從…退休(過去時) 例句:他從學校退休了。 He retired from our school. retire例句: 1.他越來越老了&#xff0c;他即將退休。…

2025年8月4日私魚創作平臺v1.0.4公測版更新發布-完成大部分功能包含關注創作者以及發布作品及合集功能優雅草科技

2025年8月4日私魚創作平臺v1.0.4公測版更新發布-完成大部分功能包含關注創作者以及發布作品及合集功能優雅草科技 鯨魚小說分銷系統介紹 優雅草私魚創作系統——產品介紹 系統概述 優雅草私魚創作系統&#xff08;簡稱“私魚”&#xff09;是一款專注于私域流量運營的垂直化…

鷓鴣云:光伏電站的“智慧中樞”,精準調控逆變器

光伏電站如星辰散落于大地&#xff0c;那些默默工作的逆變器便是每一處光芒的關鍵心臟。然而&#xff0c;分布廣袤、設備眾多&#xff0c;傳統運維如盲人摸象&#xff0c;效率低下&#xff0c;故障難尋&#xff0c;白白流失寶貴電能。鷓鴣云光伏運維軟件應時而生&#xff0c;它…

java中Reflection反射(一)

目錄 一、概述 二、class類&#xff1a; 1、獲取類的字節碼文件&#xff1a; &#xff08;1&#xff09;方式一&#xff1a;直接通過一個class的靜態變量class獲取 &#xff08;2&#xff09;方式二&#xff1a;如果知道一個class的完整類名&#xff0c;可以通過靜態方法Cl…

CVE-2021-1879

一、漏洞原理 CVE-2021-1879 是 IBM WebSphere Application Server 中存在的一個 路徑遍歷&#xff08;Path Traversal&#xff09; 漏洞&#xff0c;其核心原理為&#xff1a; ①WebSphere 在處理某些文件操作請求&#xff08;如下載、上傳或配置文件讀取&#xff09;時&#…

二進制簽名查找器(Aho-Corasick 自動機):設計思路與實現原理(C/C++代碼實現)

在逆向工程、惡意軟件分析和二進制文件解析領域&#xff0c;快速準確地識別特定字節模式&#xff08;即“簽名”&#xff09;是一項核心任務。本文將圍繞一款基于PE-bear工具的二進制簽名查找器&#xff0c;深入解析其設計思路、實現原理及相關技術背景&#xff0c;揭示其如何高…

後端開發技術教學(二) 條件指令、循環結構、定義函數

書接上回&#xff1a;後端開發技術教學(一) [附2025最新可用 phpstudy2018下載鏈接] -CSDN博客 必要資源&#xff1a; trae中文版下載網址: TRAE - The Real AI Engineer phpStudy 2018 : phpStudy - Windows 一鍵部署 PHP 開發環境 小皮出品 目錄 一、條件指令 1.1 if() …

狀壓DP-基本框架

狀壓DP-基本框架一、狀壓DP的核心思想與適用場景1.1 問題特征1.2 核心思想1.3 與傳統DP的對比二、位運算基礎&#xff1a;狀壓DP的語法三、狀壓DP的基本框架3.1 步驟拆解3.2 通用代碼模板四、經典案例詳解4.1 旅行商問題&#xff08;TSP&#xff09;問題描述狀壓DP設計代碼實現…

Web 端 AI 圖像生成技術的應用與創新:虛擬背景與創意圖像合成

隨著 Stable Diffusion、Midjourney 等生成式 AI 模型的爆發,Web 端圖像生成技術從“實驗室demo”走向“工業化應用”。其中,虛擬背景替換(如視頻會議的動態背景生成)和創意圖像合成(如用戶上傳素材與 AI 生成元素的融合)成為最具代表性的場景,它們通過“文本描述→AI 生…

應急響應知識總結

應急響應 Windows系統 查賬號 1、查看服務器是否有弱口令&#xff0c;遠程管理端口是否對公網開放。 檢查方法&#xff1a;據實際情況咨詢相關服務器管理員。 2、查看服務器是否存在可疑賬號、新增賬號。 檢查方法&#xff1a;打開 cmd 窗口&#xff0c;輸入 lusrmgr.msc …

智慧水務賦能二次供水管理精細化轉型:物聯網驅動的全鏈路解決方案

隨著我國城鎮化率激增&#xff0c;高層建筑占比上升&#xff0c;二次供水系統已成為保障城市供水安全的核心環節。然而&#xff0c;傳統管理模式面臨設備老化、運維粗放、監管缺失等矛盾&#xff0c;在此背景下&#xff0c;《“十四五”節水型社會建設規劃》明確要求推進二次供…

tsmc 5nm lvs之 short難搞的類型

1、M3層以上的層次發生的short&#xff0c;dengsity很高的情況下&#xff0c;兩根信號net導致的short&#xff0c;刪除其中一根然后ecoRoute fix不掉的情況下&#xff0c;該怎么辦&#xff0c;可以嘗試去cut 周圍或者上方的power。 2、M1&#xff0c; M2由于cell 內部出pin&…

初識神經網絡01——認識PyTorch

文章目錄一、認識PyTorch1.1 PyTorch是什么1.2 安裝PyTorch二、認識Tensor2.1 創建Tensor2.1.1 基本方式2.2.2 創建線性和隨機張量2.2 Tensor屬性2.2.1 切換設備2.2.2 類型轉換2.3 Tensor與Numpy的數據轉換2.3.1 張量轉ndarray2.3.2 Numpy轉張量2.4 Tensor常見操作2.4.1 取值2.…

Android UI 組件系列(十一):RecyclerView 多類型布局與數據刷新實戰

博客專欄&#xff1a;Android初級入門UI組件與布局 源碼&#xff1a;通過網盤分享的文件&#xff1a;Android入門布局及UI相關案例 鏈接: https://pan.baidu.com/s/1EOuDUKJndMISolieFSvXXg?pwd4k9n 提取碼: 4k9n 引言 在 Android 應用中&#xff0c;RecyclerView 是最常用…

如何學習跨模態對齊(尤其是 CLIP 思想)

學習跨模態對齊&#xff08;尤其是CLIP思想&#xff09;需要結合理論基礎、經典模型原理、實踐復現和前沿擴展&#xff0c;以下是一套系統的學習路徑&#xff0c;從入門到深入逐步展開&#xff1a; 一、先補基礎&#xff1a;跨模態對齊的“前置知識” 跨模態對齊的核心是讓圖…