日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案”

發(fā)布時(shí)間:2023/12/9 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案” 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

iOS回顧筆記( 02 ) -- 由九宮格布局引發(fā)的一系列“慘案”

前言(扯幾句淡先)

回顧到學(xué)習(xí)UI過(guò)程中的九宮格布局時(shí),發(fā)現(xiàn)當(dāng)時(shí)學(xué)的東西真是不少。

這個(gè)階段最大的特點(diǎn)就是:知識(shí)點(diǎn)繁多且瑣碎

我們的目標(biāo)就是要將這瑣碎的知識(shí)點(diǎn)靈活運(yùn)用、融匯貫通,通過(guò)不同的實(shí)現(xiàn)方式來(lái)實(shí)現(xiàn)相同的功能,最后進(jìn)行比較得到最好的那種方式。這個(gè)求知的過(guò)程就是我們最需要學(xué)習(xí)的,在過(guò)程中我們學(xué)會(huì)了自我思考,并且在自己的思考和比較中,我們的腦海里逐漸形成了自己的編程思想。

本文主要以九宮格購(gòu)物車的實(shí)現(xiàn)為引子,從最基礎(chǔ)的實(shí)現(xiàn)方法層層遞進(jìn)直到最完美的實(shí)現(xiàn)方式。代碼從起初的低效、耦合度高到后期的層層分離、MVC各模塊封裝,高內(nèi)聚、低耦合,更具擴(kuò)展性等方面逐步深化和擴(kuò)展;經(jīng)過(guò)編程思想的層層深入和代碼的步步完善最后完整的展現(xiàn)在用戶面前。

本文大體目錄

  • 九宮格購(gòu)物車demo
  • 對(duì)應(yīng)物品封裝(View的簡(jiǎn)單封裝)
  • 數(shù)據(jù)的加載方式對(duì)比 與 演變
  • 屬性列表文件(plist)的創(chuàng)建和使用
  • MVC 思想的引入和介紹

九宮格購(gòu)物車Demo

九宮格是我們?cè)陂_(kāi)發(fā)過(guò)程中對(duì)于一些有規(guī)律的UI布局常用的一種布局算法。
九宮格特點(diǎn):簡(jiǎn)單,封裝性好,可復(fù)用性高,很適合一些頁(yè)面同類型item數(shù)量動(dòng)態(tài)變化UI頁(yè)面布局

下面就實(shí)現(xiàn)一個(gè)買書(shū)購(gòu)物車


基本要求和思路如下

思路:
1. 最初沒(méi)有書(shū)(刪除按鈕不可用)
2. 點(diǎn)擊添加就添加一本書(shū)(刪除按鈕可用)
3. 添加基本之后(提示購(gòu)物車已滿,添加按鈕不可用)
4. 刪除按鈕點(diǎn)擊(購(gòu)物車不滿的時(shí)候添加按鈕又可以使用)
5. 添加書(shū)籍按九宮格的樣式在頁(yè)面中顯示




先說(shuō)說(shuō)最直接的方法

// 添加書(shū) - (IBAction)addBook:(id)sender {// 1. 創(chuàng)建書(shū)圖標(biāo)UIImageView *bookIcon = [UIImageView new];bookIcon.image = [UIImage imageNamed:@"0"];bookIcon.frame = CGRectMake(0, 0, 50, 50);[self.shopView addSubview:bookIcon];// 2.書(shū)名UILabel *bookName = [UILabel new];bookName.frame = CGRectMake(0, 50, 50, 20);bookName.text = @"book1";bookName.textAlignment = NSTextAlignmentCenter;[self.shopView addSubview:bookName];// 3.添加到數(shù)組(分開(kāi)寫(xiě)好像很難明確如何添加這本書(shū))}

