国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[iOS基礎控件-5.5]代理設計模式(基于”APP列表"練習)

2019-11-14 19:49:03
字體:
來源:轉載
供稿:網友
A.概述
     在"[iOS基礎控件 - 4.4] APP列表 進一步封裝,初見MVC模式”上進一步改進,給“下載”按鈕加上效果、功能
     1.按鈕點擊后,顯示為“已下載”,并且不可以再按
     2.在屏幕中間彈出一個消息框,通知消息“xx已經被安裝”,慢慢消失
     3.消息框樣式為圓角半透明
 
Image(67)
 
 
B.不使用代理模式,使用app空間組和主View之間的父子View關系
1.在主View中創建一個消息框
 
主View控制器:ViewController.m
   
 1  // 創建下載成功消息框 2     CGFloat labelWidth = 200; 3     CGFloat labelHeight = 50; 4     CGFloat labelX = (self.view.frame.size.width - labelWidth) / 2; 5     CGFloat labelY = (self.view.frame.size.height - labelHeight) / 2; 6     UILabel *successMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, labelWidth, labelHeight)]; 7     8     // 設置圓角矩形樣式 9     successMsgLabel.layer.cornerRadius = 10.0;10     successMsgLabel.layer.masksToBounds = YES;11    12     // 設置全透明隱藏13     successMsgLabel.alpha = 0;14    15     successMsgLabel.textColor = [UIColor whiteColor];16     successMsgLabel.backgroundColor = [UIColor grayColor];17     [successMsgLabel setTextAlignment:NSTextAlignmentCenter];18     successMsgLabel.tag = 10;19   20     [self.view addSubview:successMsgLabel];
 
2.直接在app空間組的控制器中操作消息框,加入到父控件(主View)
 
app控件組View:AppView.m
 1 // 點擊下載按鈕 2 - (IBAction)onDownloadButtonClick { 3     // 更改“下載”按鈕樣式 4     [self.downloadButton setTitle:@"已下載" forState:UIControlStateDisabled]; 5     self.downloadButton.enabled = NO; 6    7     // 拿到消息框 8     UILabel *successMsgLabel = [self.superview viewWithTag:10]; 9     successMsgLabel.text = [NSString stringWithFormat:@"成功安裝了%@", self.appData.name];10     successMsgLabel.alpha = 0.7;11    12     // 使用動畫13     [UIView beginAnimations:nil context:nil];14     [UIView setAnimationDuration:2];15     successMsgLabel.alpha = 0;16     [UIView commitAnimations];17 }
 
缺點:view的父子關系規定了這兩個view的層次關系,依賴性、耦合性太強,導致各個view都不能自由修改
 
C.不使用代理模式,在app控件組的view中將主View作為一個成員
1.在控件組AppView中創建主View的引用
控件組 AppView.h
1 // 存儲主View的引用2 @PRoperty (nonatomic, weak) UIView *vcView;
 
2.在主View逐個加載控件組的時候,設置主View的引用
ViewController.m
 1  for (int index=0; index<self.apps.count; index++) { 2         App *appData = self.apps[index]; 3  4         // 1.創建View 5         AppView *appView = [AppView appViewWithApp:appData]; 6         7         // 2.定義每個app的位置、尺寸 8         CGFloat appX = marginX + column * (marginX + APP_WIDTH); 9         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);10         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);11        12         // 設置每個app控件view的主view引用13         appView.vcView = self.view;14        15         // 3.加入此app信息到總view16         [self.view addSubview:appView];17        18         column++;19         if (column == appColumnCount) {20             column = 0;21             row++;22         }
 
3.控件組AppView使用主View引用代替父控件引用
AppView.m
 1 // 點擊下載按鈕 2 - (IBAction)onDownloadButtonClick { 3     // 更改“下載”按鈕樣式 4     [self.downloadButton setTitle:@"已下載" forState:UIControlStateDisabled]; 5     self.downloadButton.enabled = NO; 6     7     // 創建消息框 8     UILabel *successMsgLabel = [self.vcView viewWithTag:10]; 9     successMsgLabel.text = [NSString stringWithFormat:@"成功安裝了%@", self.appData.name];10     successMsgLabel.alpha = 0.7;11    12     // 使用動畫13     [UIView beginAnimations:nil context:nil];14     [UIView setAnimationDuration:2];15     successMsgLabel.alpha = 0;16     [UIView commitAnimations];17 }
 
缺點:控件組AppView的下載事件中取得控制器來彈出消息框,還是依賴于主View,耦合性強
 
 
D.暴露控件組AppView的“下載”按鈕,在主控制器中編寫“下載”事件方法,綁定方法
1.AppView暴露“下載”按鈕控件給外部
AppView.h
1 // 將“下載”按鈕控件移到 .h 文件中暴露2 @property (weak, nonatomic) IBOutlet UIButton *downloadButton;
 
2.在控制器中編寫“下載”單擊事件方法
ViewController.m
 1 // 控制器創建“下載”按鈕點擊事件 2 - (IBAction)onAppViewDownloadButtonClick:(UIButton *) downloadButton { 3     // 更改“下載”按鈕樣式 4     [downloadButton setTitle:@"已下載" forState:UIControlStateDisabled]; 5     downloadButton.enabled = NO; 6     7     // 創建消息框 8     UILabel *successMsgLabel = [self.view viewWithTag:99]; 9    10     App *app = self.apps[downloadButton.tag];11     successMsgLabel.text = [NSString stringWithFormat:@"成功安裝了%@", app.name];12     successMsgLabel.alpha = 0.7;13    14     // 使用動畫15     [UIView beginAnimations:nil context:nil];16     [UIView setAnimationDuration:2];17     successMsgLabel.alpha = 0;18     [UIView commitAnimations];19 }20 21 @end
 
3.給每個AppView的“下載”按鈕綁定方法
   
 1  for (int index=0; index<self.apps.count; index++) { 2         App *appData = self.apps[index]; 3  4         // 1.創建View 5         AppView *appView = [AppView appViewWithApp:appData]; 6         7         // 2.定義每個app的位置、尺寸 8         CGFloat appX = marginX + column * (marginX + APP_WIDTH); 9         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);10         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);11        12         // 存儲每個AppView對應的AppData數據索引在tag中13         appView.downloadButton.tag = index;14        15         // 綁定每個AppView中的“下載”按鈕點擊事件16         [appView.downloadButton addTarget:self action:@selector(onAppViewDownloadButtonClick:) forControlEvents:UIControlEventTouchUpInside];17  18         // 3.加入此app信息到總view19         [self.view addSubview:appView];20        21         column++;22         if (column == appColumnCount) {23             column = 0;24             row++;25         }26     }
 
缺點:依賴于AppView暴露的“下載”按鈕,不能被修改
 
 
E.代理模式
1.原則:誰擁有資源,誰調用
     添加label到控制器的邏輯:控制器來做
     當點擊“下載”按鈕的時候,控件組AppView的按鈕點擊事件應該通知控制器,要執行添加label到控制器view的操作
     控制器監聽控件組AppView的下載按鈕的點擊
 
1.聲明代理
AppView.h
1 // 定義代理的協議2 @protocol AppViewDelegate <NSObject>3 // “下載”按鈕被點擊事件4 @optional5 - (void) appViewClickedDownloadButton:(AppView *) appView;6 @end
 
2.在AppView中創建代理引用
AppView.h
1 @interface AppView : UIView2 // 代理3 @property(nonatomic, weak) id<AppViewDelegate> delegate;4 ...5 @end
 
3.控制器遵守AppViewDelegate,使其擁有稱為代理的資格
1 ViewController.m2 @interface ViewController () <AppViewDelegate>3 ...4 @end
 
4.實現代理方法
ViewController.m
 1 // “下載”按鈕點擊的代理方法 2 - (void)appViewClickedDownloadButton:(AppView *)appView { 3     // 創建下載成功消息框 4     CGFloat labelWidth = 200; 5     CGFloat labelHeight = 50; 6     CGFloat labelX = (self.view.frame.size.width - labelWidth) / 2; 7     CGFloat labelY = (self.view.frame.size.height - labelHeight) / 2; 8     UILabel *successMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, labelWidth, labelHeight)]; 9    10     // 設置圓角矩形樣式11     successMsgLabel.layer.cornerRadius = 10.0;12     successMsgLabel.layer.masksToBounds = YES;13    14     // 設置全透明隱藏15     successMsgLabel.alpha = 0;16    17     successMsgLabel.textColor = [UIColor whiteColor];18     successMsgLabel.backgroundColor = [UIColor grayColor];19     [successMsgLabel setTextAlignment:NSTextAlignmentCenter];20 21     successMsgLabel.text = [NSString stringWithFormat:@"成功安裝了%@", appView.appData.name];22     successMsgLabel.alpha = 0.7;23    24     // 使用動畫25     [UIView beginAnimations:nil context:nil];26     [UIView setAnimationDuration:2];27     successMsgLabel.alpha = 0;28     [UIView commitAnimations];29    30     [self.view addSubview:successMsgLabel];31 }
 
5.給每一個AppView設置代理
ViewController.m
  
 1   for (int index=0; index<self.apps.count; index++) { 2         App *appData = self.apps[index]; 3  4         // 1.創建View 5         AppView *appView = [AppView appViewWithApp:appData]; 6         7         // 2.定義每個app的位置、尺寸 8         CGFloat appX = marginX + column * (marginX + APP_WIDTH); 9         CGFloat appY = marginY + row * (marginY + APP_HEIGHT);10         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT);11        12         // 設置代理13         appView.delegate = self;14        15         // 3.加入此app信息到總view16         [self.view addSubview:appView];17        18         column++;19         if (column == appColumnCount) {20             column = 0;21             row++;22         }23     }
 
6.點擊“下載”按鈕的時候,通知代理
AppView.m
 1 // 點擊下載按鈕 2 - (IBAction)onDownloadButtonClick { 3     // 更改“下載”按鈕樣式 4     [self.downloadButton setTitle:@"已下載" forState:UIControlStateDisabled]; 5     self.downloadButton.enabled = NO; 6  7     // 通知代理 8     // 檢查是否實現了代理方法 9     if ([self.delegate respondsToSelector:@selector(appViewClickedDownloadButton:)]) {10         [self.delegate appViewClickedDownloadButton:self];11     }12 }
 
主要代碼:
Model:
 1 App.h 2 // 3 //  App.h 4 //  01-應用管理 5 // 6 //  Created by hellovoidworld on 14/11/25. 7 //  Copyright (c) 2014年 hellovoidworld. All rights reserved. 8 // 9 10 #import <Foundation/Foundation.h>11 12 @interface App : NSObject13 14 /**15 copy : NSString16 strong: 一般對象17 weak: UI控件18 assign: 基本數據類型19 */20 21 /**22 名稱23 */24 @property(nonatomic, copy) NSString *name;25 26 /**27 圖標28 */29 @property(nonatomic, copy) NSString *icon;30 31 /**32 自定義構造方法33 通過字典來初始化模型對象34 */35 - (instancetype) initWithDictionary:(NSDictionary *) dictionary;36 37 + (instancetype) appWithDictionary:(NSDictionary *) dictionary;38 39 @end
 
App.m
 1 // 2 //  App.m 3 //  01-應用管理 4 // 5 //  Created by hellovoidworld on 14/11/25. 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8  9 #import "App.h"10 11 #define ICON_KEY @"icon"12 #define NAME_KEY @"name"13 14 @implementation App15 16 - (instancetype) initWithDictionary:(NSDictionary *) dictionary {17     if (self = [super init]) {18         self.name = dictionary[NAME_KEY];19         self.icon = dictionary[ICON_KEY];20     }21    22     return self;23 }24 25 26 + (instancetype) appWithDictionary:(NSDictionary *) dictionary {27     // 使用self代表類名代替真實類名,防止子類調用出錯28     return [[self alloc] initWithDictionary:dictionary];29 }30 31 @end
 
View:
 1 AppView.h 2 // 3 //  AppView.h 4 //  01-應用管理 5 // 6 //  Created by hellovoidworld on 14/11/25. 7 //  Copyright (c) 2014年 hellovoidworld. All rights reserved. 8 // 9 10 #import <UIKit/UIKit.h>11 12 @class App, AppView;13 14 // 定義代理的協議15 @protocol AppViewDelegate <NSObject>16 // “下載”按鈕被點擊事件17 @optional18 - (void) appViewClickedDownloadButton:(AppView *) appView;19 @end20 21 @interface AppView : UIView22 23 // 代理24 @property(nonatomic, weak) id<AppViewDelegate> delegate;25 26 // 在Controller和View之間傳輸的Model數據27 @property(nonatomic, strong) App *appData;28 29 30 // 自定義將Model數據加載到View的構造方法31 - (instancetype) initWithApp:(App *) appData;32 // 自定義構造的類方法33 + (instancetype) appViewWithApp:(App *) appData;34 // 返回一個不帶Model數據的類構造方法35 + (instancetype) appView;36 37 38 @end
 
AppView.m
 1 // 2 //  AppView.m 3 //  01-應用管理 4 // 5 //  Created by hellovoidworld on 14/11/25. 6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved. 7 // 8  9 #import "AppView.h"10 #import "App.h"11 12 // 封裝私有屬性13 @interface AppView()14 15 // 封裝View中的控件,只允許自己訪問16 @property (weak, nonatomic) IBOutlet UIImageView *iconView;17 @property (weak, nonatomic) IBOutlet UILabel *nameLabel;18 @property (weak, nonatomic) IBOutlet UIButton *downloadButton;19 20 21 22 - (IBAction)onDownloadButtonClick;23 24 @end25 26 @implementation AppView27 28 - (void)setAppData:(App *)appData {29     // 1.賦值Medel成員30     _appData = appData;31    32     // 2.設置圖片33     self.iconView.image = [UIImage imageNamed:appData.icon];34     // 3.設置名字35     self.nameLabel.text = appData.name;36 }37 38 // 自定義將Model數據加載到View的構造方法39 - (instancetype) initWithApp:(App *) appData {40     // 1.從NIB取得控件41     UINib *nib = [UINib nibWithNibName:@"app" bundle:[NSBundle mainBundle]];42     NSArray *viewArray = [nib instantiateWithOwner:nil options:nil];43     AppView *appView = [viewArray lastObject];44    45     // 2.加載Model46     appView.appData = appData;47    48     return appView;49 }50 51 // 自定義構造的類方法52 + (instancetype) appViewWithApp:(App *) appData {53     return [[self alloc] initWithApp:appData];54 }55 56 // 返回一個不帶Model數據的類構造方法57 + (instancetype) appView {58     return [self appViewWithApp:nil];59 }60 61 // 點擊下載按鈕62 - (IBAction)onDownloadButtonClick {63     // 更改“下載”按鈕樣式64     [self.downloadButton setTitle:@"已下載" forState:UIControlStateDisabled];65     self.downloadButton.enabled = NO;66 67     // 通知代理68     // 檢查是否實現了代理方法69     if ([self.delegate respondsToSelector:@selector(appViewClickedDownloadButton:)]) {70         [self.delegate appViewClickedDownloadButton:self];71     }72 }73 74 @end
 
Controller:
ViewController.m
  1 //  2 //  ViewController.m  3 //  01-應用管理  4 //  5 //  Created by hellovoidworld on 14/11/24.  6 //  Copyright (c) 2014年 hellovoidworld. All rights reserved.  7 //  8   9 #import "ViewController.h" 10 #import "App.h" 11 #import "AppView.h" 12  13 #define ICON_KEY @"icon" 14 #define NAME_KEY @"name" 15 #define APP_WIDTH 85 16 #define APP_HEIGHT 90 17 #define MARGIN_HEAD 20 18 #define ICON_WIDTH 50 19 #define ICON_HEIGHT 50 20 #define NAME_WIDTH APP_WIDTH 21 #define NAME_HEIGHT 20 22 #define DOWNLOAD_WIDTH (APP_WIDTH - 20) 23 #define DOWNLOAD_HEIGHT 20 24  25 @interface ViewController () <AppViewDelegate> 26  27 /** 存放應用信息 */ 28 @property(nonatomic, strong) NSArray *apps; // 應用列表 29  30 @end 31  32 @implementation ViewController 33  34 - (void)viewDidLoad { 35     [super viewDidLoad]; 36     // Do any additional setup after loading the view, typically from a nib. 37     38     [self loadApps]; 39 } 40  41 - (void)didReceiveMemoryWarning { 42     [super didReceiveMemoryWarning]; 43     // Dispose of any resources that can be recreated. 44 } 45  46 #pragma mark 取得應用列表 47 - (NSArray *) apps { 48     if (nil == _apps) { 49         // 1.獲得plist的全路徑 50         NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil]; 51         52         // 2.加載數據 53         NSArray *dictArray  = [NSArray arrayWithContentsOfFile:path]; 54         55         // 3.將dictArray里面的所有字典轉成模型,放到新數組中 56         NSMutableArray *appArray = [NSMutableArray array]; 57         for (NSDictionary *dict in dictArray) { 58             // 3.1創建模型對象 59             App *app = [App appWithDictionary:dict]; 60             61             // 3.2 添加到app數組中 62             [appArray addObject:app]; 63         } 64         65         _apps = appArray; 66     } 67  68     return _apps; 69 } 70  71 #pragma mark 加載全部應用列表 72 - (void) loadApps { 73     int appColumnCount = [self appColumnCount]; 74     int appRowCount = [self appRowCount]; 75     76     CGFloat marginX = (self.view.frame.size.width - APP_WIDTH * appColumnCount) / (appColumnCount + 1); 77     CGFloat marginY = (self.view.frame.size.height - APP_HEIGHT * appRowCount) / (appRowCount + 1) + MARGIN_HEAD; 78     79     int column = 0; 80     int row = 0; 81     for (int index=0; index<self.apps.count; index++) { 82         App *appData = self.apps[index]; 83  84         // 1.創建View 85         AppView *appView = [AppView appViewWithApp:appData]; 86         87         // 2.定義每個app的位置、尺寸 88         CGFloat appX = marginX + column * (marginX + APP_WIDTH); 89         CGFloat appY = marginY + row * (marginY + APP_HEIGHT); 90         appView.frame = CGRectMake(appX, appY, APP_WIDTH, APP_HEIGHT); 91         92         // 設置代理 93         appView.delegate = self; 94         95         // 3.加入此app信息到總view 96         [self.view addSubview:appView]; 97         98         column++; 99         if (column == appColumnCount) {100             column = 0;101             row++;102         }103     }104    105 }106 107 108 #pragma mark 計算列數109 - (int) appColumnCount {110     int count = 0;111     count = self.view.frame.size.width / APP_WIDTH;112    113     if ((int)self.view.frame.size.width % (int)APP_WIDTH == 0) {114         count--;115     }116    117     return count;118 }119 120 #pragma mark 計算行數121 - (int) appRowCount {122     int count = 0;123     count = (self.view.frame.size.height - MARGIN_HEAD) / APP_HEIGHT;124    125     if ((int)(self.view.frame.size.height - MARGIN_HEAD) % (int)APP_HEIGHT == 0) {126         count--;127     }128    129     return count;130 }131 132 // “下載”按鈕點擊的代理方法133 - (void)appViewClickedDownloadButton:(AppView *)appView {134     // 創建下載成功消息框135     CGFloat labelWidth = 200;136     CGFloat labelHeight = 50;137     CGFloat labelX = (self.view.frame.size.width - labelWidth) / 2;138     CGFloat labelY = (self.view.frame.size.height - labelHeight) / 2;139     UILabel *successMsgLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelX, labelY, labelWidth, labelHeight)];140    141     // 設置圓角矩形樣式142     successMsgLabel.layer.cornerRadius = 10.0;143     successMsgLabel.layer.masksToBounds = YES;144    145     // 設置全透明隱藏146     successMsgLabel.alpha = 0;147    148     successMsgLabel.textColor = [UIColor whiteColor];149     successMsgLabel.backgroundColor = [UIColor grayColor];150     [successMsgLabel setTextAlignment:NSTextAlignmentCenter];151 152     successMsgLabel.text = [NSString stringWithFormat:@"成功安裝了%@", appView.appData.name];153     successMsgLabel.alpha = 0.7;154    155     // 使用動畫156     [UIView beginAnimations:nil context:nil];157     [UIView setAnimationDuration:2];158     successMsgLabel.alpha = 0;159     [UIView commitAnimations];160    161     [self.view addSubview:successMsgLabel];162 }163 164 @end

 

 

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 双江| 湖北省| 临潭县| 犍为县| 天峻县| 且末县| 和田市| 辽源市| 景东| 宝清县| 昭通市| 龙胜| 杭锦后旗| 平邑县| 蒙城县| 乐陵市| 彭水| 尼玛县| 东源县| 博湖县| 光山县| 平顶山市| 佛山市| 丰镇市| 凤城市| 潮州市| 永福县| 巧家县| 永德县| 乌鲁木齐县| 行唐县| 浮山县| 寿光市| 宝丰县| 平和县| 山东| 平湖市| 林州市| 永修县| 元谋县| 麻江县|