一個java程序員自學IOS開發之路(六)

2015/10/28數組

Day 27app

今天學習了即時通信應用的UI佈局,只是簡單的利用UITableView展現數據框架

 

第一步ide

先利用storyboard把頁面的框架搭起來佈局

  

顯示的數據是存在plist文件裏的,因此要把他們轉成模型post

 

typedef enum {學習

    YUMessageTypeMe = 0, // 本身測試

    YUMessageTypeOther // 其餘人動畫

}   YUMessageType;atom

@interface YUMessage : NSObject

@property (nonatomic, copy) NSString *text;

@property (nonatomic, copy) NSString *time;

@property (nonatomic, assign) YUMessageType type;

 

@property (nonatomic, assign) BOOL hiddenTime;

 

- (instancetype)initWithDic:(NSDictionary *)dic;

+ (instancetype)messageWithDic:(NSDictionary *)dic;

@end

因爲本身發的消息與別人的消息顯示位置不一樣,用了枚舉來區別,另外hiddenTime是爲了避免重複顯示相同的時間。

 

每一個消息都是顯示在一個UITableViewCell上的,由於隨着數據的不一樣,文字的長短有區別,也就致使每一個cell的高度可能不同,這樣的狀況相似於前面的作的微博頁面,解決方法就是再封裝一個frame的模型(實體類),在裏面計算出子控件的frame和cell的高度

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

@class YUMessage;

 

@interface YUMessageFrame : NSObject

@property (nonatomic, assign, readonly) CGRect iconF;

@property (nonatomic, assign, readonly) CGRect textF;

@property (nonatomic, assign, readonly) CGRect timeF;

@property (nonatomic, assign, readonly) CGFloat cellHight;

@property (nonatomic, strong) YUMessage *message;

@end

在setMessage方法裏設置各個frame和cellHeight

- (void)setMessage:(YUMessage *)message {

    _message = message;

    

    CGFloat padding = 15;

    //時間

    if (message.hiddenTime == NO) {

        CGFloat timeW = [UIScreen mainScreen].bounds.size.width;

        CGFloat timeH = 40;

        _timeF = CGRectMake(0, 0, timeW, timeH);

    }

    //頭像

    CGFloat iconX;

    CGFloat iconY = CGRectGetMaxY(_timeF) + padding;

    CGFloat iconW = 50;

    CGFloat iconH = 50;

    //消息內容

    CGFloat textX;

    CGFloat textY = iconY;

    CGFloat textMaxW = 200;

    CGSize textSize = [message.text boundingRectWithSize:CGSizeMake(textMaxW, MAXFLOAT) options:NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName : [UIFont systemFontOfSize:16]} context:nil].size;

    CGFloat textW = textSize.width + 40;

    CGFloat textH = textSize.height + 30;

    

    if (message.type == YUMessageTypeMe) {

        iconX = [UIScreen mainScreen].bounds.size.width - padding - iconW;

        textX = iconX - padding - textW;

    } else {

        iconX = padding;

        textX = iconX + iconW + padding;

    }

    _iconF = CGRectMake(iconX, iconY, iconW, iconH);

    _textF = CGRectMake(textX, textY, textW, textH);

    _cellHight = MAX(CGRectGetMaxY(_iconF), CGRectGetMaxY(_textF)) + padding;

}

一個個排好就行,值得注意的是,本身的消息在右,別人的消息在左

 

第二步

ViewController里加載數據,實現數據源方法

在屬性的getter方法裏懶加載數據

- (NSMutableArray *)messageFrames {

    if (_messageFrames == nil) {

        NSMutableArray *result = [[NSMutableArray alloc] init];

        NSString *path = [[NSBundle mainBundle] pathForResource:@"messages.plist" ofType:nil];

        NSArray *dics = [NSArray arrayWithContentsOfFile:path];

        for (NSDictionary *dic in dics) {

            YUMessage *message = [YUMessage messageWithDic:dic];

            YUMessageFrame *lastF = [result lastObject];

            YUMessageFrame *messageFrame = [[YUMessageFrame alloc] init];

            messageFrame.message = message;

            //消息的時間相同就隱藏時間

            messageFrame.message.hiddenTime = [lastF.message.time isEqualToString:message.time];

            [result addObject:messageFrame];

        }

        _messageFrames = result;

    }

    return _messageFrames;

}

 