這是最直接的方法來(lái)添加的一本書(shū),這樣確實(shí)能添加一本書(shū),但是這種直觀、死板的思想是不對(duì)的。

  • 面對(duì)這樣的動(dòng)態(tài)變化的UI頁(yè)面,每次添加和刪除書(shū)籍的操作都是用戶隨機(jī)的,所以代碼每次也是根據(jù)對(duì)應(yīng)的點(diǎn)擊來(lái)計(jì)算對(duì)應(yīng)書(shū)籍要添加的位置。
  • 每本書(shū)的位置主要是和它對(duì)應(yīng)的index來(lái)確定,這就涉及到“書(shū)”這個(gè)對(duì)象要每次計(jì)數(shù),書(shū)是一個(gè)整體,所以書(shū)內(nèi)部的東西應(yīng)當(dāng)封裝起來(lái)。
  • “書(shū)”在UI上表現(xiàn)是 圖標(biāo) + 書(shū)名,也就是iamgeview + label,從用戶看到的整體性上來(lái)說(shuō),每次添加和刪除同一本書(shū)也需要對(duì) 圖標(biāo) 和 書(shū)名 分別計(jì)算兩次來(lái)計(jì)算和排列。這也是非常不合理的,并且很容易計(jì)算出現(xiàn)問(wèn)題。應(yīng)該根據(jù)UIView 父子控件相關(guān)特性對(duì)“書(shū)”進(jìn)行封裝,添加/刪除的時(shí)候統(tǒng)一處理父控件,至于內(nèi)部屬性都會(huì)根據(jù)父控件來(lái)自動(dòng)布局,方便管理。

書(shū)的封裝

了解以上說(shuō)的直接把代碼分開(kāi)寫(xiě)的局限性之后,現(xiàn)在來(lái)封裝一下“書(shū)”這個(gè)對(duì)象。

  • UI層的封裝,我們先分析UI布局:內(nèi)部屬性只有 圖標(biāo)(UIImagevView) 和 書(shū)名(UILabel)
  • 父控件選取原則:父控件只是承載子控件的容器,應(yīng)當(dāng)簡(jiǎn)潔為主,所以選擇 UIView
// 0. 創(chuàng)建書(shū)UIView *book = [UIView new];book.frame = CGRectMake(0, 0, 60, 70);book.backgroundColor = [UIColor redColor];[self.shopView addSubview:book];// 1. 創(chuàng)建書(shū)圖標(biāo)UIImageView *bookIcon = [UIImageView new];bookIcon.image = [UIImage imageNamed:@"0"];bookIcon.frame = CGRectMake(0, 0, 60, 50);[book addSubview:bookIcon];// 2.書(shū)名UILabel *bookName = [UILabel new];bookName.frame = CGRectMake(0, 50, 60, 20);bookName.text = @"book1";bookName.textAlignment = NSTextAlignmentCenter;[book addSubview:bookName];// 3.添加到數(shù)組(直接添加書(shū)這個(gè)對(duì)象)[self.books addObject:book];

這樣在創(chuàng)建和管理書(shū)的時(shí)候就方便多了,并且有一個(gè)數(shù)組來(lái)記錄添加書(shū)的數(shù)量,在添加和刪除的時(shí)候有計(jì)算的依據(jù):可計(jì)算對(duì)應(yīng)位置和兩個(gè)按鈕的可用情況

九宮格布局的思路和實(shí)現(xiàn)

書(shū)的對(duì)象已經(jīng)封裝好了,我們可以以整體思維來(lái)操作它,下面就是計(jì)算位置的思路。

  • 書(shū)的數(shù)量不定,但列數(shù)是固定的,可以設(shè)置成變量 int clos = 3;
  • 每本書(shū)之間可能有一定間距,橫向間距 margin = ( width - clos * book.width)/ ( clos / 2) ;
  • 每本書(shū)的位置(x,y)可根據(jù)下圖發(fā)現(xiàn)規(guī)律 x = 列號(hào) * (W + margin); y = 行號(hào) * (H+margin)
  • 行號(hào)規(guī)律 : 行號(hào) = index / clos ;
  • 列號(hào)規(guī)律 : 列號(hào) = index % clos ;

