1 内存管理原则 只要出现new alloc retain 配对出现release kvc kvo监听属性 有人改了 它也改
2 set方法 if(_xx!= xx) { _xx release; _xx = xx retain } dealloc { _ xx release }
3 property参数 1 set方法参数 retain (对象类型 符合内存管理规则) assign(直接赋值 ) 2 nonatomic(线程相关) copy(NSString) 3是否生成set get readonly 4 set get方法别名 5 ARC 对象类型 strong替代retain weak替代assign 基本类型手机和ARC是一样 6 arc copy nsstring block ,weak 代理 控件,strong 对象 ,assign 基本数据 7 NSMutableDictionary *dict = [NSMutableDictionary dictionary];[dict setObject:@"母鸡" forKey:@"name"];dict[xx]= xxx
4 autoreleasepool 需要调用 对象autoralease ,autoreleasepool 里面调用几次对象的autoralease 就会调用几次。
5 指向函数的指针void test{}
void (*mypoint)() = test
mypoint()
OC block void(^myblock) = ^ {}
myblock()
int (^sumBlock)(int ,int) = ^(int a, int b){
return a + b;
};
int a=sumBlock(1,1); 快捷键inlineblock
6 tableviewcell 有个contentView 其他控件都在contentview里面 内边距uibutton.contentEdgeInsets = UIEdgeInsetsMake
在UITextField左边放一个view
self.textField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 8, 0)];
self.textField.leftViewMode = UITextFieldViewModeAlways;
// 在UITextField设置键盘右下角按钮的样式
self.returnKeyType = UIReturnKeySearch;
self.enablesReturnKeyAutomatically = YES;
7 两个uisrcolerview 必须使用nsrunloop
8 nstimer cadisplaylink
9 3.动画 [UIView animateWithDuration
10 [self performSelector:@selector(nextQuestion) withObject:nil afterDelay:0.5];
11 heightForRowAtIndexPath self.tableView.rowHeight = 60;
12自定义 uitableViewcell 变量名字不要定义imageview ,系统uitableviewcell 有这个名字。
// 设置选中时的背景
uitableviewcell .selectedBackgroundView = selectedBg;
13 uitableviewcell tablefooterview只需要设置高度 宽XY等设置也没有用.- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.取消选中这行
[tableView deselectRowAtIndexPath:indexPath animated:YES];}
14 UINib nibwithNibName ;nib instantiatewithOwer lastobject;;;; UITableViewcell = [[[NSBundle mainBundle] loadNibNamed:@"MJTgCell" owner:nil options:nil] lastObject];;;;
+ (instancetype)headerView
{
return [[[NSBundle mainBundle] loadNibNamed:@"MJTgHeaderView" owner:nil options:nil] lastObject];
// headerView.scrollView
}
+ (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"tg";
MJTgCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
// 从xib中加载cell
cell = [[[NSBundle mainBundle] loadNibNamed:@"MJTgCell" owner:nil options:nil] lastObject];
}
cell .accessType = 箭头
return cell;
}
15 // 模拟(2秒后执行跳转)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 移除遮盖
[MBProgressHUD hideHUD];
// 跳转 -- 执行login2contacts这个segue
[self performSegueWithIdentifier:@"login2contacts" sender:nil];
});
16 uiview init方法通过代码new对象才会调用 ,awakeFromNib 通过xib创建对象会调用。
17 代码创建uitableviewcell ,需要重写initwithstyle ,在这个方法里面创建其他控件,代码创建uitabviewcontroller initwithstyle 方法设置单租 和分组模式
uitableviewcell cell = [[uitableviewcell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
18 beakgroundview优先级大于backgroundcolor
19 viewcontroller endEditing resignFirstResponder ;; self.tableView.allowsSelection = NO; // 不允许选中
20 静态uitableview 设置多行的时候会复制第一个
21 任何控件初始化宽高都是0 ,在uiview layoutsubviews设置,当frame改变时候调用 不要在初始化方法里面设置frame.在layoutsubviews设置frame
22 UIView/**
* 当一个控件被添加到父控件中就会调用 tableview QQ好友展开合并 headerview设置旋转就在这设置.
*/
- (void)didMoveToSuperview
23 UIbutton 里面的imageview // 设置按钮内部的imageView的内容模式为居中
nameView.imageView.contentMode = UIViewContentModeCenter;
// 超出边框的内容不需要裁剪
nameView.imageView.clipsToBounds = NO;
24 代码设置按钮点击事件 [nameView addTarget:self action:@selector(nameViewClick) forControlEvents:UIControlEventTouchUpInside];
25 应用管理 点击下载的时候 中间弄个提示 已经下载
// 1.添加标签
UILabel *label = [[UILabel alloc] init];
label.text = [NSString stringWithFormat:@"成功下载%@", cell.app.name];
label.font = [UIFont systemFontOfSize:12];
label.textAlignment = NSTextAlignmentCenter;
label.textColor = [UIColor whiteColor];
label.backgroundColor = [UIColor blackColor];
label.frame = CGRectMake(0, 0, 150, 25);
label.center = CGPointMake(160, 240);
label.alpha = 0.0;
label.layer.cornerRadius = 5;
label.clipsToBounds = YES;
[self.view addSubview:label];
// 2.动画
[UIView animateWithDuration:0.5 animations:^{
label.alpha = 0.5;
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.5 delay:0.5 options:UIViewAnimationOptionCurveLinear animations:^{
label.alpha = 0.0;
} completion:^(BOOL finished) {
[label removeFromSuperview];
}];
}];
app.networkActivityIndicatorVisible = YES;
26 uitextField调出时间控件 uitextfield.inputview = uidatepicker; uitextfield.inputaccessoryview可以在键盘上自定义一个view
27 toolbar里面只能放UIBarButtonItem 控件 ,可以设置barbuttonitem是弹簧 barbuttonitem里面可以放其它控件比如uibutton。
直接拖uibutton,他自己会自动弄到uibarbuttonitem里面。uibarbuttonitem中间的view可以放按钮,也可以直接是写文字.
28 状态栏默认是viewcontroller管理,如果要uiappcation管理 要设置info.plist
29uiviewcontroller 实现了loadview方法 会跳过加载stroyborad或者xib.
UIStoryboard *story = [UIStoryboard storyboardWithName:@"Test" bundle:nil];
self.window.rootViewController = [story instantiateInitialViewController];
self.window.rootViewController = [[MJViewController alloc] initWithNibName:@"MJViewController" bundle:nil];
30 控制器的view是全屏的包括状态栏
自动型Segue 使用push方法能将某个控制器压入栈
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated;
使用pop方法可以移除控制器
将栈顶的控制器移除
- (UIViewController *)popViewControllerAnimated:(BOOL)animated;
回到指定的子控制器
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;
回到根控制器(栈底控制器)
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated;
手动型的Segue需要设置一个标识
在恰当的时刻,使用perform方法执行对应的Segue
[self performSegueWithIdentifier:@"login2contacts" sender:nil];调用sourceViewController的下面方法,做一些跳转前的准备工作并且传入创建好的Segue对象- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
---------
除了push之外,还有另外一种控制器的切换方式,那就是Modal ,modal的rootviewcontroller一直都是第一个.其他的用presentedviewcontroller引用
任何控制器都能通过Modal的形式展示出来
Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为止
以Modal的形式展示控制器
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
关闭当初Modal出来的控制器
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion;(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender;
31 导航栏的内容由栈顶控制器的navigationItem属性决定 ,navigationItem里面左右两边只能放UIBarButtonItem 控件 ,可以设置barbuttonitem是弹簧 barbuttonitem可以放其它控件比如uibutton
33 Documents:保 iTunes同步设备时会备份该目录。例如,游戏应用可将游戏存档保存在该目录
tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时不会备份该目录
Library/Caches: iTunes同步设备时不会备份该目录。一般存储体积大、不需要备份的非重要数据
Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用会在该目录中查找应用的设置信息。iTunes同步设备时会备份该目录
34 如果对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可以使用writeToFile:atomically:方法直接将对象写到属性列表文件中
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];[defaults setObject:@"itcast" forKey:@"username"],[defaults synchornize];;NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];NSString *username = [defaults stringForKey:@"username"];
归档(编码)[NSKeyedArchiver archiveRootObject:person toFile:path];
恢复(解码)Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
数组 NSMutableArray *contacts=[NSKeyedUnarchiver unarchiveObjectWithFile:MJContactsFilepath]
// 将数据封装成字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"母鸡" forKey:@"name"];
[dict setObject:@"15013141314" forKey:@"phone"];
[dict setObject:@"27" forKey:@"age"];
// 将字典持久化到Documents/stu.plist文件中
[dict writeToFile:path atomically:YES];
// 读取Documents/stu.plist的内容,实例化NSDictionary
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
NSLog(@"name:%@", [dict objectForKey:@"name"]);
NSLog(@"phone:%@", [dict objectForKey:@"phone"]);
NSLog(@"age:%@", [dict objectForKey:@"age"]);
35 如果UITabBarController有N个子控制器,那么UITabBar内部就会有N个UITabBarButton作为子控件 UITabBarButton里面显示什么内容,由对应子控制器的tabBarItem属性决定.
UITabBarItem有以下属性影响着UITabBarButton的内容
标题文字 @property(nonatomic,copy) NSString *title;
图标
@property(nonatomic,retain) UIImage *image;
选中时的图标
@property(nonatomic,retain) UIImage *selectedImage;
提醒数字
@property(nonatomic,copy) NSString *badgeValue;
[[UIImage imageNamed:selectedImageName] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];告诉系统用原始图片
UITabBar里面放UITarBarButton是私有的,UITarBarButton是UIControl的子类
36//app进入后台:休眠, 不能接受事情(比如关闭) ,接受事情必须mp3应用
/**
* app关闭的时候调用(一般情况下不会调用)
*/
- (void)applicationWillTerminate:(UIApplication *)application
37 隐藏uitabbar 勾选hide bottom bar on push. uitabviewcontroller-storyborad使用静态单元格uitabviewcontroller类里面必须删除两个代理方法(return行和组的).
hidesBottomBarWhenPushed
38 获得图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
拼接路径(下面代码是搞一条线段)
CGContextMoveToPoint(ctx, 10, 10);
CGContextAddLineToPoint(ctx, 100, 100);
CGContextSetLineWidth( 100);
CGContextSetLinecap
CGContextSetLineJoin
CGContextSetRGB==UICORLOR WITHER SET
CGContextStrokePath(ctx);绘制路径
CGContextMoveToPoint(ctx, 10, 10);
CGContextAddLineToPoint(ctx, 100, 100);
CGContextSetLineWidth( 100);
CGContextSetRGB
绘制路径
CGContextStrokePath(ctx); // CGContextFillPath(ctx);
-----添加一个矩形
void CGContextAddRect(CGContextRef c, CGRect rect)
添加一个椭圆
void CGContextAddEllipseInRect(CGContextRef context, CGRect rect)
添加一个圆弧
void CGContextAddArc(CGContextRef c, CGFloat x, CGFloat y,
CGFloat radius, CGFloat startAngle, CGFloat endAngle, int clockwise)
// 关闭路径(连接起点和最后一个点)
CGContextClosePath(ctx);
39 设置view背景 view.backcolor = UIColor colorWithPatternImage把图片转换成颜色 ui控件 init方法默认调用initwithframe ,initwithframe 代码创建控件调用
// 设置全局导航栏主题 导航栏高度64 ios6导航栏高度44
/**initailize、load方法的区别
initailize、load都是类方法
当一个类被装载进内存时,就会调用一次load方法(当时这个类还不可用)
当第一次使用这个类时,就会调用一次initailize方法
* 系统在第一次使用这个类的时候调用(1个类只会调用一次)
*/
+ (void)initialize
UINavigationBar *navBar = [UINavigationBar appearance];
[navBar setBackgroundImage:[UIImage imageNamed:bgName] forBarMetrics:UIBarMetricsDefault];// 设置标题文字颜色
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
attrs[UITextAttributeTextColor] = [UIColor whiteColor];
attrs[UITextAttributeFont] = [UIFont systemFontOfSize:16];
[navBar setTitleTextAttributes:attrs];
// 设置全局状态栏的样式
application.statusBarStyle = UIStatusBarStyleLightContent;
导航栏文字阴影 textAttrs[UITextAttributeTextShadowOffset] = [NSValue valueWithUIOffset:UIOffsetZero];
40 appicon去掉反光效果 点击 appicon 勾选ios icon is pre_render 2程序启动时隐藏状态栏 勾选Hide during application lunch 然在appDelegate application.statusBarHide=no
41自定义uibutton 从文件中解析一个对象的时候就会调用这个方法 . 方法执行顺序 initWithCoder-titleRectForContentRect-awakeFromNib
42 image拉伸storyborad上的stretching uibuttonstoryborad上的stretching 只对uibutton里面的Image有用 ,
stretchableImageWithLeftCapWidth 图片拉伸, 两个resizableImageWithCapInsets方法 重写了一个.
+ (UIImage *)resizedImageWithName:(NSString *)name
{
return [self resizedImageWithName:name left:0.5 top:0.5];
}
+ (UIImage *)resizedImageWithName:(NSString *)name left:(CGFloat)left top:(CGFloat)top
{
UIImage *image = [self imageWithName:name];
return [image stretchableImageWithLeftCapWidth:image.size.width * left topCapHeight:image.size.height * top];
}
43 设置BarButtonItem的主题
UIBarButtonItem *item = [UIBarButtonItem appearance];
navBar.tintcolor = [uicolor redcolor]//返回按钮的那个箭括号的颜色
// 设置文字颜色
NSMutableDictionary *itemAttrs = [NSMutableDictionary dictionary];
itemAttrs[NSForegroundColorAttributeName] = [UIColor whiteColor];
itemAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:14];
[item setTitleTextAttributes:itemAttrs forState:UIControlStateNormal];
45 在model模型数据中UI控件用strong, UITableViewCell accessoryView使用strong ,[UITableViewCell .contentView addSubview:divider] divider使用weak
46 UICollectionViewController 必须在viewDidLoad // 1.注册cell(告诉collectionView将来创建怎样的cell)
UINib *nib = [UINib nibWithNibName:@"MJProductCell" bundle:nil];
[self.collectionView registerNib:nib forCellWithReuseIdentifier:MJProductCellID];
// [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:MJProductCellID];
// 2.设置collectionView的背景色
self.collectionView.backgroundColor = [UIColor whiteColor];
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// 1.获得cell
MJProductCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:MJProductCellID forIndexPath:indexPath];
// 2.传递模型
cell.product = self.products[indexPath.item];
return cell;
}
- (id)init
{
// 1.流水布局
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
// 2.每个cell的尺寸
layout.itemSize = CGSizeMake(80, 80);
// 3.设置cell之间的水平间距
layout.minimumInteritemSpacing = 0;
// 4.设置cell之间的垂直间距
layout.minimumLineSpacing = 10;
// 5.设置四周的内边距
layout.sectionInset = UIEdgeInsetsMake(layout.minimumLineSpacing, 0, 0, 0);
return [super initWithCollectionViewLayout:layout];
}
47 // JSON文件的路径
NSString *path = [[NSBundle mainBundle] pathForResource:@"products.json" ofType:nil];
// 加载JSON文件
NSData *data = [NSData dataWithContentsOfFile:path];
// 将JSON数据转为NSArray或者NSDictionary
NSArray *dictArray = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
48 imageview圆角 // 根据图片自动调整大小
[self.imageView sizeToFit];
self.iconView.layer.cornerRadius = 8;
self.iconView.clipsToBounds = YES;
49 真机调式 需要加入99美元年费账号
登录开发者主页
生成cer证书:cer是一个跟电脑相关联的证书文件,让电脑具备真机调试的功能 :只能配置一台电脑 可以删除 然后增加
添加App ID:调试哪些app?
注册真机设备:哪台设备需要做真机调试?
生成MobileProvision文件:结合2、3、4生成一个手机规定文件
导入cer、MobileProvision文件
50 打开别的应用,别的应用需要配置 URL types : url identifier URL Schemes
51 ViewController 里面的block __unsafe_unretained ViewController *share = self;
__unsafe_unretained typeof(self) selfVc = self;
52 /**
UIViewAutoresizingFlexibleLeftMargin = 1 << 0, 距离父控件左边的间距是伸缩的
UIViewAutoresizingFlexibleWidth = 1 << 1, 自己的宽度跟随着父控件的宽度进行伸缩
UIViewAutoresizingFlexibleRightMargin = 1 << 2, 距离父控件右边的间距是伸缩的
UIViewAutoresizingFlexibleTopMargin = 1 << 3, 距离父控件顶部的间距是伸缩的
UIViewAutoresizingFlexibleHeight = 1 << 4, 自己的高度跟随着父控件的高度进行伸缩
UIViewAutoresizingFlexibleBottomMargin = 1 << 5 距离父控件底部的间距是伸缩的
*/
UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];
btn.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
53 // 2.保存到图片
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
54 // 设置按钮不可用
self.userInteractionEnabled = NO;
55 多个手势需要实现代理方法
shouldRecognizeSimultaneouslyWithGestureRecognizer
56 calayer self.iconView.layer.transform = CATransform3DMakeRotation(M_PI_4, 0, 0, 1);
NSValue *value = [NSValue valueWithCATransform3D:CATransform3DMakeRotation(M_PI_4, 0, 0, 1)];
[self.iconView.layer setValue:value forKeyPath:@"transform"];
[self.iconView.layer setValue:@(M_PI_2) forKeyPath:@"transform.rotation"];可以传递哪些key path, 在官方文档搜索"CATransform3D key paths"
CALayer是定义在QuartzCore框架中的
CGImageRef、CGColorRef两种数据类型是定义在CoreGraphics框架中的
UIColor、UIImage是定义在UIKit框架中的 QuartzCore框架和CoreGraphics框架是可以跨平台使用的,在iOS和Mac OS X上都能使用
57 calayer隐式动画// [CATransaction begin]; // 开启事务
// [CATransaction setDisableActions:YES];
// self.layer.position = CGPointMake(100, 100);
// [CATransaction commit]; // 提交事务
58 CAKeyframeAnimation *anim = [CAKeyframeAnimation animation]; calayer动画一般只用转场动画 因为他的动画不改变位置等.一般用uiview动画
anim.keyPath = @"position";
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
anim.duration = 2.0; [self.redView.layer addAnimation:anim forKey:nil];
围绕圆转圈动画
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"position";
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
anim.duration = 2.0;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddEllipseInRect(path, NULL, CGRectMake(100, 100, 200, 200));
anim.path = path;
CGPathRelease(path);
// 设置动画的执行节奏
// kCAMediaTimingFunctionEaseInEaseOut : 一开始比较慢, 中间会加速, 临近结束的时候, 会变慢
anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
anim.delegate = self;
[self.redView.layer addAnimation:anim forKey:nil];
59
/* 过渡效果 fade //交叉淡化过渡(不支持过渡方向) kCATransitionFade push //新视图把旧视图推出去 kCATransitionPush
moveIn //新视图移到旧视图上面 kCATransitionMoveIn reveal //将旧视图移开,显示下面的新视图 kCATransitionReveal cube //立方体翻滚效果 oglFlip //上下左右翻转效果 suckEffect //收缩效果,如一块布被抽走(不支持过渡方向) rippleEffect //滴水效果(不支持过渡方向) pageCurl //向上翻页效果 pageUnCurl //向下翻页效果 cameraIrisHollowOpen //相机镜头打开效果(不支持过渡方向) cameraIrisHollowClose //相机镜头关上效果(不支持过渡方向) */
/* 过渡方向 kCATransitionFromRight kCATransitionFromLeft kCATransitionFromBottom kCATransitionFromTop*/
CATransition的使用
CATransition *anim = [CATransition animation];
anim.type = @“cube”; // 动画过渡类型
anim.subtype = kCATransitionFromTop; // 动画过渡方向
anim.duration = 1; // 动画持续1s
// 代理,动画执行完毕后会调用delegate的animationDidStop:finished:
anim.delegate = self;
/*******中间穿插改变layer属性的代码**********/
[layer addAnimation:anim forKey:nil];
60 uiview动画
[UIView beginAnimations:nil context:nil];
// 动画执行完毕后, 会自动调用self的animateStop方法
// [UIView setAnimationDelegate:self];
// [UIView setAnimationDidStopSelector:@selector(animateStop)];
self.myview.center = CGPointMake(200, 300);
[UIView commitAnimations];
61 用CADisplayLink做转圈动画
// 1秒内刷新60次
CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
[link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
self.link = link;- (void)update
{
self.centerWheel.transform = CGAffineTransformRotate(self.centerWheel.transform, M_PI / 500);//累加的角度
}
- (void)stopRotating 停止
{
[self.link invalidate];
self.link = nil;
}
62 // 从大图片中裁剪中对应星座的图片
CGFloat smallW = bigImage.size.width / 12 * [UIScreen mainScreen].scale;
CGFloat smallH = bigImage.size.height * [UIScreen mainScreen].scale; // CGImageCreateWithImageInRect只认像素
CGImageRef smallImage = CGImageCreateWithImageInRect(bigImage.CGImage, smallRect); 裁剪图片
63 GCD dispatch_queue_t
串行队列,队列中的任务只会顺序执行 dispatch_async dispatch_sync两个操作都是顺序执行 dispatch_sync主线程上运行 阻塞UI
并行队列,队列中的任务通常会并发执行 dispatch_async操作都是没有顺序的执行 dispatch_sync在主线程顺序的执行阻塞UI
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcddemo", DISPATCH_QUEUE_SERIAL);
// 串行行队列的同步任务,同样会在主线程上运行
// 提示:在开发中极少用d
// 面试中有可能会问!
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
for (int i = 0; i < 10; ++i) {
// 异步任务,并发执行,但是如果在串行队列中,仍然会依次顺序执行
dispatch_async(q, ^{
// [NSThread currentThread] 可以在开发中,跟踪当前线程
// num = 1,表示主线程
// num = 2,表示第2个子线程。。。
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
dispatch_queue_t q = dispatch_queue_create("cn.itcast.gcd2", DISPATCH_QUEUE_CONCURRENT);
// for (int i = 0; i < 10; ++i) {
// // 异步任务
// dispatch_async(q, ^{
// // [NSThread currentThread] 可以在开发中,跟踪当前线程
// // num = 1,表示主线程
// // num = 2,表示第2个子线程。。。
// NSLog(@"%@ %d", [NSThread currentThread], i);
// });
// }
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
全局队列(苹果为了方便多线程的设计,提供一个全局队列,供所有的APP共同使用)
dispatch_queue_t q =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_queue_t q =dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
for (int i = 0; i < 10; ++i) {
// 同步任务顺序执行
dispatch_sync(q, ^{
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
for (int i = 0; i < 10; ++i) {
// 异步任务,并发执行,但是如果在穿行队列中,仍然会依次顺序执行
dispatch_async(q, ^{
// [NSThread currentThread] 可以在开发中,跟踪当前线程
// num = 1,表示主线程
// num = 2,表示第2个子线程。。。
NSLog(@"%@ %d", [NSThread currentThread], i);
});
}
// 在iOS开发中,所有UI的更新工作,都必须在主线程上执行!
dispatch_queue_t q = dispatch_get_main_queue();
// 异步任务,在主线程上运行,同时是保持队形的
for (int i = 0; i < 10; ++i) {
dispatch_async(q, ^{
NSLog(@"%@ - %d", [NSThread currentThread], i);
});
}
64 NSOperationQueue(操作队列)是由GCD提供的队列模型的Cocoa抽象
self.myQueue = [[NSOperationQueue alloc] init];
NSBlockOperation *block = [NSBlockOperation blockOperationWithBlock:^{
// NSLog(@"%@", [NSThread currentThread]);
// }];
// 所有的自定义队列,都是在子线程中运行
// [self.myQueue addOperation:block];
[self.myQueue setMaxConcurrentOperationCount:2];
for (int i = 0; i < 10; ++i) {
[self.myQueue addOperationWithBlock:^{
NSLog(@"%@ %d", [NSThread currentThread], i);
}];
}
#pragma mark 设置任务的执行顺序
- (void)demoOp3
{
NSBlockOperation *op1 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"下载图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"修饰图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op3 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"保存图片 %@", [NSThread currentThread]);
}];
NSBlockOperation *op4 = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"更新UI %@", [NSThread currentThread]);
}];
// 设定执行顺序, Dependency依赖,可能会开多个,但不会太多
// 依赖关系是可以跨队列的!
[op2 addDependency:op1];
[op3 addDependency:op2];
[op4 addDependency:op3];
// GCD是串行队列,异步任务,只会开一个线程
[self.myQueue addOperation:op1];
[self.myQueue addOperation:op2];
[self.myQueue addOperation:op3];
// 所有UI的更新需要在主线程上进行
[[NSOperationQueue mainQueue] addOperation:op4];
}
65 如果self对象持有操作对象的引用,同时操作对象当中又直接访问了self时,才会造成循环引用.
单纯在操作对象中使用self不会造成循环引用
class person {- (void)demoOp:(id)obj
{
NSLog(@"%@ %@", [NSThread currentThread], obj);
}
- (void)demoBlockOp
{
// 不能用__weak
// __weak DemoObj *weakSelf = self;
// 只有self直接强引用block,才会出现循环引用
// block的管理以及线程的创建和销毁是由队列负责的,直接在block中使用self没有关系!
for (int i = 0; i < 10; ++i) {
[self.queue addOperationWithBlock:^{
[self demoOp:@(i)];
}];
}
}}
66 单列 /**
1. 重写allocWithZone,用dispatch_once实例化一个静态变量
2. 写一个+sharedXXX方便其他类调用
*/
// 在iOS中,所有对象的内存空间的分配,最终都会调用allocWithZone方法
// 如果要做单例,需要重写此方法
// GCD提供了一个方法,专门用来创建单例的
+ (id)allocWithZone:(struct _NSZone *)zone
{
static DemoObj *instance;
// dispatch_once是线程安全的,onceToken默认为0
static dispatch_once_t onceToken;
// dispatch_once宏可以保证块代码中的指令只被执行一次
dispatch_once(&onceToken, ^{
// 在多线程环境下,永远只会被执行一次,instance只会被实例化一次
instance = [super allocWithZone:zone];
});
return instance;
}
67 NSThread [self performSelectorInBackground:@selector(setImagePath:) withObject:@"头像1.png"];
[self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageNamed:imagePath] waitUntilDone:NO];
1> 不能够自动回收线程,如果并发数量多,会建立大量的子线程!
2> 使用NSThread的线程,不会自动添加autoreleasepool
主线程中是有自动释放池的,使用GCD和NSOperation也会自动添加自动释放池
NSThread和NSObject不会,如果在后台线程中创建了autorelease的对象,需要使用自动释放池,否则会出现内存泄漏!
自动释放池工作原理:
1. 当自动释放池被销毁或者“耗尽”时,对池中的所有对象发送release消息,清空自动释放池
2. 所有autorelease的对象,在出了作用域之后,会自动添加到【最近一次创建的自动释放池中】自动释放池中
在ARC中,编译器在编译过程中,会自动根据代码结构,添加retain和release。
68 SearchBar UISearchBarDelegate,WebView UIWebViewDelegate
69 网络get post
NSString *urlStr = [NSString stringWithFormat:@"http://localhost/login.php?username=%@&password=%@", self.userName.text, self.userPwd.text];
NSURL *url = [NSURL URLWithString:urlStr];
// 2. Request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError == nil) {
// 网络请求结束之后执行!
// 将Data转换成字符串
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// num = 2
NSLog(@"%@ %@", str, [NSThread currentThread]);
// 更新界面
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.logonResult.text = @"登录完成";
}];
}
}];
// 1. URL
NSURL *url = [NSURL URLWithString:@"http://localhost/login.php"];
// 2. 请求(可以改的请求)
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// ? POST
// 默认就是GET请求
request.HTTPMethod = @"POST";
// ? 数据体
NSString *str = [NSString stringWithFormat:@"username=%@&password=%@", self.userName.text, self.userPwd.text];
// 将字符串转换成数据
request.HTTPBody = [str dataUsingEncoding:NSUTF8StringEncoding];
// 3. 连接,异步
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (connectionError == nil) {
// 网络请求结束之后执行!
// 将Data转换成字符串
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
// num = 2
NSLog(@"%@ %@", str, [NSThread currentThread]);
// 更新界面
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.logonResult.text = str;
}];
}
}];
NSURLConnectionDataDelegate
// 1. URL
NSString *urlStr = [NSString stringWithFormat:@"http://localhost/login.php?username=%@&password=%@", self.userName.text, self.myPwd];
NSLog(@"%@", self.myPwd);
NSURL *url = [NSURL URLWithString:urlStr];
// 2. Request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 3. 连接,已经10多岁了
// 是一个很古老的技术
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
// 开始工作,在很多多线程技术中,start run
dispatch_async(dispatch_queue_create("demo", DISPATCH_QUEUE_CONCURRENT), ^{
[connection start];
});
70 JSON的序列化和反序列化
/ 将接收到的二进制数据反序列化为数据字典
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:NULL];
requestM.HTTPBody = [NSJSONSerialization dataWithJSONObject:obj options:0 error:NULL];
71 dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"网络不给力" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
}];
[[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"提示" message:@"网络不给力" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
[alert show];
}];
72 可以在storyboard 点击view controller 开启refreshControl
73 /
// 在继承子类中,需要使用合成指令生命成员变量
// 在继承自类中,如果需要使用属性的成员变量,需要使用@synthesize指令
@synthesize groups = _groups;
74/**
苹果官方要求,写入文档目录的文件只能是应用本身创建的文件
从网络上下载的文件,是不能存储在文档目录中的,应该保存在缓存路径中
*/
75 copy
在堆中的变量,系统只负责维护空间不管变量类型.
用指针的时候,需要使用类型比如NSString,Person
栈区(1M) Char Int Float Double
NSCopying copyWithZone
深复制:要改地址
浅复制:不改地址
只有不可变对象创建不可变副本(copy)才是浅复制,其他都是深复制
Int 是在栈区的,效率高,速度快,可以放在方法内部使用
NSNumber是对象,在堆中的,自带了数值转换功能,效率差一些,方便KVC赋值
76 HTTP HEAD方法
request.HTTPMethod = @"HEAD";HEAD方法只是返回资源信息,而不会返回数据体
获取资源Mimetype
获取资源文件大小,用于端点续传或多线程下载
77通过设置Range可以指定每次从网路下载数据包的大小
78 多线程下载 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:kTimeOut];
NSFileHandle *fp = [NSFileHandle fileHandleForWritingAtPath:self.cachePath];
// 如果文件不存在,直接写入数据
if (!fp) {
[data writeToFile:self.cachePath atomically:YES];
} else {
// 移动到文件末尾
[fp seekToEndOfFile];
// 将数据文件追加到文件末尾
[fp writeData:data];
// 关闭文件句柄
[fp closeFile];
}
79 UIButton
// 高亮的时候不要自动调整图标
self.adjustsImageWhenHighlighted = NO;
// 图标居中
self.imageView.contentMode = UIViewContentModeCenter;
// 文字居中
self.titleLabel.textAlignment = NSTextAlignmentCenter;
UIButton.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
UIButton.imageEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 10);
// UIButton.contentEdgeInsets = UIEdgeInsetsMake(10, 10, 10, 10);
80 NSString *key = @"CFBundleVersion";
// 获得当前软件的版本号
NSString *currentVersion = [NSBundle mainBundle].infoDictionary[key];
81 self.tableView.backgroundColor = IWColor(226, 226, 226);
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, IWStatusTableBorder, 0);
82
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
// 左边按钮
self.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithIcon:@"navigationbar_friendsearch" highIcon:@"navigationbar_friendsearch_highlighted" target:self action:@selector(findFriend)];
83
// 4.通过动画移动按钮(按钮向下移动 btnH + 1)
[UIView animateWithDuration:0.7 animations:^{
btn.transform = CGAffineTransformMakeTranslation(0, btnH + 2);
} completion:^(BOOL finished) { // 向下移动的动画执行完毕后
// 建议:尽量使用animateWithDuration, 不要使用animateKeyframesWithDuration
[UIView animateWithDuration:0.7 delay:1.0 options:UIViewAnimationOptionCurveLinear animations:^{
btn.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
// 将btn从内存中移除
[btn removeFromSuperview];
}];
}];
84
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
fmt.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";
#warning 真机调试下, 必须加上这段
fmt.locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
85 [UILabel sizeToFit];
// 垂直方向上永远可以拖拽
textView.alwaysBounceVertical = YES;
86
/**
让程序保持后台运行
1.尽量申请后台运行的时间
[application beginBackgroundTaskWithExpirationHandler:^{
}];
2.在Info.plist中声明自己的应用类型为audio、在后台播放mp3
*/
/**
* app进入后台会调用这个方法
*/
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// 在后台开启任务让程序持续保持运行状态(能保持运行的时间是不确定)
[application beginBackgroundTaskWithExpirationHandler:^{
// IWLog(@"过期了------");
}];
// 本地通知,定时提醒(定时弹框)
// [UILocalNotification ];
}
87
block修改外面的值 加_block 变量,数字变对象@数字 ,-568h@2x修改 Contents.json
88
self.tableView.sectionHeaderHeight = 5;
self.tableView.sectionFooterHeight = 0;
if (iOS7) {
self.tableView.contentInset = UIEdgeInsetsMake(-30, 0, 0, 0);
}
89
IWBadgeButton *badgeButton = [[IWBadgeButton alloc] init];
badgeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin;
90 UITextFieldDelegate
- (BOO L)textFieldShouldReturn:(UITextField *)textField