#pragma mark - 數據源方法

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return self.messageFrames.count;

}

 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    YUMessageCell *cell = [YUMessageCell cellWithTableView:tableView];

    cell.messageFrame = self.messageFrames[indexPath.row];

    return cell;

}

因爲系統提供的cell根本不夠我顯示數據,因而自定義cell,YUMessageCell爲我自定義cell的類名。cell的建立封裝在本身的類方法裏,這樣即實現瞭解耦,也簡化了ViewController的代碼。

在類擴展裏包含子控件

@interface YUMessageCell()

@property (nonatomic, weak) UIImageView *iconView;

@property (nonatomic, weak) UILabel *timeView;

@property (nonatomic, weak) UIButton *textView;

@end

在初始化方法里加載子控件

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

        UIImageView *iconView = [[UIImageView alloc] init];

        iconView.layer.cornerRadius = 8;

        //iconView.clipsToBounds = YES;

        [self.contentView addSubview:iconView];

        self.iconView = iconView;

        

        UILabel *timeView = [[UILabel alloc] init];

        timeView.textAlignment = NSTextAlignmentCenter;

        timeView.font = [UIFont systemFontOfSize:12];

        [self.contentView addSubview:timeView];

        self.timeView = timeView;

        

        UIButton *textView = [[UIButton alloc] init];

        textView.titleLabel.font = [UIFont systemFontOfSize:16];

        textView.titleLabel.numberOfLines = 0;//自動換行

        [self.contentView addSubview:textView];

        self.textView = textView;

        

        self.backgroundColor = [UIColor clearColor];

    }

    return self;

}

 

setter方法裏設置數據子控件的數據與frame