有了上面的鋪墊,就可以寫(xiě)動(dòng)態(tài)代碼了,只需要用戶 設(shè)置一個(gè)列數(shù),知道最終有多少本書(shū),遍歷每本書(shū),根據(jù)書(shū)的索引來(lái)計(jì)算對(duì)應(yīng)的書(shū)的位置即可。

廢話不多說(shuō)了,上代碼

// 添加書(shū) - (IBAction)addBook:(id)sender {// 設(shè)置列數(shù)為 3int clos = 3;// 設(shè)置書(shū)的寬高分別為 W HCGFloat W = 60;CGFloat H = 70;CGFloat iconH = 50;// 0. 創(chuàng)建書(shū)UIView *book = [UIView new];book.backgroundColor = [UIColor redColor];[self.shopView addSubview:book];// 計(jì)算書(shū)的位置// 獲得索引NSUInteger index = [self.books count];// 計(jì)算橫間距 marginCGFloat margin = (self.shopView.frame.size.width - clos * W) / (clos - 1);// 書(shū) frame 的 XCGFloat x = (index % clos) * (W + margin);// 書(shū) frame 的 YCGFloat y = (index / clos) * (H + margin);book.frame = CGRectMake(x, y, W, H);// 1. 創(chuàng)建書(shū)圖標(biāo)UIImageView *bookIcon = [UIImageView new];bookIcon.image = [UIImage imageNamed:@"0"];bookIcon.frame = CGRectMake(0, 0, W, iconH);[book addSubview:bookIcon];// 2.書(shū)名UILabel *bookName = [UILabel new];bookName.frame = CGRectMake(0, iconH, W, H-iconH);bookName.text = @"book1";bookName.textAlignment = NSTextAlignmentCenter;[book addSubview:bookName];// 3.添加到數(shù)組(分開(kāi)寫(xiě)好像很難明確如何添加這本書(shū))[self.books addObject:book];}

效果圖如下

書(shū)數(shù)據(jù)加載方式和對(duì)比

到這里購(gòu)物車?yán)锏臅?shū)已經(jīng)可以隨意添加了,并且可以根據(jù)用戶的點(diǎn)擊,無(wú)限制的添加。
如果項(xiàng)目需求修改了,比如變成5列了,寬高什么的也是根據(jù)項(xiàng)目自行修改就行。
九宮格布局的代碼已經(jīng)完成了。

現(xiàn)在需要注意的問(wèn)題是,“書(shū)”的屬性數(shù)據(jù)的添加問(wèn)題,現(xiàn)在簡(jiǎn)單的來(lái)說(shuō),書(shū)屬性有 :書(shū)名 + icon。

“書(shū)”的各屬性值,應(yīng)該如何賦值呢?



幾種簡(jiǎn)單數(shù)據(jù)加載方法與對(duì)比

  • 直接根據(jù) index 來(lái)進(jìn)行if判斷,逐個(gè)添加數(shù)據(jù)
if (index == 0) {bookIcon.image = [UIImage imageNamed:@"0"];bookName.text = @"Book1";}else if(index == 1){bookIcon.image = [UIImage imageNamed:@"1"];bookName.text = @"Book2";}else if(index == 2){bookIcon.image = [UIImage imageNamed:@"2"];bookName.text = @"Book3";}...
  • 創(chuàng)建一個(gè)書(shū)的數(shù)組,數(shù)組存放對(duì)應(yīng)的字典,作為書(shū)的屬性方法的數(shù)據(jù)源,從中取值
// 0.創(chuàng)建書(shū)的數(shù)據(jù)源self.books = @[@{@"icon":@"0",@"name":@"book1"},@{@"icon":@"1",@"name":@"book2"},@{@"icon":@"2",@"name":@"book3"},@{@"icon":@"3",@"name":@"book4"},];// 1.書(shū)圖標(biāo) bookIcon.image = [UIImage imageNamed:self.books[index][@"icon"]]; // 2.書(shū)名 bookName.text = self.books[index][@"name"];
  • 進(jìn)一步分離數(shù)據(jù),將數(shù)據(jù)信息放到其他文件中,用的時(shí)候從文件中讀取
