UI基礎(chǔ)


類擴(kuò)展(Class Extension)

  • 作用
    • 能為某個(gè)類增加額外的屬性、成員變量、方法聲明
    • 一般將類擴(kuò)展寫到.m文件中
    • 一般將一些私有的屬性寫到類擴(kuò)展
  • 使用格式
@interface 類名()
/* 屬性、成員變量、方法聲明 */
@end
  • 與分類的區(qū)別
    • 分類的小括號必須有名字
@interface 類名(分類名字)
/* 方法聲明 */
@end
@implementation 類名(分類名字)
/* 方法實(shí)現(xiàn) */
@end
- 分類只能擴(kuò)充方法
- 如果在分類中聲明了一個(gè)屬性,分類只會(huì)生成這個(gè)屬性的get\set方法聲明,`并不會(huì)生成成員變量`

項(xiàng)目的常見屬性

  • Product Name
    • 產(chǎn)品名稱
    • 項(xiàng)目名稱
    • 軟件名稱
  • Organization Name
    • 公司名稱
  • Organization Identifier
    • 公司的唯一標(biāo)識
    • 一般用網(wǎng)站域名的反寫形式
  • Bundle Identifier
    • 軟件的唯一標(biāo)識
    • 默認(rèn) == Organization Identifier + Product Name

九宮格的計(jì)算方式

/**************  一些常用的變量 begin **************/
// 每一行的列數(shù)
NSUInteger colsPerRow = 3;
// 獲得當(dāng)前商品的索引
NSUInteger index = self.shopsView.subviews.count;
// 商品寬度
CGFloat shopW = 70;
// 商品高度
CGFloat shopH = 90;
/**************  一些常用的變量 end **************/
    
/**************  計(jì)算X值 begin **************/
// 求出列號
NSUInteger col = index % colsPerRow;
// 每一列之間的間距
CGFloat xMargin = (self.shopsView.frame.size.width - colsPerRow * shopW) / (colsPerRow - 1);
// 商品X
CGFloat shopX = (shopW + xMargin) * col;
/**************  計(jì)算X值 end **************/
    
    
/**************  計(jì)算Y值 begin **************/
// 求出行號
NSUInteger row = index / colsPerRow;
// 每一行之間的間距
CGFloat yMargin = 20;
// 商品Y
CGFloat shopY = (shopH + yMargin) * row;
/**************  計(jì)算X值 end **************/

UIImageView

// 內(nèi)容模式:一般用來控制圖片如何顯示
imageView.contentMode = UIViewContentModeScaleAspectFit;
// 裁剪超出imageView邊框的部分
imageView.clipsToBounds = YES;
// 設(shè)置動(dòng)畫圖片
self.imageView.animationImages;
// 設(shè)置播放次數(shù)
self.imageView.animationRepeatCount
// 設(shè)置動(dòng)畫的時(shí)間
self.imageView.animationDuration
// 開始動(dòng)畫
[self.imageView startAnimating];

contentMode屬性

  • 帶有scale單詞的:圖片有可能會(huì)拉伸

    • UIViewContentModeScaleToFill
      • 將圖片拉伸至填充整個(gè)imageView
      • 圖片顯示的尺寸跟imageView的尺寸是一樣的
    • 帶有aspect單詞的:保持圖片原來的寬高比
      • UIViewContentModeScaleAspectFit
      • 保證剛好能看到圖片的全部
      • UIViewContentModeScaleAspectFill
      • 拉伸至圖片的寬度或者高度跟imageView一樣
  • 沒有scale單詞的:圖片絕對不會(huì)被拉伸,保持圖片的原尺寸

    • UIViewContentModeCenter
    • UIViewContentModeTop
    • UIViewContentModeBottom
    • UIViewContentModeLeft
    • UIViewContentModeRight
    • UIViewContentModeTopLeft
    • UIViewContentModeTopRight
    • UIViewContentModeBottomLeft
    • UIViewContentModeBottomRight

