2016 Week 2
开篇
第二星期开始,先和浩哥去看了美人鱼,就开始每天继续Coding-iOS的学习了。个人感觉这个Coding-iOS项目代码写的真好,开源之后简直就是iOS菜鸡开发者的福音。自己写起来之后,才发现coding速度真的是慢=。=
问题列表
UITextField
有关- 自定义
UITableViewCell
流程 NSUserDefaults
基础dispatch_once
和static
变量- 创建
category
SHA1
加密- 2种
enum
类型 - Coding调用API流程
MBProgressHUD
基础keyWindow
- 文件操作有关
- 账户输入提示框
enumerateObjectsUsingBlock:
- 2种
UITableViewCell
重用方式 NSRange
基础CAShapeLayer
基础- 显示/隐藏导航栏
- ViewController之间切换卡顿
SDWebImageOptions
- 在
category
中新增property
- 用户名存储整个流程
UIAlertController
基础
UITextField
有关
介绍几个UITextField的属性和方法
secureTextEntry
: 输入的文本不可见,多用于密码输入clearButtonMode
: 清空文本输入的按钮的模式控制,属于UITextFieldViewMode
。经常用到的有:UITextFieldViewModeNever
,UITextFieldViewModeWhileEditing
- 触发事件: 常用的有 开始编辑(
UIControlEventEditingDidBegin
), 文本变更(UIControlEventEditingChanged
), 结束编辑(UIControlEventEditingDidEnd
) keyboardType
: 键盘类型,可选的有UIKeyboardTypeEmailAddress
,UIKeyboardTypeDefault
等
自定义UITableViewCell
流程
参考这里
NSUserDefaults
基础
NSUserDefaults适合存储轻量级的本地数据,非常适合用来存储登录界面的数据(用户名,密码等等)。用法也很简单👇
- 存储数据
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // 获取 defaults [defaults setObject:loginData forKey:@"loginData"]; // 存放登录数据 [defaults synchronize]; // 同步到磁盘,避免数据丢失
- 读取数据
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; // 获取 defaults NSDictionary *loginData = [defaults objectForKey:@"loginData"]; // 获取登录数据
dispatch_once
和 static
变量
dispatch_once
函数只会被执行一次,经常用来创建单例实例,先来看看dispatch_once
函数
void dispatch_once(dispatch_once_t *predicate, dispatch_block_t block);
第二个参数是只会被执行一次的代码块,第一个参数用来判断代码块是否被执行。该函数与static
变量一同使用,看看具体代码👇
+ (instancetype)sharedManager {
static Coding_NetAPIManager *manager = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
manager = [[Coding_NetAPIManager alloc] init];
});
return manager;
}
上面的static
变量属于类成员,如果没有在.h文件中声明该static变量,那么他就是私有的类成员。类成员不能通过实例对象或是实例方法(-)去访问,只能通过类实例或是类方法(+)访问。
创建category文件
这个很简单啦,xcode -> New File -> Objective-C File -> 填写所需信息 -> Finish
例如,创建一个UIButton+Common
的category,应该👇
SHA1
加密
加密方法如下👇
- (NSString *)sha1Str {
const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
NSData *data = [NSData dataWithBytes:cstr length:self.length];
uint8_t digest[CC_SHA1_DIGEST_LENGTH];
CC_SHA1(data.bytes, (CC_LONG)data.length, digest);
NSMutableString *output = [NSMutableString stringWithCapacity:CC_SHA1_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_SHA1_DIGEST_LENGTH; i++) {
[output appendFormat:@"%02x", digest[i]];
}
return output;
}
注意 该方法写在了NSString的category里面
2种enum
类型
指定enum有两种方式:
1.
typedef enum {
Get = 0,
Post,
Put,
Delete
} NetworkMethod;
2.
typedef NS_ENUM(NSInteger, IllegalContentType) {
IllegalContentTypeTweet = 0,
IllegalContentTypeTopic,
IllegalContentTypeProject,
IllegalContentTypeWebsite
};
Coding调用API流程
参考这里
MBProgressHUD
基础
MBProgressHUD
是一个用来显示提示信息的第三方库,效果图如下👇
事例代码:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.mode = MBProgressHUDModeText;
hud.detailsLabelFont = [UIFont boldSystemFontOfSize:15];
hud.detailsLabelText = @"tip from vanney9.com";
hud.margin = 10;
hud.removeFromSuperViewOnHide = YES;
[hud hide:YES afterDelay:2.0f];
}
keyWindow
[UIApplication sharedApplication].keyWindow
APP主界面
文件操作有关
3个与文件操作相关的方法
- [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
该方法返回该APP的Documents目录,在真机上显示的结果如下:
在模拟机上显示的结果如下:/var/mobile/Containers/Data/Application/7DB19AAA-B9E7-40D8-AAFA-C5BA2FA91CF0/Documents
/Users/vanney/Library/Developer/CoreSimulator/Devices/FF2B6585-B815-4762-AC40-268D51742C85/data/Containers/Data/Application/82FEAB7E-9245-4BA8-88ED-A559034BA5F0/Documents
- [NSMutableDictionary dictionaryWithContentsOfFile:@”file name”];
该方法读取@"file name"
这个文件中的内容(注意:该文件应该存放键值对,一般XML文件),并返回由该键值对组成的NSMutableDictionary - [loginDataList writeToFile:@”file name” atomically:YES];
该方法中的loginDataList是一个NSMutableDictionary,这个方法将键值对写入@"file name"
这个文件中
账户输入提示框
效果如下图👇
实现该效果的步骤如下:
- 创建提示的UITableView
显示提示的白色框框实际上是一个UITableView,UITableView的内容根据当前已经输入的内容进行改变,若没有输入到@符号,就从之前输入过的账户中搜索;若已经输入了@符号,就显示不同的邮箱后缀。 - 将上一步创建的UITableView添加到输入账号,密码的UITableView中,并将提示框UITableView的位置定在账号的cell下面。
- 至于两个UITableView的交互:当账号的cell中的UITextField内容发生变化时,调用提示框UITableView的一个block,传入当前UITextField的文本,对提示的内容进行实时的变换。
enumerateObjectsUsingBlock:
enumerateObjectsUsingBlock:
方法和for-in
类似,具体代码如下👇
NSDictionary *dict = @{@"a": @"1", @"b": @"2"};
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
NSLog(@"key: %@, value: %@", key, obj);
}];
推荐使用for-in
方法,快。
2种UITableViewCell
重用方式
UITableViewCell
有两种dequeueReuse方法:
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier;
该方法是不用事先注册Cell,但是它可能返回nil;所以当返回nil时,需要重新init。示例代码如下👇static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; }
- (id)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath;
该方法在iOS6中取代了第一种方法,它可以保证一定会返回UITableViewCell,但是在初始化UITableView时,需要进行UITableViewCell的注册,如下👇
于是在重用UITableViewCell,不需要判断是否为nil,代码如下👇[_tableView registerClass:[CustomCell class] forCellReuseIdentifier:@"Cell"];
CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
NSRange
基础
NSRange是一个结构体,其定义如下👇
typedef struct _NSRange {
NSUInteger location;
NSUInteger length;
} NSRange;
其中location
表示起始位置,length
表示长度。
CAShapeLayer
基础
CAShapeLayer
继承自CALayer
,它表示一个形状,有一个path
属性用来描述该形状,然后可以对这个形状进行描边,填充等操作。示例代码如下👇
CAShapeLayer *layer = [CAShapeLayer layer];
// 创建path, 给layer添加path, 释放path
CGMutablePathRef pathRef = CGPathCreateMutable();
CGRect bounds = CGRectInset(cell.bounds, 0, 0);
CGPathAddRect(pathRef, nil, bounds);
layer.path = pathRef;
CFRelease(pathRef);
// 对layer进行填充操作
layer.fillColor = [UIColor colorWithWhite:1.0 alpha:0.8].CGColor;
// 添加layer
UIView *bgView = [[UIView alloc] initWithFrame:bounds];
[bgView.layer addSublayer:layer];
显示/隐藏导航栏
使用下列方法实现导航栏的显示或者隐藏
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// 隐藏导航栏,若Hidden设为NO,则显示导航栏
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
ViewController之间切换卡顿
可能的原因:没有设置ViewController的backgroundColor=。=
SDWebImageOptions
typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) {
SDWebImageRetryFailed = 1 << 0,//下载失败了会再次尝试下载
WebImageLowPriority = 1 << 1,//当UIScrollView等正在滚动时,延迟下载图片(放置scrollView滚动卡)
SDWebImageCacheMemoryOnly = 1 << 2,//只缓存到内存中
SDWebImageProgressiveDownload = 1 << 3,// 图片会边下边显示
SDWebImageRefreshCached = 1 << 4,//将硬盘缓存交给系统自带的NSURLCache去处理
SDWebImageContinueInBackground = 1 << 5,//后台下载
SDWebImageHandleCookies = 1 << 6,// 通过设置NSMutableURLRequest.HTTPShouldHandleCookies = YES来处理存储在NSHTTPCookieStore中的cookie
SDWebImageAllowInvalidSSLCertificates = 1 << 7,// 允许不受信任的SSL证书。主要用于测试目的。
SDWebImageHighPriority = 1 << 8,
SDWebImageDelayPlaceholder = 1 << 9,
SDWebImageTransformAnimatedImage = 1 << 10,
};
在category
中新增property
正常情况下,在category中是不能新增property的,要按如下步骤进行=。=
- 导入头文件
#import <objc/runtime.h>
- 新增@property
@property (nonatomic, strong) UIActivityIndicatorView *buttonIndicatorView;
自定义
setter
和getter
static char EAButtonIndicatorViewKey; - (void)setButtonIndicatorView:(UIActivityIndicatorView *)buttonIndicatorView { objc_setAssociatedObject(self, &EAButtonIndicatorViewKey, buttonIndicatorView, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (UIActivityIndicatorView *)buttonIndicatorView { return objc_getAssociatedObject(self, &EAButtonIndicatorViewKey); }
用户名存储整个流程
参考这里
UIAlertController
基础
从iOS8开始,UIAlertController
开始替代UIAlertAction
,先来看看UIAlertController的效果图👇
实现代码👇
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"欢迎注册 Coding,请尽快去邮箱查收邮件并激活账号。如若在收件箱中未看到激活邮件,请留意一下垃圾邮件箱(T_T)。" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[alertController dismissViewControllerAnimated:YES completion:nil];
}];
[alertController addAction:ok];
[self presentViewController:alertController animated:YES completion:nil];
参考
- iOS学习笔记42—利用dispatch_once创建单例
- Enum-枚举的正确使用-Effective-Objective-C-读书笔记-Item-5
- ios中集合遍历方法的比较和技巧
- UITableView的两种重用Cell方法的区别
- iOS CAShapeLayer精讲
- SDWebImage源码剖析
P.S
以上都不是重点,重点是ollie要过立了=。=