// 獲取文件路徑NSString *books = [[NSBundle mainBundle] pathForResource:@"bookData" ofType:@"plist"];// 加載路徑中內(nèi)容放到數(shù)組中_books = [NSMutableArray arrayWithContentsOfFile:books];// 1.書(shū)圖標(biāo)bookIcon.image = [UIImage imageNamed:self.books[index][@"icon"]]; // 2.書(shū)名bookName.text = self.books[index][@"name"];

對(duì)于三種方法簡(jiǎn)單的比較和點(diǎn)評(píng)

  • 第一種直接if判斷index的位置

    • 直接把動(dòng)態(tài)判斷代碼寫(xiě)到代碼中,過(guò)于死板
    • 代碼耦合性太高,及其不利于后期擴(kuò)展,如果加數(shù)據(jù)簡(jiǎn)直是惡魔
    • 一些死布局并且元素個(gè)數(shù)極少(幾個(gè))的時(shí)候可以使用
    • 代碼重復(fù)性高,技術(shù)含量低
  • 第二種把數(shù)據(jù)代碼獨(dú)立出來(lái)放到一個(gè)數(shù)組中

    • 避免了第一種直接寫(xiě)到代碼中的低效且惡心的做法
    • 代碼還是和數(shù)據(jù)耦合到一起了,如果后期修改需要修改代碼
    • 如果數(shù)據(jù)量大,及其不利于后期管理和數(shù)據(jù)的修改
    • 相比第一種有明顯的分離,是一種進(jìn)步
  • 第三種代碼和數(shù)據(jù)分離,放到外部文件中

    • 徹底代碼和數(shù)據(jù)分離,耦合性低,易于擴(kuò)展
    • 數(shù)據(jù)放到文件中、后期添加或者修改數(shù)據(jù)無(wú)需改動(dòng)代碼、更加獨(dú)立
    • 代碼更簡(jiǎn)潔直觀,只需關(guān)注功能和布局
    • 適合企業(yè)開(kāi)發(fā)、這是一種通用方式(網(wǎng)絡(luò)應(yīng)用更是如此)

plist文件介紹和使用

簡(jiǎn)介

  • plist文件全稱:Property List文件,中文又叫屬性列表文件。
  • 是蘋(píng)果平臺(tái)上常用的一種資源描述類文件。
  • 它存儲(chǔ)的屬性一般都是Xcode里面的基本數(shù)據(jù)類型或者OC里面的對(duì)應(yīng)類型(NSDictionary,NSArray,NSString等)
  • Xcode會(huì)自動(dòng)進(jìn)行解析成可以打開(kāi)和合上的層疊格式
  • 用文本文件打開(kāi)直接就是XML格式的鍵值對(duì)

plist文件的創(chuàng)建

plist的創(chuàng)建一般直接用Xcode創(chuàng)建,然后在里面添加對(duì)應(yīng)的key和value,(幾乎沒(méi)有人會(huì)手寫(xiě)plist文件)

plist文件的使用

plist使用就和其他的文件用法一樣,先讀取目標(biāo)文件的路徑在根據(jù)路徑加載到數(shù)組中。

// 獲取文件路徑NSString *books = [[NSBundle mainBundle] pathForResource:@"bookData" ofType:@"plist"];// 加載路徑中內(nèi)容放到數(shù)組中_books = [NSMutableArray arrayWithContentsOfFile:books];

plist使用注意

我們自己創(chuàng)建plist文件的時(shí)候不能使用info/Info.plist命名

由于每次創(chuàng)建工程的時(shí)候,系統(tǒng)會(huì)自動(dòng)生成一個(gè)對(duì)該項(xiàng)目信息進(jìn)行描述的info.plist,它會(huì)記錄項(xiàng)目的一些包名、項(xiàng)目名、開(kāi)發(fā)工具、版本和其他項(xiàng)目的基礎(chǔ)信息。