小語法點(diǎn)

  • 不能直接修改:OC對象的結(jié)構(gòu)體屬性的成員
  • 下面的寫法是錯(cuò)誤的
imageView.frame.size = imageView.image.size;
  • 正確寫法
CGRect tempFrame = imageView.frame;
tempFrame.size = imageView.image.size;
imageView.frame = tempFrame;

initWithImage:方法

  • 利用這個(gè)方法創(chuàng)建出來的imageView的尺寸和傳入的圖片尺寸一樣

修改frame的3種方式

  • 直接使用CGRectMake函數(shù)
imageView.frame = CGRectMake(100, 100, 200, 200);
  • 利用臨時(shí)結(jié)構(gòu)體變量
CGRect tempFrame = imageView.frame;
tempFrame.origin.x = 100;
tempFrame.origin.y = 100;
tempFrame.size.width = 200;
tempFrame.size.height = 200;
imageView.frame = tempFrame;
  • 使用大括號{}形式
imageView.frame = (CGRect){{100, 100}, {200, 200}};
  • 圖片的加載方式
  • 1、有緩存
UIImage *image = [UIImage imageNamed:@"圖片名"];
//使用場合:圖片比較小、使用頻率較高
//建議把需要緩存的圖片直接放到Images.xcassets
  • 2、無緩存
NSString *file = [[NSBundle mainBundle] pathForResource:@"圖片名" ofType:@"圖片的擴(kuò)展名"];
UIImage *image = [UIImage imageWithContentsOfFile:@"圖片文件的全路徑"];
//使用場合:圖片比較大、使用頻率較小
//不需要緩存的圖片不能放在Images.xcassets
//放在Images.xcassets里面的圖片,只能通過圖片名去加載圖片

UIControl

  • 凡是繼承自UIControl的控件,都可以通過addTarget:...方法來監(jiān)聽事件

UILabel

  • 內(nèi)容包含模式
UILabel *la = [[UILabel alloc] init];
la.lineBreakMode = NSLineBreakByWordWrapping;//保持單詞的完整性

@property的使用策略

  • assign
    • 基本數(shù)據(jù)類型枚舉結(jié)構(gòu)體等非OC對象類型
  • weak
    • OC對象類型(比如NSArray、NSDate、NSNumber、模型類)
  • strong
    • OC對象類型(比如NSArray、NSDate、NSNumber、模型類)
    • 一個(gè)對象只要有強(qiáng)指針引用著,就不會(huì)被銷毀
  • copy
    • 一般用在NSStringblock類型上

自定義控件的步驟

1、通過純代碼自定義控件

  • 繼承自系統(tǒng)自帶的控件,寫一個(gè)屬于自己的控件
  • 目的:封裝控件內(nèi)部的細(xì)節(jié),不讓外界關(guān)心
  • 步驟
    • 新建一個(gè)繼承UIView的類
    • initWithFrame:方法中添加子控件
    • layoutSubviews方法中設(shè)置子控件的frame
      • 一定要調(diào)用[super layoutSubviews];
    • 提供一個(gè)模型屬性,重寫模型屬性的set方法
      • 在set方法中取出模型屬性,給對應(yīng)的子控件賦值

2、通過xib自定義控件

  • 新建一個(gè)繼承UIView的類
  • 新建一個(gè)xib文件(xib的文件名最好跟控件類名一樣)
    • 添加子控件、設(shè)置子控件屬性
    • 修改最外面那個(gè)控件的class為控件類名
    • 將子控件進(jìn)行連線
  • 提供模型屬性,重寫模型的set方法
    • 在set方法中給子控件設(shè)置數(shù)據(jù)

中間的提醒內(nèi)容

  • 指示器、HUD、遮蓋、蒙板
  • 半透明的指示器如何實(shí)現(xiàn)?
    • 指示器的alpha = 1.0
    • 指示器的背景色是半透明的

