类扩展(Class Extension)
- 作用
- 能为某个类增加额外的属性、成员变量、方法声明
- 一般将类扩展写到.m文件中
一般将一些私有的属性写到类扩展
- 使用格式
@interface 类名()
/* 属性、成员变量、方法声明 */
@end
- 与分类的区别
- 分类的小括号必须有名字
@interface 类名(分类名字)
/* 方法声明 */
@end
@implementation 类名(分类名字)
/* 方法实现 */
@end
- 分类只能扩充方法
- 如果在分类中声明了一个属性,分类只会生成这个属性的get\set方法声明,`并不会生成成员变量`
项目的常见属性
- Product Name
- 产品名称
- 项目名称
- 软件名称
- Organization Name
- 公司名称
- Organization Identifier
- 公司的唯一标识
- 一般用网站域名的反写形式
- Bundle Identifier
- 软件的唯一标识
- 默认 == Organization Identifier + Product Name
九宫格的计算方式
/************** 一些常用的变量 begin **************/
// 每一行的列数
NSUInteger colsPerRow = 3;
// 获得当前商品的索引
NSUInteger index = self.shopsView.subviews.count;
// 商品宽度
CGFloat shopW = 70;
// 商品高度
CGFloat shopH = 90;
/************** 一些常用的变量 end **************/
/************** 计算X值 begin **************/
// 求出列号
NSUInteger col = index % colsPerRow;
// 每一列之间的间距
CGFloat xMargin = (self.shopsView.frame.size.width - colsPerRow * shopW) / (colsPerRow - 1);
// 商品X
CGFloat shopX = (shopW + xMargin) * col;
/************** 计算X值 end **************/
/************** 计算Y值 begin **************/
// 求出行号
NSUInteger row = index / colsPerRow;
// 每一行之间的间距
CGFloat yMargin = 20;
// 商品Y
CGFloat shopY = (shopH + yMargin) * row;
/************** 计算X值 end **************/
UIImageView
// 内容模式:一般用来控制图片如何显示
imageView.contentMode = UIViewContentModeScaleAspectFit;
// 裁剪超出imageView边框的部分
imageView.clipsToBounds = YES;
// 设置动画图片
self.imageView.animationImages;
// 设置播放次数
self.imageView.animationRepeatCount
// 设置动画的时间
self.imageView.animationDuration
// 开始动画
[self.imageView startAnimating];
contentMode属性
-
带有scale单词的:图片有可能会拉伸
- UIViewContentModeScaleToFill
- 将图片拉伸至填充整个imageView
- 图片显示的尺寸跟imageView的尺寸是一样的
- 带有aspect单词的:保持图片原来的宽高比
- UIViewContentModeScaleAspectFit
- 保证刚好能看到图片的全部
- UIViewContentModeScaleAspectFill
- 拉伸至图片的宽度或者高度跟imageView一样
- UIViewContentModeScaleToFill
-
没有scale单词的:图片绝对不会被拉伸,保持图片的原尺寸
- UIViewContentModeCenter
- UIViewContentModeTop
- UIViewContentModeBottom
- UIViewContentModeLeft
- UIViewContentModeRight
- UIViewContentModeTopLeft
- UIViewContentModeTopRight
- UIViewContentModeBottomLeft
- UIViewContentModeBottomRight
小语法点
- 不能直接修改:OC对象的结构体属性的成员
- 下面的写法是错误的
imageView.frame.size = imageView.image.size;
- 正确写法
CGRect tempFrame = imageView.frame;
tempFrame.size = imageView.image.size;
imageView.frame = tempFrame;
initWithImage:方法
- 利用这个方法创建出来的imageView的尺寸和传入的图片尺寸一样
修改frame的3种方式
- 直接使用CGRectMake函数
imageView.frame = CGRectMake(100, 100, 200, 200);
- 利用临时结构体变量
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:@"图片的扩展名"];
UIImage *image = [UIImage imageWithContentsOfFile:@"图片文件的全路径"];
//使用场合:图片比较大、使用频率较小
//不需要缓存的图片不能放在Images.xcassets
//放在Images.xcassets里面的图片,只能通过图片名去加载图片
UIControl
- 凡是继承自UIControl的控件,都可以通过addTarget:...方法来监听事件
UILabel
- 内容包含模式
UILabel *la = [[UILabel alloc] init];
la.lineBreakMode = NSLineBreakByWordWrapping;//保持单词的完整性
@property的使用策略
- assign
-
基本数据类型
、枚举
、结构体
等非OC对象类型
-
- weak
- OC对象类型(比如NSArray、NSDate、NSNumber、模型类)
- strong
- OC对象类型(比如NSArray、NSDate、NSNumber、模型类)
- 一个对象只要有强指针引用着,就不会被销毁
- copy
- 一般用在
NSString
、block
类型上
- 一般用在
自定义控件的步骤
1、通过纯代码自定义控件
- 继承自系统自带的控件,写一个属于自己的控件
- 目的:封装控件内部的细节,不让外界关心
- 步骤
- 新建一个继承
UIView
的类 - 在
initWithFrame:
方法中添加子控件 - 在
layoutSubviews
方法中设置子控件的frame- 一定要调用
[super layoutSubviews]
;
- 一定要调用
- 提供一个模型属性,重写模型属性的set方法
- 在set方法中取出模型属性,给对应的子控件赋值
- 新建一个继承
2、通过xib自定义控件
- 新建一个继承
UIView
的类 - 新建一个xib文件(xib的文件名最好跟控件类名一样)
- 添加子控件、设置子控件属性
- 修改最外面那个控件的class为控件类名
- 将子控件进行连线
- 提供模型属性,重写模型的set方法
- 在set方法中给子控件设置数据
中间的提醒内容
- 指示器、HUD、遮盖、蒙板
- 半透明的指示器如何实现?
- 指示器的alpha = 1.0
- 指示器的背景色是半透明的
创建颜色
- 直接创建对应的颜色
+ (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; // 透明色
按钮
- 自定义按钮:调整内部子控件的frame
- 方式1:实现titleRectForContentRect:和imageRectForContentRect:方法,分别返回titleLabel和imageView的frame
- 方式2:在layoutSubviews方法中设置
- 内边距
// 设置按钮内容的内边距(影响到imageView和titleLabel)
@property(nonatomic) UIEdgeInsets contentEdgeInsets;
// 设置titleLabel的内边距(影响到titleLabel)
@property(nonatomic) UIEdgeInsets titleEdgeInsets;
// 设置imageView的内边距(影响到imageView)
@property(nonatomic) UIEdgeInsets imageEdgeInsets;
图片拉伸
- iOS5之前
// 只拉伸中间的1x1区域
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
- iOS5开始
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets;
- (UIImage *)resizableImageWithCapInsets:(UIEdgeInsets)capInsets resizingMode:(UIImageResizingMode)resizingMode;
拷贝(copy)
- 实现拷贝的方法有2个
- copy:返回不可变副本
- mutableCopy:返回可变副本
- 普通对象实现拷贝的步骤
- 遵守NSCopying协议
- 实现-copyWithZone:方法
- 创建新对象
- 给新对象的属性赋值
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(键值监听)
- 作用:监听模型的属性值改变
- 步骤
- 添加监听器
// 利用b对象来监听a对象name属性的改变
[a addObserver:b forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"test"];
- 在监听器中实现监听方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
NSLog(@"%@ %@ %@ %@", object, keyPath, change, context);
}
代理的使用步骤
- 定义一份代理协议
- 协议名字的格式一般是:类名 + Delegate
- 比如UITableViewDelegate
- 代理方法细节
- 一般都是@optional
- 方法名一般都以类名开头
- 比如
- (void)scrollViewDidScroll:
- 比如
- 一般都需要将对象本身传出去
- 比如tableView的方法都会把tableView本身传出去
- 必须要遵守NSObject协议
- 比如
@protocol XMGWineCellDelegate <NSObject>
- 比如
- 协议名字的格式一般是:类名 + Delegate
- 声明一个代理属性
- 代理的类型格式:id<协议> delegate
@property (nonatomic, weak) id<XMGWineCellDelegate> delegate;
- 设置代理对象
xxx.delegate = yyy;
- 代理对象遵守协议,实现协议里面相应的方法
- 当控件内部发生了一些事情,就可以调用代理的代理方法通知代理
- 如果代理方法是@optional,那么需要判断方法是否有实现
if ([self.delegate respondsToSelector:@selector(wineCellDidClickPlusButton:)]) {
[self.delegate wineCellDidClickPlusButton:self];
}
iOS监听某些事件的方法
- 通过addTarget:
- 只有继承自UIControl的控件,才有这个功能
- UIControlEventTouchUpInside : 点击事件(UIButton)
- UIControlEventValueChanged : 值改变事件(UISwitch、UISegmentControl、UISlider)
- UIControlEventEditingChanged : 文字改变事件(UITextField)
- 通知(NSNotificationCenter\NSNotification)
- 任何对象之间都可以传递消息
- 使用范围
- 1个对象可以发通知给N个对象
- 1个对象可以接受N个对象发出的通知
- 必须得保证通知的名字在发出和监听时是一致的
- KVO
- 仅仅是能监听对象属性的改变(灵活度不如通知和代理)
- 代理delegate
- 只有拥有delegate属性的控件,才有这个功能
- 使用范围
- 1个对象只能设置一个代理(假设这个对象只有1个代理属性)
- 1个对象能成为多个对象的代理
- 比
通知
规范 - 建议使用
代理
多于通知
数据刷新(UITableView数据)
1.全局刷新(最常用的方法)
[self.tableView reloadData];
2.局部刷新
- 2.1 增加模型数组
//在index插入一个模型数据
-(void)insertObject:(id)anObject atIndex:(NSUInteger)index;
//添加模型
- (void)addObject:(id)anObject;
- 2.1.1 增加数据后刷新
-(void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- 2.2 删除模型数组
//移除最后一个模型
- (void)removeLastObject;
//移除index位置的的数据模型
- (void)removeObjectAtIndex:(NSUInteger)index;
//用anObject取代index位置的模型
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
- 2.2.1 删除数据后刷新
-(void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
- 2.3 更改模型数组
-(void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;
左滑删除功能
//只要实现了这个方法,左滑出现Delete按钮的功能就有了;点击了“左滑出现的Delete按钮”也会调用这个方法
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
//修改右侧Delete的文字
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath;
- 2.左滑出现多个按钮
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *action0 = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:@"关注" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath) {
NSLog(@"点击了关注");
// 收回左滑出现的按钮(退出编辑模式)
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;