- (void)setMessageFrame:(YUMessageFrame *)messageFrame {

    _messageFrame = messageFrame;

    

    YUMessage *msg = messageFrame.message;

    if (msg.hiddenTime) {

        self.timeView.hidden = YES;

    } else {

        self.timeView.hidden = NO;

        self.timeView.frame = messageFrame.timeF;

        self.timeView.text = msg.time;

    }

    

    self.iconView.frame = messageFrame.iconF;

    self.iconView.image = [UIImage imageNamed:(msg.type == YUMessageTypeMe)?@"me":@"other"];

    

    self.textView.frame = messageFrame.textF;

    [self.textView setTitle:msg.text forState:UIControlStateNormal];

    

    // 4.設置聊天背景

    NSString *normal, *high;

    if (msg.type == YUMessageTypeOther) {

        normal = @"chat_recive_nor";

        high = @"chat_recive_press_pic";

        [self.textView setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

    } else {

        normal = @"chat_send_nor";

        high = @"chat_send_press_pic";

        [self.textView setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];

    }

    //設置按鈕內部的內間距

    self.textView.contentEdgeInsets = UIEdgeInsetsMake(15, 20, 15, 20);

    // 拉伸圖片 且保留圖片周圍的像素不被拉伸

    UIImage *normalBackground = [UIImage imageNamed:normal];

    normalBackground = [normalBackground stretchableImageWithLeftCapWidth:normalBackground.size.width * 0.5 topCapHeight:normalBackground.size.height * 0.5];

    //normalBackground = [normalBackground resizableImageWithCapInsets:UIEdgeInsetsMake(15, 20, 15, 20) resizingMode:UIImageResizingModeStretch];

    [self.textView setBackgroundImage:normalBackground forState:UIControlStateNormal];

}

因爲,聊天的背景圖片是這樣的

 

若是直接放進去,被拉伸後的效果很坑爹

 

因而須要方法拉伸圖片的時候四周不跟着拉伸,我的認爲比較好記又好用的方法是UIImage的一個對象方法,

- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight __TVOS_PROHIBITED;

這兩個參數通常傳入,圖片寬度的一半和高度的一半,這個方法的原理是按照你給的參數,在那個座標取像素爲1的正方形進行拉伸,這樣就能夠保持圖片的周邊在拉伸的時候像素不變了,效果以下

 

最後還有個問題,就是點擊文本框的時候鍵盤彈出,就會蓋住下方的部分,因此須要監聽鍵盤的狀態,在鍵盤出來的時候View要隨着鍵盤一塊兒動。那麼問題又來了,怎麼監聽鍵盤呢?

這就要靠通知機制

  • 每個應用程序都有一個通知中心(NSNotificationCenter)實例,專門負責協助不一樣對象之間的消息通訊
  • 任何一個對象均可以向通知中心發佈通知(NSNotification),描述本身在作什麼。其餘感興趣的對象(Observer)能夠申請在某個特定通知發佈時(或在某個特定的對象發佈通知時)收到這個通知

 

一個完整的通知通常包含3個屬性:

  • - (NSString *)name; // 通知的名稱
  • - (id)object; // 通知發佈者(是誰要發佈通知)
  • - (NSDictionary *)userInfo; // 一些額外的信息(通知發佈者傳遞給通知接收者的信息內容)

 

初始化一個通知(NSNotification)對象

  • + (instancetype)notificationWithName:(NSString *)aName object:(id)anObject;
  • + (instancetype)notificationWithName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
  • - (instancetype)initWithName:(NSString *)name object:(id)object userInfo:(NSDictionary *)userInfo;

通知中心(NSNotificationCenter)提供了相應的方法來幫助發佈通知

  • - (void)postNotification:(NSNotification *)notification;
  • 發佈一個notification通知,可在notification對象中設置通知的名稱、通知發佈者、額外信息等

 

  • - (void)postNotificationName:(NSString *)aName object:(id)anObject;
  • 發佈一個名稱爲aName的通知,anObject爲這個通知的發佈者

 

  • - (void)postNotificationName:(NSString *)aName object:(id)anObject userInfo:(NSDictionary *)aUserInfo;
  • 發佈一個名稱爲aName的通知,anObject爲這個通知的發佈者,aUserInfo爲額外信息

 

通知中心(NSNotificationCenter)提供了方法來註冊一個監聽通知的監聽器(Observer)

- (void)addObserver:(id)observer selector:(SEL)aSelector name:(NSString *)aName object:(id)anObject;

observer:監聽器,即誰要接收這個通知

aSelector:收到通知後,回調監聽器的這個方法,而且把通知對象當作參數傳入

aName:通知的名稱。若是爲nil,那麼不管通知的名稱是什麼,監聽器都能收到這個通知

anObject:通知發佈者。若是爲anObject和aName都爲nil,監聽器都收到全部的通知

 

- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block;

name:通知的名稱

obj:通知發佈者

block:收到對應的通知時,會回調這個block

queue:決定了block在哪一個操做隊列中執行,若是傳nil,默認在當前操做隊列中同步執行

 

通知中心不會保留(retain)監聽器對象,在通知中心註冊過的對象,必須在該對象釋放前取消註冊。不然,當相應的通知再次出現時,通知中心仍然會向該監聽器發送消息。由於相應的監聽器對象已經被釋放了,因此可能會致使應用崩潰

 

通知中心提供了相應的方法來取消註冊監聽器

  • - (void)removeObserver:(id)observer;
  • - (void)removeObserver:(id)observer name:(NSString *)aName object:(id)anObject;

 

通常在監聽器銷燬以前取消註冊(如在監聽器中加入下列代碼):

- (void)dealloc {

//[super dealloc];  非ARC中須要調用此句

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}

 

UIDevice類提供了一個單例對象,它表明着設備,經過它能夠得到一些設備相關的信息,好比電池電量值(batteryLevel)、電池狀態(batteryState)、設備的類型(model,好比iPod、iPhone等)、設備的系統(systemVersion)

經過[UIDevice currentDevice]能夠獲取這個單粒對象

 

UIDevice對象會不間斷地發佈一些通知,下列是UIDevice對象所發佈通知的名稱常量:

UIDeviceOrientationDidChangeNotification // 設備旋轉

UIDeviceBatteryStateDidChangeNotification // 電池狀態改變

UIDeviceBatteryLevelDidChangeNotification // 電池電量改變

UIDeviceProximityStateDidChangeNotification // 近距離傳感器(好比設備貼近了使用者的臉部)

 

咱們常常須要在鍵盤彈出或者隱藏的時候作一些特定的操做,所以須要監聽鍵盤的狀態

鍵盤狀態改變的時候,系統會發出一些特定的通知

UIKeyboardWillShowNotification // 鍵盤即將顯示

UIKeyboardDidShowNotification // 鍵盤顯示完畢

UIKeyboardWillHideNotification // 鍵盤即將隱藏

UIKeyboardDidHideNotification // 鍵盤隱藏完畢

UIKeyboardWillChangeFrameNotification // 鍵盤的位置尺寸即將發生改變

UIKeyboardDidChangeFrameNotification // 鍵盤的位置尺寸改變完畢

系統發出鍵盤通知時,會附帶一下跟鍵盤有關的額外信息(字典),字典常見的key以下:

UIKeyboardFrameBeginUserInfoKey // 鍵盤剛開始的frame

UIKeyboardFrameEndUserInfoKey // 鍵盤最終的frame(動畫執行完畢後)

UIKeyboardAnimationDurationUserInfoKey // 鍵盤動畫的時間

UIKeyboardAnimationCurveUserInfoKey // 鍵盤動畫的執行節奏(快慢)

我測試打印出來的信息以下(用的6s模擬器)

UIKeyboardAnimationCurveUserInfoKey = 7;

 UIKeyboardAnimationDurationUserInfoKey = "0.25";

 UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {375, 258}}";

 UIKeyboardCenterBeginUserInfoKey = "NSPoint: {187.5, 796}";

 UIKeyboardCenterEndUserInfoKey = "NSPoint: {187.5, 538}";

 UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 667}, {375, 258}}";

 UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 409}, {375, 258}}";

 UIKeyboardIsLocalUserInfoKey = 1;

 