所以我們自己創(chuàng)建plist文件的時(shí)候不能使用info/Info.plist

這是為了不和系統(tǒng)的info.plist混淆,實(shí)際上自己創(chuàng)建一個(gè)info.plist文件和系統(tǒng)重名之后項(xiàng)目是運(yùn)行不了的。

懶加載(lazyLoad) -- 提升性能

懶加載又叫延遲加載,由于項(xiàng)目運(yùn)行時(shí)候很多數(shù)據(jù)用不到,可以暫時(shí)不創(chuàng)建,等到用的時(shí)候在創(chuàng)建,這樣節(jié)省系統(tǒng)性能。

如以上項(xiàng)目中,就是在添加書(shū)的方法中每次創(chuàng)建書(shū)籍?dāng)?shù)組

// 添加書(shū) - (IBAction)addBook:(id)sender {self.books = @[@{@"icon":@"0",@"name":@"book1"},@{@"icon":@"1",@"name":@"book2"},@{@"icon":@"2",@"name":@"book3"},@{@"icon":@"3",@"name":@"book4"},];// 設(shè)置列數(shù)為 3int clos = 3;// 設(shè)置書(shū)的寬高分別為 W HCGFloat W = 60;CGFloat H = 70;CGFloat iconH = 50;// 0. 創(chuàng)建書(shū)UIView *book = [UIView new];book.backgroundColor = [UIColor redColor];

這樣其實(shí)非常耗性能,每次都要?jiǎng)?chuàng)建一個(gè)數(shù)組,然后用過(guò)一次就沒(méi)有用了,對(duì)此可以進(jìn)行一個(gè)優(yōu)化,對(duì)于該書(shū)籍?dāng)?shù)據(jù)其實(shí)就是一個(gè)固定數(shù)據(jù),每次用一下,用的時(shí)候再創(chuàng)建,不用的時(shí)候就不管了,這里正好用懶加載最好了。

懶加載實(shí)際上就是一個(gè)get方法

// 懶加載書(shū)籍?dāng)?shù)據(jù) - (NSMutableArray *)books {if (_books == nil) {// 獲取文件路徑NSString *books = [[NSBundle mainBundle] pathForResource:@"bookData" ofType:@"plist"];// 加載路徑中內(nèi)容放到數(shù)組中_books = [NSMutableArray arrayWithContentsOfFile:books];}return _books; }// 使用的時(shí)候,直接用數(shù)組就行 bookIcon.image = [UIImage imageNamed:self.books[index][@"icon"]]; bookName.text = self.books[index][@"name"];

MVC 思想的介紹和引入

以上的小Demo,已經(jīng)告一段落了,可以實(shí)現(xiàn)把文件中書(shū)籍?dāng)?shù)據(jù),按九宮格的布局添加到購(gòu)物車中,也可以一一刪除。

思考

還有什么可以改進(jìn)的嗎?
數(shù)據(jù)就這樣存放到數(shù)組中就完美了嗎?
每次用書(shū)的數(shù)據(jù)的時(shí)候,直接從數(shù)組總?cè)〕鰜?lái)確實(shí)方便,但是這樣真的足夠完美嗎?
現(xiàn)在的所有代碼幾乎都在一個(gè)文件中,如果項(xiàng)目大了也這樣寫(xiě)嗎?
上面把對(duì)應(yīng)的數(shù)據(jù)加載方式分離到文件中了,其他的業(yè)務(wù)邏輯能不能也分離一下,能不能讓項(xiàng)目的結(jié)構(gòu)更加清晰?

待著這些思考,答案是肯定的,項(xiàng)目的代碼還是非常耦合的,并且有個(gè)致命的缺點(diǎn)。

  • 每次從數(shù)組中取書(shū)的信息時(shí)候都自己寫(xiě)key值,self.books[index][@"icon"] 如果這個(gè)“icon“手誤寫(xiě)錯(cuò),編輯器一點(diǎn)提示也沒(méi)有
  • 如果書(shū)有很多屬性,每次手寫(xiě)key值很頭痛,并且代碼看起來(lái)很糟

