作者聲明
因跟人能力問題,文中不免有錯誤之處,歡迎各位讀者交流,批評,指正!
摘要
在上文的基礎上,重構“qq表情排列”,主要的原則就是:將公共代碼提取到一個方法中,供其它方法調用,不同的地方通過傳遞參數來實現。主要包括添加表情代碼和排序代碼。
實例
viewController h代碼
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
- (IBAction)sortImages:(UISegmentedControl *)sender;
#pragma mark 待改進1:是否可以通過其它方法將其省略?
// 僅僅是爲了在加號的監聽事件調用的方法中得到segment的值。
@property (weak, nonatomic) IBOutlet UISegmentedControl *segment;
@end
viewController m代碼
//
// ViewController.m
// qq表情排序(按老師的思路重寫一遍)
//
// Created by dqw on 15/5/7.
// Copyright (c) 2015年 itcast. All rights reserved.
//
#import "ViewController.h"
#define KImageWH 50 // 每個圖片的長寬
#define No 10 // 初始化圖片的個數。
@interface ViewController ()
@end
@implementation ViewController
#pragma mark 1. 在view加載完畢後加載圖片。
- (void)viewDidLoad {
[super viewDidLoad];
// 加載圖片。
for (int i = 0; i < No; i++) {
[self addImageWithNo:i AtIndex:i + 1 isInitial:YES];
}
// 加載後按2列排序。
[self sortImagesWithCount:No InColumns:2];
}
#pragma mark 2. 定義加載單個圖片方法
- (void)addImageWithNo:(int)imageNo AtIndex:(int)index isInitial:(BOOL)isInitial
{
NSString *newImageName = [NSString stringWithFormat:@"%d.png",imageNo];
UIImage *newImage = [UIImage imageNamed:newImageName];
// 定義父類指針。
UIView *newImageView;
#pragma mark 注意點1:最後一個是button類型。
// 創建最後一個加號(button類型)
if ((imageNo == (No -1)) && isInitial ) {
newImageView = [[UIButton alloc]init];
#pragma mark 重點1:多態。
// 多態,強制類型轉換後才能調用子類方法。
UIButton *temp = (UIButton *)newImageView;
[temp setImage:newImage forState:UIControlStateNormal];
// 爲按鈕添加監聽事件。
[temp addTarget:self action:@selector(addImage) forControlEvents:UIControlEventTouchUpInside];
}
// 創建非最後一個加號,或者隨機圖片。
else
{
newImageView = [[UIImageView alloc]init];
// 多態,強制類型轉換後才能調用子類方法。
UIImageView *temp = (UIImageView *)newImageView;
temp.image = newImage;
}
#pragma mark 待改善1:是否可以簡化合成
#pragma mark 疑問1:仔細研究這三種插入方法。
// 初始化和隨機插入兩種情況,該部分要考慮一下是否可以合成。
if (isInitial) {
[self.view insertSubview:newImageView atIndex:index];
}
else{
[self.view insertSubview:newImageView belowSubview:self.view.subviews[index]];
}
}
#pragma mark 3. 定義圖片排序方法
- (void)sortImagesWithCount:(int)count InColumns:(int)column
{
#pragma mark 注意點2:動畫的位置。
// 動畫放在這裏更合適,因爲位置值的改變就這這裏發生。
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0];
// 圖片y方向的起始位置和間距。
CGFloat startY = 10;
CGFloat distanceY = 50;
CGFloat startX;
CGFloat x;
CGFloat y;
startX = (self.view.frame.size.width -column * KImageWH) / (column + 1);
// 多態,父類指針。
UIView *tempView;
for (int i = 0; i < count; i++) {
x = startX + (startX + KImageWH) * (i % column);
y = startY + (distanceY + KImageWH) * (i / column);
tempView = self.view.subviews[i + 1];
tempView.frame = CGRectMake(x, y, KImageWH, KImageWH);
}
[UIView commitAnimations];
}
#pragma mark 4. 監聽segment的值。
- (IBAction)sortImages:(UISegmentedControl *)sender {
// [UIView beginAnimations:nil context:nil];
//
// [UIView setAnimationDuration:1.0];
int column = sender.selectedSegmentIndex + 2;
// 更新個數。
int count = self.view.subviews.count;
[self sortImagesWithCount:count -1 InColumns:column];
// [UIView commitAnimations];
}
#pragma mark 5. 定義添加隨機圖片的方法(供加號監聽事件調用)
- (void)addImage
{
#pragma mark 待改善2:是否可以合成到添加圖片方法中?
#pragma mark 疑問2:監聽事件調用該方法時如果該方法有參數則如何傳遞參數?
int imageNo = arc4random() % 9;
int count = self.view.subviews.count;
// index參數和插入的方法對應。
[self addImageWithNo:imageNo AtIndex:count - 1 isInitial:NO];
int column = _segment.selectedSegmentIndex + 2;
// 注意此處的count,因爲已經add過了,所以此處count不-1.
[self sortImagesWithCount:count InColumns:column];
}
@end
重點 難點 注意點
- 如KImageWH,宏定義的時候第一個字目寫K,可以用後面的WH表示一個單詞width,但是一般宏名是全大寫,單詞簡化也是取單詞前綴。
- 將表情的添加方法和表情的排序方法提取,體會這樣的模塊化思想,更加靈活。
- 多態:用同樣的父類uiview指針指向子類uiimageview和uibutton,但是在調用子類方法時,要強制類型轉換。
- 動畫的位置,避免重複寫,放在動畫發生的代碼塊中。
- 實施的更新subviews的個數。
疑問
- 爲一個控件添加監聽事件時,所調用的方法如果有參數,則該參數如何傳遞進去??
- 三種插入方法的區別?
待完善內容
- .h文件待改進1:@property segment 是否可以省略?
- 單詞的縮寫規則。
- .m文件待改進1,2:代碼進一步合併簡化。
- 添加storyboard,還有以前的。
- 這一部分的視頻和實例代碼還沒有看。