好了,知道這些我就能夠監聽鍵盤了,讓鍵盤彈出的同時整個view也向上移動就好了,鍵盤收起也是同樣,跟着向下移動

首先監聽鍵盤通知,通常在viewDidLoad方法裏寫

//監聽鍵盤的通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardChange:) name:UIKeyboardWillChangeFrameNotification object:nil];

    

實現方法

- (void)keyboardChange:(NSNotification *)note {

    CGFloat duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    CGRect keyboardFrame = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

    CGFloat transfromY = (CGFloat)(keyboardFrame.origin.y - self.view.frame.size.height);

    [UIView animateWithDuration:duration animations:^{

        self.view.transform = CGAffineTransformMakeTranslation(0, transfromY);

    }];

}

利用transform能夠同時監聽鍵盤的彈出和收起,動畫效果使用block簡單方便

 

好啦!大功告成,總結一下,繼續熟悉了UITableView的使用,以及自定義Cell,另外學到了通知機制。

 

2015/10/30

Day 28

今天作了一個QQ好友列表展現,先放效果圖

仍是利用UITableView,這回是直接在starboard裏拖入一個UITableViewController,這個UITableViewController自動實現數據源方法和代理方法,不須要我手寫了

老規矩,先封裝模型類

 

這個算是多維數組了,每一個friend會在一個cell中顯示,最好分兩個模型封裝,group和friend

@interface YUFriend : NSObject

@property (nonatomic, copy) NSString *icon;

@property (nonatomic, copy) NSString *intro;

@property (nonatomic, copy) NSString *name;

@property (nonatomic, assign, getter=isVip) BOOL vip;

 

+ (instancetype)friendWithDic:(NSDictionary *)dic;

- (instancetype)initWithDic:(NSDictionary *)dic;

@end

bool類型的數據getter方法最好用is開頭