創(chuàng)建顏色

  • 直接創(chuàng)建對應(yīng)的顏色
+ (UIColor *)blackColor;      // 0.0 white
+ (UIColor *)darkGrayColor;   // 0.333 white
+ (UIColor *)lightGrayColor;  // 0.667 white
+ (UIColor *)whiteColor;      // 1.0 white
+ (UIColor *)grayColor;       // 0.5 white
+ (UIColor *)redColor;        // 1.0, 0.0, 0.0 RGB
+ (UIColor *)greenColor;      // 0.0, 1.0, 0.0 RGB
+ (UIColor *)blueColor;       // 0.0, 0.0, 1.0 RGB
+ (UIColor *)cyanColor;       // 0.0, 1.0, 1.0 RGB
+ (UIColor *)yellowColor;     // 1.0, 1.0, 0.0 RGB
+ (UIColor *)magentaColor;    // 1.0, 0.0, 1.0 RGB
+ (UIColor *)orangeColor;     // 1.0, 0.5, 0.0 RGB
+ (UIColor *)purpleColor;     // 0.5, 0.0, 0.5 RGB
+ (UIColor *)brownColor;      // 0.6, 0.4, 0.2 RGB
+ (UIColor *)clearColor;      // 透明色

按鈕

  • 自定義按鈕:調(diào)整內(nèi)部子控件的frame
    • 方式1:實(shí)現(xiàn)titleRectForContentRect:和imageRectForContentRect:方法,分別返回titleLabel和imageView的frame
    • 方式2:在layoutSubviews方法中設(shè)置
  • 內(nèi)邊距
// 設(shè)置按鈕內(nèi)容的內(nèi)邊距(影響到imageView和titleLabel)
@property(nonatomic) UIEdgeInsets contentEdgeInsets;
// 設(shè)置titleLabel的內(nèi)邊距(影響到titleLabel)
@property(nonatomic) UIEdgeInsets titleEdgeInsets;
// 設(shè)置imageView的內(nèi)邊距(影響到imageView)
@property(nonatomic) UIEdgeInsets imageEdgeInsets;

圖片拉伸

  • iOS5之前
// 只拉伸中間的1x1區(qū)域
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
  • iOS5開始
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode;

拷貝(copy)

  • 實(shí)現(xiàn)拷貝的方法有2個(gè)
    • copy:返回不可變副本
    • mutableCopy:返回可變副本
  • 普通對象實(shí)現(xiàn)拷貝的步驟
    • 遵守NSCopying協(xié)議
    • 實(shí)現(xiàn)-copyWithZone:方法
      • 創(chuàng)建新對象
      • 給新對象的屬性賦值
copy

KVC

  • 全稱:Key Value Coding(鍵值編碼)
  • 賦值
// 能修改私有成員變量
- (void)setValue:(id)value forKey:(NSString *)key;
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
  • 取值
// 能取得私有成員變量的值
- (id)valueForKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;

KVO

  • 全稱:Key Value Observing(鍵值監(jiān)聽)
  • 作用:監(jiān)聽模型的屬性值改變
  • 步驟
    • 添加監(jiān)聽器
// 利用b對象來監(jiān)聽a對象name屬性的改變
[a addObserver:b forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"test"];
  • 在監(jiān)聽器中實(shí)現(xiàn)監(jiān)聽方法
 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change     context:(void *)context
    {
        NSLog(@"%@ %@ %@ %@", object, keyPath, change, context);
    }

代理的使用步驟

  • 定義一份代理協(xié)議
    • 協(xié)議名字的格式一般是:類名 + Delegate
      • 比如UITableViewDelegate
    • 代理方法細(xì)節(jié)
      • 一般都是@optional
      • 方法名一般都以類名開頭
        • 比如- (void)scrollViewDidScroll:
      • 一般都需要將對象本身傳出去
        • 比如tableView的方法都會(huì)把tableView本身傳出去
    • 必須要遵守NSObject協(xié)議
      • 比如@protocol XMGWineCellDelegate <NSObject>
  • 聲明一個(gè)代理屬性
    • 代理的類型格式:id<協(xié)議> delegate