所以我們需要一種新的方式:因?yàn)闀?shū)是一個(gè)對(duì)象,可以把它封裝成對(duì)象,它用有自己的各種屬性和方法。這樣做有幾點(diǎn)好處:

  • 便于管理,在使用的時(shí)候直接調(diào)用屬性的get方法就行。
  • 系統(tǒng)會(huì)自動(dòng)提示get方法,安全性高不會(huì)出錯(cuò),如果寫(xiě)錯(cuò)系統(tǒng)會(huì)報(bào)錯(cuò)。
  • 代碼封裝性好,書(shū)就是書(shū),而不是每次到數(shù)組中去取字典根據(jù)對(duì)應(yīng)的key來(lái)取值
  • 擴(kuò)展性好,如果日后需要添加新的屬性和方法,直接在”書(shū)“類中加就行

MVC介紹

經(jīng)過(guò)上面的分析,可以確定的是書(shū)應(yīng)該獨(dú)立封裝起來(lái)保存數(shù)據(jù),頁(yè)面邏輯也應(yīng)該單獨(dú)管理,至于ViewController恰好就是兩者的橋梁。這樣的設(shè)計(jì)模式就是MVC

  • M : (Model)數(shù)據(jù)模型,用來(lái)存儲(chǔ)和保存數(shù)據(jù)
  • V : (View)UI視圖,用來(lái)展示給用戶看的頁(yè)面,一些復(fù)雜的頁(yè)面要封裝起來(lái)放到里面單獨(dú)管理。
  • C: (Controller)控制器,是兩者的橋梁,主要用來(lái)處理業(yè)務(wù)邏輯。

使用MVC模式可以很好的簡(jiǎn)化項(xiàng)目代碼,對(duì)不同的模塊進(jìn)行封裝,降低耦合性,擴(kuò)展性也會(huì)得到提高,MVC是企業(yè)開(kāi)發(fā)常用的設(shè)計(jì)模式。

MVC的分層封裝和使用

經(jīng)過(guò)分析可知,在此小項(xiàng)目中,書(shū)和展示的書(shū)的UI和ViewController對(duì)應(yīng)MVC的關(guān)系:

  • 書(shū) -- Model:用來(lái)封裝書(shū)的各種屬性信息和方法
  • 書(shū)UI -- View:封裝書(shū)這個(gè)小表象,用于展示給用戶看
  • ViewController -- Controller:用來(lái)處理整體的業(yè)務(wù)邏輯,優(yōu)化代碼



廢話不多說(shuō)了,上各層的代碼

  • 下面是書(shū)的代碼封裝:存儲(chǔ)書(shū)的數(shù)據(jù)和方法
頭文件 XYBook.h@interface XYBook : NSObject// 書(shū)圖標(biāo) @property (nonatomic, copy) NSString *icon; // 書(shū)名字 @property (nonatomic, copy) NSString *name;// 對(duì)象方法,返回自己對(duì)象 - (instancetype)initWithDict:(NSDictionary *)dict; // 類方法,返回自己對(duì)象 + (instancetype)bookWithDict:(NSDictionary *)dict; @end#import "XYBook.h"@implementation XYBook- (instancetype)initWithDict:(NSDictionary *)dict {if (self = [super init]) {[self setValuesForKeysWithDictionary:dict];}return self; }+ (instancetype)bookWithDict:(NSDictionary *)dict {return [[self alloc] initWithDict:dict]; } @end
  • 書(shū)的UI的封裝:集中布局,減少控制器代碼,優(yōu)化控制器邏輯