@interface YUGroup : NSObject

@property (nonatomic, strong) NSArray *friends;

@property (nonatomic, copy) NSString *name;

@property (nonatomic, assign) int online;

@property (nonatomic, assign) BOOL open;

 

+ (instancetype)groupWithDic:(NSDictionary *)dic;

- (instancetype)initWithDic:(NSDictionary *)dic;

@end

open表示組的打開或關閉

另外group的init方法中,須要把字典數組轉化成對象數組

- (instancetype)initWithDic:(NSDictionary *)dic {

    if (self = [super init]) {

        [self setValuesForKeysWithDictionary:dic];

        NSMutableArray *friends = [NSMutableArray array];

        for (NSDictionary *dic in self.friends) {

            YUFriend *friend = [YUFriend friendWithDic:dic];

            [friends addObject:friend];

        }

        self.friends = friends;

    }

    return self;

}

而後加載plist數據,實現ViewController的數據源方法

因爲這是分組的,numberOfSectionsInTableView終於用上了。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return self.groups.count;

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    YUGroup *group = self.groups[section];

    return group.open ? group.friends.count : 0;

}

自定義cell

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    YUFriendCell *cell = [YUFriendCell cellWithTableView:tableView];

    YUGroup *group = self.groups[indexPath.section];

    cell.friendData = group.friends[indexPath.row];

    return cell;

}

另外,每組的header也須要自定義(delegate屬性後面收縮組的時候要用到)

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {

    YUGroupHeader *header = [YUGroupHeader headerWithTableView:tableView];

    header.delegate = self;

    header.group = self.groups[section];

    return header;

}

自定義cell

@interface YUFriendCell : UITableViewCell

@property (nonatomic, strong) YUFriend *friendData;

 

+ (instancetype)cellWithTableView:(UITableView *)tableView;

@end

setter方法加載數據

- (void)setFriendData:(YUFriend *)friendData {

    _friendData = friendData;

    self.imageView.image = [UIImage imageNamed:friendData.icon];

    self.textLabel.text = friendData.name;

    self.textLabel.textColor = friendData.isVip ? [UIColor redColor] : [UIColor blackColor];

    self.detailTextLabel.text = friendData.intro;

}

init方法,作些基礎的設置

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {

    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {

        self.textLabel.font = [UIFont boldSystemFontOfSize:15];

    }

    return self;

}

初始化類方法,方便控制器使用

+ (instancetype)cellWithTableView:(UITableView *)tableView {

    static NSString *yu3 = @"friends";

    YUFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:yu3];

    if (cell == nil) {

        cell = [[YUFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:yu3];

    }

    return cell;

}

自定義headerView

@interface YUGroupHeader : UITableViewHeaderFooterView

@property (nonatomic, strong)  YUGroup *group;

+ (instancetype)headerWithTableView:(UITableView *)tableView;

@end

有兩個子控件,左邊的按鈕和右邊的在線人數

@interface YUGroupHeader ()

@property (nonatomic, weak) UIButton *nameBtn;

@property (nonatomic, weak) UILabel *onlineLabel;

@end

 

init方法里加入子控件和設置子控件的數據,

不建議在這裏設置子控件的frame,可能不許

- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier {

。。。   

}

在這個方法裏設置必定準,另外注意調用super

- (void)layoutSubviews {

    [super layoutSubviews];

    self.nameBtn.frame = self.bounds;

    self.onlineLabel.frame = CGRectMake(self.frame.size.width - 160, 0, 150, self.frame.size.height);

}

這樣數據就能全顯示出來,然而點擊header並不會收起來。

這就須要監聽header的點擊事件了,是誰要監聽呢?這就要看誰負責顯示數據了,是TableView,改變group的open屬性而後reloadData就能夠從新顯示數據,顯然,交給TableViewController監聽是最合適的,A的事件由B來監聽,又要用到代理模式了~

首先聲明header的代理協議

@protocol YUGroupHeaderDelegate <NSObject>

@optional

- (void)groupHeaderClick:(YUGroupHeader *)header;

@end