@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
  • 設(shè)置代理對象
xxx.delegate = yyy;
  • 代理對象遵守協(xié)議,實(shí)現(xiàn)協(xié)議里面相應(yīng)的方法
  • 當(dāng)控件內(nèi)部發(fā)生了一些事情,就可以調(diào)用代理的代理方法通知代理
    • 如果代理方法是@optional,那么需要判斷方法是否有實(shí)現(xiàn)
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
    [self.delegate wineCellDidClickPlusButton:self];
}

iOS監(jiān)聽某些事件的方法

  • 通過addTarget:
    • 只有繼承自UIControl的控件,才有這個(gè)功能
    • UIControlEventTouchUpInside : 點(diǎn)擊事件(UIButton)
    • UIControlEventValueChanged : 值改變事件(UISwitch、UISegmentControl、UISlider)
    • UIControlEventEditingChanged : 文字改變事件(UITextField)
  • 通知(NSNotificationCenter\NSNotification)
    • 任何對象之間都可以傳遞消息
    • 使用范圍
      • 1個(gè)對象可以發(fā)通知給N個(gè)對象
      • 1個(gè)對象可以接受N個(gè)對象發(fā)出的通知
    • 必須得保證通知的名字在發(fā)出和監(jiān)聽時(shí)是一致的
  • KVO
    • 僅僅是能監(jiān)聽對象屬性的改變(靈活度不如通知和代理)
  • 代理delegate
    • 只有擁有delegate屬性的控件,才有這個(gè)功能
    • 使用范圍
      • 1個(gè)對象只能設(shè)置一個(gè)代理(假設(shè)這個(gè)對象只有1個(gè)代理屬性)
      • 1個(gè)對象能成為多個(gè)對象的代理
    • 通知規(guī)范
    • 建議使用代理多于通知

數(shù)據(jù)刷新(UITableView數(shù)據(jù))

1.全局刷新(最常用的方法)

[self.tableView reloadData];

2.局部刷新

  • 2.1 增加模型數(shù)組
//在index插入一個(gè)模型數(shù)據(jù)
-(void)insertObject:(id)anObject atIndex:(NSUInteger)index;
//添加模型
- (void)addObject:(id)anObject;
  • 2.1.1 增加數(shù)據(jù)后刷新
-(void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
  • 2.2 刪除模型數(shù)組
//移除最后一個(gè)模型
- (void)removeLastObject;
//移除index位置的的數(shù)據(jù)模型
- (void)removeObjectAtIndex:(NSUInteger)index;
//用anObject取代index位置的模型
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
  • 2.2.1 刪除數(shù)據(jù)后刷新
-(void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
  • 2.3 更改模型數(shù)組
-(void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

左滑刪除功能

//只要實(shí)現(xiàn)了這個(gè)方法,左滑出現(xiàn)Delete按鈕的功能就有了;點(diǎn)擊了“左滑出現(xiàn)的Delete按鈕”也會(huì)調(diào)用這個(gè)方法
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
//修改右側(cè)Delete的文字
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
  • 2.左滑出現(xiàn)多個(gè)按鈕
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"關(guān)注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        NSLog(@"點(diǎn)擊了關(guān)注");
        
        // 收回左滑出現(xiàn)的按鈕(退出編輯模式)
        tableView.editing = NO;
    }];
    
UITableViewRowAction *action1 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:@"刪除" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
        [self.wineArray removeObjectAtIndex:indexPath.row];
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
    }];
      return @[action1, action0];
}

批量刪除功能

//開啟批量刪除功能
[self.tableView setEditing:!self.tableView.isEditing animated:YES];
//開啟批量刪除功能后,可以編輯
self.tableView.allowsMultipleSelectionDuringEditing = YES;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容