XYBookView.h 頭文件#import <UIKit/UIKit.h> @class XYBook;@interface XYBookView : UIView// 只放一個(gè)數(shù)據(jù)屬性用來(lái)賦值,內(nèi)部布局,放到.m 中自己管,不暴露給外界 @property (nonatomic, strong) XYBook *book;@end實(shí)現(xiàn)文件 .m文件 #import "XYBookView.h" #include "XYBook.h"@interface XYBookView ()@property (nonatomic, weak) UIImageView *icon;@property (nonatomic, weak) UILabel *label;@end@implementation XYBookView- (instancetype)initWithFrame:(CGRect)frame {if (self = [super initWithFrame:frame]) {// 1. 創(chuàng)建書(shū)圖標(biāo)UIImageView *icon = [UIImageView new];self.icon = icon;[self addSubview:self.icon];// 2.書(shū)名UILabel *bookName = [UILabel new];bookName.textAlignment = NSTextAlignmentCenter;self.label = bookName;[self addSubview:self.label];}return self; }// 重寫(xiě)布局 - (void)layoutSubviews {[super layoutSubviews];CGSize size = self.frame.size;self.icon.frame = CGRectMake(0, 0, size.width , size.height * 0.7);self.label.frame = CGRectMake(0, size.height * 0.7, size.width, size.height *(1 - 0.7));}// 設(shè)置書(shū)的屬性 - (void)setBook:(XYBook *)book {_book = book;self.icon.image = [UIImage imageNamed:book.icon];self.label.text = book.name; } @end
  • 控制器:不管細(xì)節(jié),專注處理邏輯
// 懶加載數(shù)據(jù)源 - (NSMutableArray *)books {if (_books == nil) {_books = [NSMutableArray array];// 獲取文件路徑NSString *books = [[NSBundle mainBundle] pathForResource:@"bookdata" ofType:@"plist"];// 加載路徑中內(nèi)容放到數(shù)組中NSMutableArray *arrayM = [NSMutableArray arrayWithContentsOfFile:books];for (NSDictionary *dict in arrayM) {XYBook *book = [XYBook bookWithDict:dict];[_books addObject:book];}}return _books; }// 添加書(shū) - (IBAction)addBook:(id)sender {// 設(shè)置列數(shù)為 3int clos = 3;// 設(shè)置書(shū)的寬高分別為 W HCGFloat W = 60;CGFloat H = 70;// 0. 創(chuàng)建書(shū)XYBookView *bookView = [XYBookView new];bookView.backgroundColor = [UIColor redColor];// 計(jì)算書(shū)的位置// 獲得索引NSUInteger index = [self.shopView.subviews count];// 計(jì)算橫間距 marginCGFloat margin = (self.shopView.frame.size.width - clos * W) / (clos - 1);// 書(shū) frame 的 XCGFloat x = (index % clos) * (W + margin);// 書(shū) frame 的 YCGFloat y = (index / clos) * (H + margin);bookView.frame = CGRectMake(x, y, W, H);[self.shopView addSubview:bookView];// 給書(shū)的UI設(shè)置數(shù)據(jù)bookView.book = self.books[index];[self checkState];self.removeBtn.enabled = YES; }// 移除書(shū) - (IBAction)removeBook:(id)sender {[[self.shopView.subviews lastObject] removeFromSuperview];[self checkState];self.addBtn.enabled = YES; }

以上就是對(duì)于本Demo的最終MVC封裝版
不同部分各司其職,負(fù)責(zé)自己的模塊
項(xiàng)目的健壯性和封裝性也也到了對(duì)應(yīng)的提高



小記

一個(gè)簡(jiǎn)單的九宮格購(gòu)物車的小Demo,真是麻雀雖小五臟俱全。

關(guān)于這個(gè)項(xiàng)目的完整代碼,歡迎私聊或評(píng)論找我要,如果文章有任何問(wèn)題或有其他技術(shù)問(wèn)題,歡迎隨時(shí)和我交流。

最后放一張項(xiàng)目效果圖

?

轉(zhuǎn)載于:https://www.cnblogs.com/xiaoyouPrince/p/6494710.html

總結(jié)

以上是生活随笔為你收集整理的iOS回顾笔记( 02 ) -- 由九宫格布局引发的一系列“惨案”的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。