而後在header里加個屬性

@property (nonatomic, weak) id<YUGroupHeaderDelegate> delegate;

讓ViewController遵循協議

@interface ViewController () <YUGroupHeaderDelegate>

實現代理方法,很簡單,就是刷新數據

#pragma mark - 代理方法

- (void)groupHeaderClick:(YUGroupHeader *)header {

    [self.tableView reloadData];

}

在header裏實現headerDidClick方法

- (void)headerDidClick{

    self.group.open = !self.group.open;

    

    if ([self.delegate respondsToSelector:@selector(groupHeaderClick:)]) {

        [self.delegate groupHeaderClick:self];

    }

}

小結:熟悉UITableViewController的使用,代理的使用

通知和代理的選擇

共同點

  • 利用通知和代理都能完成對象之間的通訊

(好比A對象告訴B對象發生了什麼事情, A對象傳遞數據給B對象)

 

不一樣點

  • 代理 : 一對一關係(1個對象只能告訴另1個對象發生了什麼事情)
  • 通知 : 多對多關係(1個對象能告訴N個對象發生了什麼事情, 1個對象能得知N個對象發生了什麼事情)

 

UIView自帶的方法

1> - (void)layoutSubviews;

* 當一個控件的frame發生改變的時候就會自動調用

* 通常在這裏佈局內部的子控件(設置子控件的frame)

* 必定要調用super的layoutSubviews方法

2> - (void)didMoveToSuperview;

* 當一個控件被添加到父控件中就會調用

3> - (void)willMoveToSuperview:(UIView *)newSuperview;

* 當一個控件即將被添加到父控件中會調用

 

2015/10/31

Day 29

今天仍是繼續UITableView,利用storyboard在cell裏拖入控件顯示數據,照例先放效果圖

 

第一步,在storyboard裏拖控件,不得不說,感受比以前寫的自定義cell方便多了

 

另外要注意你的cell的屬性設置,特別是Identifier,

 

數據的模型封裝類,這就不貼了

而後建立cell類

@interface YUAppCell : UITableViewCell

@property (nonatomic, strong) YUApp *app;

@end

利用app屬性來傳入數據

另外在storyboard裏設置cell 的類型爲YUAppCell,而後就能夠愉快的連線了!

像這樣,在.m文件的類擴展裏連個痛快!

 

而後在setter方法里加載數據

- (void)setApp:(YUApp *)app {

    _app = app;

    self.iconView.image = [UIImage imageNamed:app.icon];

    self.nameLabel.text = app.name;

    self.descLabel.text = [NSString stringWithFormat:@"大小:%@ | 下載量:%@",app.size,app.download];

}

//按鈕點擊後不可用

- (IBAction)downClick:(UIButton *)btn {

    btn.enabled = NO;

}

最後在ViewController實現數據源方法,就能顯示出來了。注意cell的Identifier要跟你在storyboard裏的一致

然而坑爹的是,你在上面點了按鈕,讓按鈕不可用了,滑到下面,下面新的條目的按鈕也不可用了= =

這就是cell循環利用的一個坑。

解決方法:給cell設置數據的時候同時要把狀態也設置一下

在本例中

我在app模型里加入一個bool類型屬性,表示按鈕是否被點過了

@property (nonatomic, assign, getter=isDownloaded) BOOL downloaded;

 

而後點按鈕的時候,加入一行更新狀態

- (IBAction)downClick:(UIButton *)btn {

    self.app.downloaded = YES;

    btn.enabled = NO;

 }

最後在setter方法裏設置狀態

- (void)setApp:(YUApp *)app {

    _app = app;

    self.iconView.image = [UIImage imageNamed:app.icon];

    self.nameLabel.text = app.name;

    self.descLabel.text = [NSString stringWithFormat:@"大小:%@ | 下載量:%@",app.size,app.download];

    //覆蓋按鈕狀態

    self.downloadBtn.enabled = (self.app.isDownloaded == NO);

}

這樣,各個cell裏按鈕的狀態就互不影響了

相關文章
相關標籤/搜索