iphone 5.5inch 540*960
第二周Lab.textAlignment = NSTextAlignmentCenter; 设置字体居中TextField.placeholder = @"请输入密码"; 设置隐藏编辑字符TextField.secureTextEntry = YES; 设置是否安全键入TextField.borderStyle = UITextBorderStyleRoundedRect; 设置边框样式 border 边角TextField.clearButtonMode = UITextFieldViewModeAlways; 设置清除文本框[t addTarget:self action:@selector(XX) forControlEvents:UIControlEventEditingDidEndOnExit]; 设置return键取消键盘是否允许剪切 earth.clipsToBounds=YES;这个值设置长宽高的一半 earth.layer.cornerRadius=20;字符串判断是否相等 isEqualToString去掉字符串中的空格和空白str = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]返回参数字符串在原字符串中的位置和长度//返回值是NSRange,类似于CGRect,CGPoint//NSRange有两个属性,location,length//location,参数字符串的第一个字符在原字符串中的位置//length,参数字符串的长度//如果原字符串不包含参数字符串,返回的NSRange的location的值为NSNotFoundif ([urlString rangeOfString:@"code"].location == NSNotFound) {};//substringToIndex,截取字符串,从0开始,到index结束//substringFromIndex,截取字符串,从index开始,到末尾结束//substringWithRange,截取字符串,从location开始,长度为length textView.text = [resultString substringToIndex:10];#define 宏定义 分为 常量宏 函数宏IBAction 绑定方法 IBOutlet 关键字 关联对象 (xib中在.h文件中写的)如果xib文件被修改后 需手动加载xib文件 调用 [ ]initWithNibName:@“”……获取window的方式:1. UIWindow *window = [UIApplication sharedApplication].keyWindow;2. AppDelegate * app =[UIApplication sharedApplication].delegate;UIWindow *window = app.window;3. NSArray *array = [UIApplication sharedApplication].Windows;UIWindow *window = [array objectAtIndex : 0 ]; 部分可用 self.view.window字符串拼接来找图片的图片名 (格式化字符串)NSString* imageName = [NSString stringWithFormat:@"Fire%d.gif",i];根据图片名找图片放到fire的imageView上 fire.image = [UIImage imageNamed:imageName];让定时器方法不再等待第一个时间差 [Timer fire];暂时关闭定时器 [timer setFireDate:[NSDate distantFuture]];再开启定时器 [timer setFireDate:[NSDate distantPast]];永久关闭定时器 [timer invalidate]; timer = nil;输出一个对象的CGRect , CGPoint ,CGSize :NSLog(@"%@",NSStringFromCGRect(CGRect rect));NSLog(@"%@",NSStringFromCGPoint(CGPoint point));NSLog(@"%@",NSStringFromCGSize(CGSize size));//输出字节数 NSLog(@"int---%lu",sizeof(int)); NSLog(@"long---%lu",sizeof(long));第三周开辟线程的两种方法//开辟分线程的时候,绑定一个方法,让这个方法在分线程里面执行.[NSThread detachNewThreadSelector:@selector(new) toTarget:self withObject:nil];NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(new) object:nil]; 通过alloc 方法开辟线程 需要去调用start方法 [thread start];解决多个线程同时访问一个数据(类比 多个卖票点同时卖一张火车票),1.NSLock 加线程锁, // _lock = [[NSLock alloc] init];// [_lock lock]; 线程队列执行// [_lock unlock];2,线程同步块 @synchronized(self)分线程中不能开启 Timer分线程中不会执行UI的更新,要回到主线程去更新 [self performSelectorOnMainThread:(SEL) withObject:(id) waitUntilDone:(BOOL)];waitUntilDone: 为yes 让分线程等待,直接去主线程中执行,执行完毕后继续执行当前的分线程为NO, 分线程执行结束再去执行主线程当前线程休眠 [NSThread sleepForTimeInterval:(NSTimeInterval)];[Thread MainThread]; [Thread currentThread]; //判断当前线程是否为主线程,返回值为 BOOL类型 [NSThread isMainThread];12.31号 :// 获取URL地址上的data 方法 是一个同步的方法 NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/pic/item/e4dde71190ef76c666af095f9e16fdfaaf516741.jpg"]];//perform 执行, 在主线程中执行一个方法,可以传一个参数给这个方法// 拿到数据之后 回到主线程刷新UI 分线程不能刷新UI [self performSelectorOnMainThread:@selector(setImageViev:) withObject:data waitUntilDone:YES];3,操作队列://用操作队列可以解决线程同步的问题,如果有多个操作的话,每个操作随机先执行,执行完一个操作之后才去执行另外一个操作,不会出现一个数据同时被多个操作访问的情况. // 创建一个操作 绑定相应的方法,当把操作添加到操作队列中时 操作绑定的方法就会自动执行了 // 创建一个操作队列 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; // 1,系统提供的操作 // 调用操作 NSInvocationOperation *operation1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSomeThing) object:nil]; // 把操作添加到操作队列中 [queue addOperation:operation1];设置导航栏标题第一种self.title = @"setting"; 第二种self.navigationItem.title = @"1111";第三种 UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];lab.text = @"111222";lab.backgroundColor = [UIColor redColor];self.navigationItem.titleView = lab;设置导航栏右边按钮选项UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(buttonClick:)];self.navigationItem.rightBarButtonItems = rightButton ;跳转到下一个界面1. SecondViewController *secondVC = [[SecondViewController alloc] init]; [self.navigationController pushViewController:secondVC animated:YES];2.模态弹出 SecondViewController *secondVC = [[SecondViewController alloc] init];[self.navigationController presentViewController:secondVC animated:YES completion:nil];(如果使用模态弹出,此时没有导航栏且ViewController 不会被加载到导航控制器中,那么就不能使用pop方法) 若想返回上一个界面,要使用 [self.navigationController dismissViewControllerAnimated:YES completion:nil]; //模态弹出的样式( 非全屏 formSheet,pageSheet) vc.modalPresentationStyle = UIModalPresentationFormSheet; //模态弹出的动画方式 vc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;返回到上一个界面[self.navigationController popViewControllerAnimated:YES];返回到根视图界面[self.navigationController popToRootViewControllerAnimated:YES];返回到指定视图界面(获取导航器中的所有导航控制器) NSArray *array = self.navigationController.viewControllers;[self.navigationController popToViewController:[array objectAtIndex:0] animated:YES];在一个数组中插入数组NSMutableArray *array1 = [NSMutableArray arrayWithObjects: @"one", @"two", @"three", @"four", nil];NSArray *newAdditions = [NSArray arrayWithObjects: @"a", @"b", nil];NSMutableIndexSet *indexes = [NSMutableIndexSet indexSetWithIndex:1];[indexes addIndex:3];// indexes 1 3[array1 insertObjects:newAdditions atIndexes:indexes];NSLog(@"array: %@", array)// Output: array: (one, a, two, b, three, four) 替换多个索引值的对象(NSIndexSet *) 索引[arr replaceObjectsAtIndexes:(NSIndexSet *) withObjects:(NSArray *)];从第二界面回到第一界面时 此时viewdidload方法不再执行,因为视图已经加载过了此时需要重写viewWillAppear(视图将要显示)- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; NSLog(@"从第二个页面得到的内容 %@",self.fromSecondText);// 把第二界面的内容赋值给text1 text1.text = self.fromSecondText;}判断从数组中取的对象是否是( )类型的对象用 iskindOfClassScrollView.contentSize (容量大小)设置水平竖直方向的标示符scrollView.showsHorizontalScrollIndicator = YES;scrollView.showsVerticalScrollIndicator = YES;设置是否可以分页scrollView.pagingEnabled = YES;设置是否回弹scrollView.bounces = YES;设置偏移量 (向左为正 向右为负)scrollView.contentOffset = CGPointMake(30, 0);设置拖动过程中水平或者垂直方向能否被锁定scrollView.directionalLockEnabled = YES;设置 scrollView 四个边界的预留空白区域scrollView.contentInset = UIEdgeInsetsMake(40, 40, 0, 0);ScrollView中实现图片的缩放设置它的最大放大比例(长和宽) _scrollView.maximumZoomScale = 4; _scrollView.minimumZoomScale = 0.25; 返回需要缩放的 View,这个 View 必须是 scrollview 的子 View,实现了这个方法,scrollview 就可以实现缩放了。 如果使用了 scrollView 的缩放功能,就不能再用它的滑动效果,否则会乱。- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView{ return _imageView;}当 scrollView 已经缩放时的回调- (void)scrollViewDidZoom:(UIScrollView *)scrollView{ //_imageView.center = self.view.center;(缩小的时候可以用) if (scrollView.zoomScale<1) { float width = _scrollView.frame.size.width*(1-scrollView.zoomScale)/2; float height = _scrollView.frame.size.height*(1-scrollView.zoomScale)/2; scrollView.contentInset = UIEdgeInsetsMake(height, width, 0, 0); }}PageControl.numberOfPages 设置页数(几个点)PageControl.currentPage 当前的页数系统 tabBar的选项 pay.tabBarItem = [[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemRecents tag:1];若要给它换图片,用pay.tabBarItem = [[UITabBarItem alloc] initWithTitle:@"pay" image:[UIImage imageNamed:@"1"] selectedImage:[UIImage imageNamed:@"1"]];给tabBar 设置多个视图控制器NSArray *vcArray = @[nav1,nav2,nav3,nav4,five,six];tabBarController.viewControllers = vcArray;设置当前选中的索引tabBarController.selectedIndex = 0; 1.创建多个视图控制器 2.创建UITabBarController的实例 3.把UITabBarController的对象做为根视图添加到window上 4.将所有的视图控制器添加到tabbar上 5.设置tabbar中的item设置样式toolBar.barStyle = UIBarStyleDefault;UIBarButtonItem *barButton1 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:Nil];设置BarButtonItem 之间的固定空间UIBarButtonItem *FixedSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:self action:Nil];宽度 FixedSpace.width = 20; NSArray *itemArray = @[FixedSpace,barButton2,FixedSpace,barButton3];[toolBar setItems:itemArray animated:YES];ActionSheet 中的按钮是从上到下来按顺序设置索引值的AlertView 中的按钮中“取消”的索引值是0,其他的按顺序设置若要使用系统的代理方法,要在.h 文件声明类的后面加上<UI XXX Delegate>第四周代理如果一个页面以及上面的内容会在不同的时候出现,此时可以把这个相同的东西封装到一个类当中, 若此页面出现的时候需要调用一些方法,此时为了区分它们,我们可以在封装类的头文件中声明一个 id 类型的对象(delegate),并在@end 下面用@protocol声明此对象的方法(此方法的实现内容在具体出现的页面中实现),让其在需要用的时候调用。@end@protocol XXXDelgate <NSObject>@optional- (void)myView:(UIView *)myView clickedButtonAtIndex:(NSInteger)buttonIndex;@end继承于 UIView的类所创造的对象可以打点调用 hidden 设置为 YES 让其隐藏。 数据源 pickerView.dataSource = self; 有两个必须实现的方法代理 pickerView.delegate = self;[pickerView selectedRowInComponent:0]; 获得第0区的第Row行刷新第一个区 [pickerView reloadComponent:1];选中第1区的第0行[pickerView selectRow:0 inComponent:1 animated:YES];#pragma mark 杂注设置样式datePicker.datePickerMode = UIDatePickerModeDateAndTime;获取picker的时间NSDate *date = picker.date;创建时间格式化器NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 设置date的格式[dateFormatter setDateFormat:@"yyyy-MMMM-dd-EEE-aa"];把时间转换成字符串NSString *dateString = [dateFormatter stringFromDate:date];yy: 年的后2位 yyyy: 完整年 MM: 月,显示为1-12 MMM: 月,显示为英文月份简写,如Jan MMMM: 月,显示为英文月份全称,如Janualydd: 日,2位数表示,如02 d: 日,1-2位显示,如 2EEE: 简写星期几,如Sun EEEE: 全写星期几,如Sundayaa: 上下午,AM/PMH: 时,24小时制,0-23K:时,12小时制,0-11m: 分,1-2位 mm: 分,2位s: 秒,1-2位 ss: 秒,2位 S: 毫秒Z: 时区常用日期结构:yyyy-MM-dd HH:mm:ss.SSSyyyy-MM-dd HH:mm:ssyyyy-MM-ddMM dd yyyy 第五周获取标题宽度width = button.titleLabel.frame.size.width;UIFont *font = [UIFont systemFontOfSize:17];CGSize size = [@"百度" sizeWithFont:font];webView 网页视图_webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];[self.view addSubview:_webView]; // 创建 链接NSURL *url = [[NSURL alloc] initWithString:@"http://www.baidu.com"];// 创建请求NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];// 加载请求[_webView loadRequest:request];不能深度赋值应该这样:CGRect rect = rainImage.frame; rect.origin.y = 305; rainImage.frame = rect;如果把 Image 盖在 button 上面,在 image 上点击 button 效果还会被触发,如果是把 View 盖在上面,button 效果不会被触发。UITableView设置分割线的颜色 tableView.separatorColor实现表的数据源方法下面黄色部分可以相互代替(写在 tableView 的创建后面)给 tableview 的 ReuseIdentifier 注册一个 cell类,当 tableview 找不到可以重用的 cell 时,就会自动创建一个这种类型的 cell[_table registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *cellIdentifier = @"cell"; // 在队列中查询有没有可以重用的单元格 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; // 如果没有单元格 就去创建新的单元格 if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; } return cell;}如果是自定义表加载 xib 时,要用if (!cell) { //手动加载xib文件 NSArray *array = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:Nil options:Nil]; //强转 cell = (CustomCell *)[array objectAtIndex:0]; }自定义区头后一定要记得设置区头和区尾的高度// 设置索引标题- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{ return _array;}// 完成编辑- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{ (此方法写上以后向右划定单元格会出现删除按钮,移除单元格的方法也就写在这个方法里面)}//设置是否可以移动- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{ return YES;}//改变数据- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath{ 找到sourceIndexPath所在的位置(区、行)并把它从当前的数组中移除,然后把 sourceIndexPath加入到destinationIndexPath所在的位置(区、行),完成操作后一定要刷新表}刷新表的两种方法:1.[_tableView reloadData];2. NSIndexSet 索引集合 把将要改变的区加入到索引集合中 NSMutableIndexSet 可变的索引集合 NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSetWithIndex:section];[_tableView reloadSections:indexSet withRowAnimation:UITableViewRowAnimationFade];第二种方法比较高效刷新表的时候,表的数据源方法和代理方法都要重新执行一次Rotation 旋转顺时针旋转90Button.transform = CGAffineTransformMakeRotation(M_PI_2);transform默认为CGAffineTransformIdentity// 获取最后一行的索引 NSIndexPath *indexPath = [NSIndexPath indexPathForRow:_messageArray.count - 1 inSection:0];// _tableView滑动 [_tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];// 自适应高度 CGRect rect = [contentText boundingRectWithSize:CGSizeMake(160, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:17]} context:Nil];UIImage *old = _whoSay ?[UIImage imageNamed:@"bubbleSelf"]:[UIImage imageNamed:@"bubble"];UIImage *image = [old stretchableImageWithLeftCapWidth:10 topCapHeight:10];imageView.image = image;第六周NSNumber 能够把基本类型的数据包装成一个对象,此对象可以存进数组。 _sectionOpenArray = [[NSMutableArray alloc]initWithObjects:[NSNumber numberWithBool:NO], [NSNumber numberWithBool:NO],[NSNumber numberWithBool:NO],nil];利用 NSNumber 实现 BOOL 值的转换来改变tableView 中区的打开与关闭[_sectionOpenArray replaceObjectAtIndex:button.tag withObject:[NSNumber numberWithBool:![[_sectionOpenArray objectAtIndex:button.tag] boolValue]]];设置 alert 的样式,不同样式上面的 textfield 数量和类型不同 alert.alertViewStyle = UIAlertViewStylePlainTextInput; [alert textFieldAtIndex:0].placeholder = @"用户名";用 alert 在 tableView 中添加一个分组if (alertView.tag == 100) { //首先在好友数组中添加一个新的数组,用来存放这个区的好友 [_friendArray addObject:[NSMutableArray arrayWithCapacity:0]]; //然后再分组名称数组中添加这个新分组的名字 NSString *name = [alertView textFieldAtIndex:0].text; [_sectionNameArray addObject:name]; //最后在控制打开关闭的数组中给这个新区添加一个 NSnumber,用来标记它的打开状态 [_sectionOpenArray addObject:[NSNumber numberWithBool:NO]]; [_table reloadData]; }//从 iOS7 开始,状态栏和 navigationBar 与 viewController 合为一体(ViewController 的 View 左上角从屏幕左上角开始),为了保证 tableview 或者 scrollView 顶部的内容不被 navigationBar 挡住,ViewController回自动给自身上的 scrollerView 顶部添加64的 inset,如果不需要这个 inset,automaticallyAdjustsScrollViewInsets设置为 NO 即可。 self.automaticallyAdjustsScrollViewInsets = NO; _table.contentInset = UIEdgeInsetsMake(64, 0, 0, 0); //刷新控制器 UIRefreshControl *control = [[UIRefreshControl alloc] init]; //设置菊花颜色 control.tintColor = [UIColor redColor]; //设置下拉刷新标题 NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"下拉刷新"]; [str setAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIFont systemFontOfSize:20],NSFontAttributeName,[UIColor redColor],NSForegroundColorAttributeName, nil] range:NSMakeRange(0, 4)]; control.attributedTitle = str; //把刷新控制器和tableViewController结合 self.refreshControl = control; //停止下拉刷新的转动动画 [self.refreshControl endRefreshing];为什么要管理内存?计算机的内存是有限的,如果我们需要使用一个对象,会在内存中创建这个对象,内存使用量就会越来越多,如果只创建,不去释放,那么就会造成内存撑爆。所以,我们在使用一个对象时创建,不再使用这个对象时,要把它释放。不同语言管理内存的方式Java:全自动内存管理:Java 运行时,每隔一段时间就会自动检查内存当中的所有对象,当发现不再使用的对象时,就会把这个对象从内存中释放。这个功能叫做 Java 垃圾回收机制。这种内存管理机制使用方便,但是运行效率低。C++:全手动内存管理:当需要使用一个对象时创建,确定不再使用这个对象时,手动把它释放掉。这种内存管理机制使用麻烦,但是运行效率高。OC:通过引用计数来管理内存(半自动管理内存):对象的引用计数就是标记当前有多少个其他对象正在使用这个对象。当其他对象需要使用这个对象时,要把这个对象的引用计数加1,当某个其他对象不再使用这个对象时,要把这个对象引用计数减1。一旦某个对象的引用计数为0,那么它就会被系统释放掉。*全局指针需要在dealloc中release。 *局部指针需要在方法结束前releasesuper dealloc目的是释放掉父类的全局指针指向的对象。super dealloc必须写在最后,因为要先释放自己的全局属性,再释放父类的全局属性通过alloc,new,copy创建出来的对象,引用计数为1 其他的方式创建的对象,都是延迟释放的。 new就相当于alloc+initretain方法使一个对象引用计数+1 release方法使一个对象引用计数-1如果一个指针指向了一个对象,那么这个指针指向另外一个对象时,需要先把之前指向的对象release一次。否则就会导致内存泄露。*引用计数管理原则:谁创建,谁释放,谁使用,谁管理。alloc的数量+retain的数量=release的数量把对象放进数组后,数组会对这个对象的引用计数+1当数组移除某个对象时,这个对象的引用计数-1当数组将要被释放时,会对这个内部的所有对象release一次。当一个视图添加到父视图上时,父视图会对这个视图引用计数+1当一个视图将要被释放时,会对自己的所有子视图release一次。用buttonWithType创建的button,addSubview之后不需要releasealertView show之后会导致alert引用计数增加。 alertView show之后立刻release模态弹出一个vc之后,vc的引用计数会增加。 vc模态弹出或者push之后立刻release*如果property为retain(copy)形式,当打点调用赋值时,会先对之指向的对象release一次,再对新指向的对象retain(copy)一次对于对象的set方法,需要先对之前的对象release一次,然后对新的对象retain一次对于全局的timer一般需要在界面消失的时候停止,而不是dealloc中停止,因为timer如果不停止,那么timer的target就不会释放。dealloc就不会执行。NSTimer只要还在执行,即使引用计数为0,也不会被释放,直到timer停止才可能被释放。UIImage的imageNamed方法虽然是延迟release的,但是并不会在事件循环结束的时候release。delegate的property要用assign描述,否则会导致循环引用,最后两个对象都释放不掉//用storyboard设计的viewController需要用UIStoryboard加载 UIStoryboard *board = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; ViewController *vc = [board instantiateInitialViewController];单例类1、单例类只有一个实例(对象)2、单例类必须提供一个获得这个唯一实例的方法3、单例类能够自动创建这个唯一的实例自定义单例类static Singleton *__singleton = nil;+(Singleton *)defaultSingleton{ //为了防止多个线程同时判断单例是否存在,从而导致同时创建单例。判断的时候必须加线程同步。 @synchronized(self){ if (!__singleton) { __singleton = [[Singleton alloc] init]; } } return __singleton;}//为了防止人为创建单例类,重写alloc方法。+ (id)alloc{ //dispatch_once 的block中的代码当程序运行后只会被执行一次。 //单例类的创建最好用dispatch_once。 //使用dispatch_once就不需要再进行判断,也不需要关心线程同步。 static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ __singleton = [super alloc]; }); return __singleton;}通知是 iOS中的一种调用机制,当发送通知时,不需要关心谁来接收,需要接收这个通知的对象需要自己去监听这个通知。 通知和代理的区别:相同之处,都可以实现回调,都可以传参。不同之处,代理只能一对一调用,而且必须明确代理对象,通知可以实现多对多调用,而且不需要关心通知的接收者;代理的协议方法可以有返回值,但是通知的调用方法不能加返回值。UIApplication就是单例类,我们使用的时候没有alloc 而是通过sharedApplication找到单例对象[UIApplication sharedApplication]NSNotificationCenter是单例类。通知中心类似于广播站,发送任何通知都必须通过通知中心发送。NSNotificationCenter *center = [NSNotificationCenter defaultCenter];//字典,也是一种对象的容器,和数组不同的是,数组中的对象按照顺序存储,而字典中的对象按照键值对存储。NSDictionary *dic = [[NSDictionary alloc] initWithObjectsAndKeys:color,@"color", nil];//NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:color,@"color", nil];//postNotification,发送一个通知//第一个参数name是发送的通知的名字,用来区分不同的通知。//第二个参数object是通知的发送者,一般都写self//第三个参数是通知的参数,用来传参.[center postNotificationName:@"changeColor" object:self userInfo:dic];//addObserver添加一个监听者(让某个对象可以接收通知)。 //第一个参数observer就是添加的监听者,就是让哪个对象去接受通知 //第二个参数selector当监听者收到通知时调用的方法。 //第三个参数name,监听的通知名字,只监听哪个通知。 //第四个参数object,限定通知来源(只接受某个对象发的通知),如果不限定,写成nil[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveChangeColorNotification:) name:@"changeColor" object:nil];- (void)receiveChangeColorNotification:(NSNotification *)noti{ //当收到通知时调用方法会传过来一个NSNotification类型的参数,这个参数包含了name,object,和userInfo。 self.view.backgroundColor = [noti.userInfo objectForKey:@"color"];}removeObserver取消所有的通知监听。*当一个对象将要被释放时,如果这个对象注册有监听通知,那么在释放前(也就是dealloc中)必须取消所有的监听,否则就会导致程序崩溃[[NSNotificationCenter defaultCenter] removeObserver:self];- (void)introduceSelf{ NSLog(@"%@",self);}//description方法用来设置NSLog这个对象时输出的内容。如果不设置,默认输出为内存地址- (NSString *)description{ return [NSString stringWithFormat:@"我叫%@,今年%d岁,性别%@",_name,_age,_sex?@"男":@"女"];}//UIApplicationDidEnterBackgroundNotification应用程序已经进入后台的通知。//UITextFieldTextDidChangeNotification输入框中内容改变时的通知//UIKeyboardWillChangeFrameNotification键盘的frame将要发生改变的通知NSValue能够把结构体封装成对象,就可以放入数组或字典。 NSValue *value = [noti.userInfo objectForKey:UIKeyboardFrameEndUserInfoKey]; //获得键盘的坐标 CGRect rect = [value CGRectValue]; //获得动画时间 float duration = [[noti.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; int curve = [[noti.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];数据的存储沙盒:在存储器中一块独立的空间,这个空间中存储了一个应用,以及这个应用的数据,那么这块空间就叫做这个应用的沙盒。沙盒运行模式:应用程序在运行时,对硬盘的操作权限仅限于自己沙盒内部,不能对沙盒外部的空间进行直接操作。沙盒内部有4个文件夹, Documents,library,tmp,app Documents 存储应用的文档文件,对于开发者最常用. library 存储应用设置或配置的相关信息,也存储一些系统数据,提供给系统使用,一般情况下不在这个文件夹下存储文件. tmp 临时文件夹,用来存储一些临时文件 app 应用资源文件夹,存储应用所需要的所有资源,此文件夹只能读,不能修改. 1.使用NSUserDefaults存储数据 // NSUserDefaults 用户数据存储器,常用来存储和一些用户信息或用户设置有关的一些数据 // NSUserDefaults 单例类 NSUserDefaults *user = [NSUserDefaults standardUserDefaults]; // NSUserDefaults 类似字典,但不是字典,它可以存对象,还可以存基本类型. [user setObject:name forKey:@"name"]; [user setInteger:age forKey:@"age"]; [user setBool:sex forKey:@"sex"]; // NSUserDefaults 修改后必须立刻同步一次(存储到硬盘),否则修改无效. [user synchronize]; // NSUserDefaults 中的内容存储在沙盒下 library 文件夹中从 NSUserDefaults 中读取数据 NSString *name = [[NSUserDefaults standardUserDefaults] objectForKey:@"name"]; int age = [[NSUserDefaults standardUserDefaults] integerForKey:@"age"]; BOOL sex = [[NSUserDefaults standardUserDefaults] boolForKey:@"sex"]; _name.text = name; _age.text = [NSString stringWithFormat:@"%d",age]; _sexControl.selectedSegmentIndex = sex;2.使用数组存储数据 NSArray *array = [[NSArray alloc]initWithObjects:name,_age.text,sex?@"男":@"女", nil]; //Directory (计算机文件或程序)的目录 //Appending 附加 添加 贴上 Component 构成 成分 //NSHomeDirectory()找到当前应用的沙盒路径。 //stringByAppendingPathComponent当一个路径后追加路径。 NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/abc.xml"]; //writeToFile 把数据存入文件,第一个参数是路径名,第二个参数是是否原子性(是否使用临时文件存储). [array writeToFile:path atomically:NO]; [array release]; //文件名的后缀和文件内容没有关系,后缀仅仅是标记了这个文件的类型,也就是这个文件应该用什么工具去打开.从文件当中读取数组. NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/abc.xml"]; NSArray *array = [[NSArray alloc]initWithContentsOfFile:path]; _name.text = [array objectAtIndex:0]; _age.text = [array objectAtIndex:1]; _sexControl.selectedSegmentIndex = [[array objectAtIndex:2] isEqualToString:@"男"]?0:1;//判断某个文件是否存在[[NSFileManager defaultManager]fileExistsAtPath:directoryPath] //创建一个文件夹 [[NSFileManager defaultManager ] createDirectoryAtPath:directoryPath withIntermediateDirectories:YES attributes:nil error:nil];//创建一个文件[[NSFileManager defaultManager]createFileAtPath:filePath contents:nil attributes:nil];3.使用字符串拼接存储数据 NSString *string = [NSString stringWithFormat:@"%@|%@|%@",name,_age.text,sex?@"女":@"男"]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"]; //把字符串存入文件,第一个参数是存储路径,第二个参数是原子性,第三个参数是编码方式,iOS 的默认编码方式是 UTF8编码,第四个参数是如果写入失败,失败的原因. [string writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:nil];3. NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"]; NSString *string = [[NSString alloc]initWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil]; //按照某个字符串分割成一个长字符串,得到一个数组,数组中就是分割成的若干个字符串. NSArray *arr = [string componentsSeparatedByString:@"|"]; _name.text = [arr objectAtIndex:0]; _age.text = [arr objectAtIndex:1]; _sexControl.selectedSegmentIndex = [[arr objectAtIndex:2] isEqualToString:@"男"]?0:1; [string release];NSUserDefaults只能存系统自带的数据类,例如NSArray,NSString,int,BOOL等,自定义的类不能存。NSArray(NSDictionary)只有当存储的对象都是系统自带的数据类时,才可以writeToFile,如果数组中存有自定义类,那么就不能writeToFile.NSData数据类,存储了一段二进制数据。NSDate可以直接存入文件 //对于自定义类,如果想存入文件,必须先转化为二进制数据。这个转化的过程叫做对象序列化。 //只有实现了NSCoding协议,这个类才能被转化为二进制数据 //NSKeyedArchiver编码器,能够把实现了NSCoding协议的对象编码成二进制数据. NSData *data = [NSKeyedArchiver archivedDataWithRootObject:p]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.plist"]; [data writeToFile:path atomically:NO];从文件中读取NSData NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.plist"]; NSData *data = [NSData dataWithContentsOfFile:path]; //NSKeyedUnarchiver解码器,能够把二进制数据还原成原来的对象。 People *p = [NSKeyedUnarchiver unarchiveObjectWithData:data]; _nameField.text = p.name; _ageField.text = [NSString stringWithFormat:@"%d",p.age]; _sexControl.selectedSegmentIndex = p.sex;实现 NSCoding 协议(先在.h 文件中用<NSCoding>在想要实现的类后追加) //编码方法。- (void)encodeWithCoder:(NSCoder *)aCoder{ //如果父类也遵守NSCoding协议,需要先调用super encodeWithCoder //在编码方法中,把需要编码的数挨个进行编码 [aCoder encodeObject:_name forKey:@"name"]; [aCoder encodeInt:_age forKey:@"age"]; [aCoder encodeBool:_sex forKey:@"sex"];} //解码方法。- (id)initWithCoder:(NSCoder *)aDecoder{ self = [super init]; //在解码方法中,对编码过的属性逐一解码 if (self) { _name = [[aDecoder decodeObjectForKey:@"name"] copy]; _age = [aDecoder decodeIntForKey:@"age"]; _sex = [aDecoder decodeBoolForKey:@"sex"]; } return self;}指针本身也是个变量,也需要占用内存,所以指针本身也有内存地址。 // NSString **str;两个星的指针叫做双指针,也就是指向指针的指针(指向指针的内存地址)。&取地址符,获得一个指针的内存地址 //NSString **dString = &string;/方法传参时如果要传递一个指针,那么不能直接写这个指针,因为写成指针实际传递的是这个指针指向的对象,所以如果要传递指针,参数必须写成指向这个指针的指针。// NSFileManager 文件管理器,对文件进行删除,移动,复制,剪切等操作。 //NSFileManager也是单例类 NSFileManager *manager = [NSFileManager defaultManager]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"]; NSError *err = nil; //删除一个文件,如果删除失败,输出失败的原因 if (![manager removeItemAtPath:path error:&err]) { NSLog(@"%@",err); }/创建文件夹 NSFileManager *manager = [NSFileManager defaultManager]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/abc/123"]; //withIntermediateDirectories是否自动创建路径中不存在的文件夹。 [manager createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];//查看文件属性- (IBAction)checkFileAttribute:(UIButton *)sender { NSFileManager *manager = [NSFileManager defaultManager]; NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/string.txt"]; NSDictionary *dic = [manager attributesOfItemAtPath:path error:nil]; NSLog(@"%@",dic);}UIImagePickerController 图片选择器 把图片转化成data的 NSData *data = UIImageJPEGRepresentation(_imageView.image, 0.5);//图片可编辑 controller.allowsEditing = YES;第七周//FMDB是对sqlite3的封装,内部使用的也是sqlite3,所以要使用FMDB,需要先导入sqlite3库//FMDatabase数据库操作类,可以打开或创建一个数据库文件。 FMDatabase *_db;//打开或创建一个数据库文件 _db = [[FMDatabase alloc]initWithPath:[NSHomeDirectory() stringByAppendingPathComponent:@"Documents/data.sqlite"]]; //打开数据库 [_db open]; //在这个数据库中创建一张表 executeUpdate 执行一条修改语句 [_db executeUpdate:@"CREATE TABLE IF NOT EXISTS people(peopleID INTEGER PRIMARY KEY AUTOINCREMENT,name TEXT,phone TEXT)"]; //FMResultSet 结果集,查询出来的数据有可能很多条,所以放在了一个结果集中 FMResultSet *set = [_db executeQuery:@"SELECT * FROM people"]; //next 方法前往下一条记录,如果存在下一条记录返回 YES,不存在返回 NO.存在这条记录的话,把此记录封装成 people 对象,装进数组.(通过 while 循环遍历结果集) while ([set next]) { People *p = [[People alloc]init]; p.name = [set stringForColumn:@"name"]; p.peopleID = [set intForColumn:@"peopleID"]; p.phone = [set stringForColumn:@"phone"]; [_array addObject:p]; [p release]; } [set close]; //关闭数据库 [_db close];//把新添加的人写入数据库 [_db open]; //FMDB中 SQL 语句的占位符(?)只能用 NSString 替代,不能用 int [_db executeUpdate:@"INSERT INTO people(name,phone)VALUES(?,?)",p.name,p.phone]; //SELECT MAX(peopleID) 搜索表中最大的peopleID, FMResultSet *set = [_db executeQuery:@"SELECT MAX(peopleID) FROM people"]; [set next]; int maxID = [set intForColumnIndex:0]; p.peopleID = maxID;//执行删除操作时,要先从数据库中删除 People *p = [_array objectAtIndex:indexPath.row]; [_db open]; [_db executeUpdate:@"DELETE FROM people WHERE peopleID=?",[NSString stringWithFormat:@"%d",p.peopleID]]; [_db close];/*----这两个方法配套使用,是 UIViewController 的方法*/- (BOOL)shouldAutorotate{ return YES;} //设置支持的屏幕方向- (NSUInteger)supportedInterfaceOrientations{ return UIInterfaceOrientationMaskLandscape;}/*----_________________*/获取屏幕的旋转角度 UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;设置标签的旋转(到的)角度 lab.transform = CGAffineTransformMakeRotation( 270 * M_PI/180);第八周通讯是客户端与服务器之间的通信服务器(客户端):1.安装了服务器(客户端)软件的电脑 2.服务器(客户端)软件IP 地址:Internet protocol 网络传输协议的逻辑地址IPv4 地址是由4个 0到255 的数字组成互联网中一台计算机发出的数据通过 IP 地址才能把数据准确的发送到另外一台计算机域名,俗称网址,为了方便记忆和输入,进行通信时,不直接使用 IP 地址,而是使用域名.DNS 服务:域名解析服务,能够把域名解析为 IP 地址MAC地址:Media Access Control 接入互联网计算机的物理地址或网卡地址 通过物理地址识别主机端口号: 是计算机与外界通讯交流的出口。 物理接口,协议端口 192.169.0.1:80 冒号后面的就是端口号在计算机上运行的软件如果需要上网,就必须有一个端口号,用来区分网络返回的数据用于哪个软件。范围0-65535。一些号被特定的使用如:用于网络的80端口,用于FTP服务的21端口。HTML:Hyper Text Mark-up Language 超文本标记语言,用来设计一个网页,任何网页的实质都是 html 标签对.URL:唯一资源标识符.(链接地址) 代表一个资源的位置。可以是网络上的,可以是本地的。http协议: 超文本传输协议http传输 以报文形式传输, 分为请求报文和响应报文请求报文分为请求行,请求头,和请求体。 请求行:请求方式(GET,POST)空格 IP 地址后的url 空格 http 版本回车 请求头:contentLength = 0 connection = “close”回车回车请求体:请求内容,可以为空也可以传数据telnet localhost 8080GET /MyServer/ HTTP/1.0Host=localhostConnection=close //把接收到服务器返回的data类型的数据 转换成String类型的数据NSString *str = [[NSString alloc] initWithData:_buffer encoding:NSUTF8StringEncoding]; NSLog(@"str %@",str);响应报文1.响应行:HTTP 版本 响应状态码(2XX 正常响应 4XX 异常响应)GET 请求:把请求的参数写在请求的 url 之后,在 url 最后加?然后后面写参数,参数与参数之间用&分割(url?XXX=XXX&XXX=XXX)GET请求参数长度受限,而且不安全.POST 请求:把参数写在请求体中,这种请求方式相对安全.JSON数据[]表示数组{}表示字典[{name:张三,qq:123,sign:我今年5岁了},{name:李四,qq:333,sign:我捡了100块}]OAuth 2.0认证过程1.客户端从新浪微博请求一个认证界面,然后将这个认证界面呈现给用户。2.用户在认证界面填写完账号密码并点确定时,认证界面会把账号密码直接发送给新浪微博(不通过客户端)。3.新浪微博验证用户输入的账号密码,如果输入正确,新浪微博回交给客户端一个 code。4.客户端拿到 code 之后,用 code 去请求 token。token 就是这个用户的通行证。在当前时间的基础上加上一个时间NSDate *date = [[NSDate date] dateByAddingTimeInterval:expires.doubleValue]//dateWithTimeIntervalSinceNow//于现在相隔多少秒的一个时间//正数,多少秒后,负数,多少面前NSDate* date = [NSDate dateWithTimeIntervalSinceNow:[expires intValue]];比较两个时间的大小 NSOrderedDescending降序 说明前者比后者大[date compare:nowDate] == NSOrderedDescending//实现断点下载,首先要获取已经下载的文件的大小。 NSDictionary *att = [[NSFileManager defaultManager] attributesOfItemAtPath:[self filePath] error:nil]; unsigned long long size = [att fileSize];//*当继续下载时,应该告诉服务器,客户端已经下载好了一部分数据,只需要把下载好的数据后面的数据传输过来即可。//*请求头中Range代表下载的范围,从总数据的第几个字节之后开始下载就写成xx-[request addValue:[NSString stringWithFormat:@"bytes=%qu-",size] forHTTPHeaderField:@"Range"];上传文件或图片时,要用到固定的HeaderField [request addValue:@"multipart/form-data" forHTTPHeaderField:@"Content-Type"];//UIImagePNGRepresentation把一个UIImage转成png格式的 NSData。//UIImageJPEGRepresentation把一个UIImage转成jpg格式的 NSData。//0.7是压缩比例,把图片压缩后转成DATANSData *data = UIImageJPEGRepresentation(_imageView.image, 0.7);//把需要上传的数据放入请求体[request setHTTPBody:data];unsigned long long size = [att fileSize]; //告诉服务器上传的文件的大小 [request addValue:[NSString stringWithFormat:@"%qu",size] forHTTPHeaderField:@"Content-Length"]; //生成一个文件的输入流 NSInputStream *stream = [NSInputStream inputStreamWithFileAtPath:path]; //当上传大文件时,为了节省内存,不直接把所有数据都读入内存,而是使用数据流一点一点读取。 //设置请求体的输入流 [request setHTTPBodyStream:stream];第十周//自定义类型 在#import 下,@interface 上 定义以后,在本类中后者就可以代替前者使用typedef int myInt;typedef NSString String;//定义一个block类型typedef int (^myBlock)(int a,int b) ;//block不能使用局部变量,可以使用全局变量,如果block中需要使用局部变量,需要在定义的变量前+ __block//局部变量在block中只读。而且,是一次性赋值(把c的值copy到block中,以后c的值改变,并不会影响到block中的c)//全局变量,__block变量,static变量,在block中引用的话,引用的是变量,而不是变量的值,也就是说,引用之后,变量发生改变的话,block中的值也会发生变化//如果属于某个对象的block当中又使用到了这个对象,就会造成循环引用(对象和block的循环引用),导致最后对象释放不掉,所以,当属于某个对象的block使用这个对象时,应该再定义一个__block的指针指向这个对象,在block中使用__block指针。//如果是ARC,用__weak__block SecondVC *safeSelf = self; self.block = ^{ safeSelf.view.backgroundColor = [UIColor redColor]; };//全局的block(在栈内存中的block)需要对block块内局部变量的引用计数+1(块内全局变量不变)。//某些情况下,不能使block的对象引用计数增加,那么在这个指针前+__block。__block NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"123", nil];//局部的 block 块内对象的引用计数均不变 self.block = ^{ [array addObject:@"222"]; [_array addObject:@"222"]; };//GCD中使用线程队列实现多线程。 //我们可以在一个线程队列中加入一段代码,线程队列就会执行这个段代码。 //dispatch_queue_t 线程队列, //dispatch_queue_create函数,创建一个新的线程队列,其中第一个参数是线程队列的标签(名字)。第二个参数是队列的类型。 //线程队列分为串行队列和并行队列,如果要创建串行队列,第二个参数写DISPATCH_QUEUE_SERIAL,并行队列写DISPATCH_QUEUE_CONCURRENT。 dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_SERIAL); //虽然并行队列也可以创建,但是一般不去创建并行队列,而是找到系统自带的global并行队列使用。 dispatch_queue_t tQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); //dispatch_sync在线程队列中同步执行一个block//同步执行,相当于waitUntilDone,当前代码先停止,直到分线程的block中的代码执行完毕,当前线程才继续往下执行。//异步执行,开启一个分线程后,当前线程不去等待分线程执行完毕,直接往下执行。dispatch_async(concurrentQueue, ^{ NSLog(@"%@",[NSThread currentThread]); [NSThread sleepForTimeInterval:1];});//dispatch_get_main_queue获得主线程队列,主线程只有一个,所以,主线程是串行队列。 dispatch_queue_t mainQueue = dispatch_get_main_queue(); //把刷新UI的代码放在主线程中执行 dispatch_async(mainQueue, ^{ _imageView.image = image; }); });//dispatch_suspend暂停一个线程队列,暂停之后,正在执行的block还会继续执行,这个block执行完之后,后面的block不会继续执行。 dispatch_suspend(_queue);//dispatch_resume继续一个线程队列,继续之后,队列中的block会继续执行。 dispatch_resume(_queue);//创建出来的线程队列用完之后需要release dispatch_release(queue);//dispatch_semaphore_t 线程信号量,dispatch_semaphore_create创建一个信号量,参数为初始信号量。 dispatch_semaphore_t sem = dispatch_semaphore_create(0);//dispatch_semaphore_signal给某个信号量发送一个信号,作用是使这个信号量+1. dispatch_semaphore_signal(sem); //dispatch_semaphore_wait等待信号量(等待信号量大于0),当信号量等于0时,当前线程会在这一行代码等待,直到sem信号的信号量大于0,当信号量大于0时,当前线程会对信号量-1,然后继续往下执行。 dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);//设置一个信号量,信号量的值就是最大并发数。 dispatch_semaphore_t sema = dispatch_semaphore_create(10);-使用semaphore设置并发队列的最大并发数- //创建一个并发队列 dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT); dispatch_async(queue, ^{ //每当向队列中加入一个block时,先让线程等待,信号量足够时(大于0),线程执行,否则线程等待。 dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); //code //code //code //code //当block执行完毕时,给信号量发送信号,使信号量+1 dispatch_semaphore_signal(sema); });//dispatch_after延迟执行一个block dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"3秒之前点击了button"); });//NSOperationQueue,操作队列。 NSOperationQueue *queue = [[NSOperationQueue alloc] init]; //maxConcurrentOperationCount设置队列的最大并发数,当把最大并发数设置为1时,这个队列就相当于串行队列。 queue.maxConcurrentOperationCount = 10;//addOperationWithBlock把一个block封装成NSOperation,然后把这个operation放进操作队列中执行。 [queue addOperationWithBlock:^{ NSLog(@"%d",[NSThread isMainThread]); //currentQueue得到当前线程所在的操作队列。 NSOperationQueue *qu = [NSOperationQueue currentQueue]; //mainQueue得到主线程操作队列 NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; }];第十一周 //setApplicationIconBadgeNumber设置应用程序icon的角标 //申请推送权限,IOS8开始,需要申请推送权限,才能显示icon角标 [[UIApplication sharedApplication] registerUserNotificationSettings:nil]; [[UIApplication sharedApplication] setApplicationIconBadgeNumber:3]; //badgeValue属性,角标。 self.navigationController.tabBarItem.badgeValue = nil; frame是相对于父类的坐标系,bounds 是相对于自己的坐标系字符串的逆转NSString *str = @"a,b,c,d"; NSMutableString *newStr = [[NSMutableString alloc]initWithCapacity:0]; @autoreleasepool { for (int i = str.length-1; i>=0; i--) { [newStr appendString:[NSString stringWithFormat:@"%c",[str characterAtIndex:i]]]; } } NSLog(@"%@",newStr);//在图片边缘添加一个像素的透明区域,去图片锯齿 CGRect imageRrect = CGRectMake(0, 0,_imageView.frame.size.width, _imageView.frame.size.height); UIGraphicsBeginImageContext(imageRrect.size); [_imageView.image drawInRect:CGRectMake(1,1,_imageView.frame.size.width-2,_imageView.frame.size.height-2)]; _imageView.image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();2015.1.13手势 touch时间 核心动画/*iOS学习笔记之QuartzCore框架 iOS编程给用户视觉反馈其实都是通过QuartzCore框架来进行的,说白了,所有用户最终看到的显示界面都是图层合成的结果,而图层即是QuartzCore中的CALayer。 通常我们所说的视图即UIView,并不是直接显示在屏幕上,而是在创建视图对象的时候视图对象会自动创建一个层,而视图对象把要显示的东西绘制在层上,待到需要显示时硬件将所有的层拷贝,然后按Z轴的高低合成最终的显示结果。 CALayer本质上是一块包含一幅位图的缓冲区,由视图创建的层为隐式层,而手动创建的层称为显示层。 如果要在iOS上能够有良好的用户体验,动画的过渡效果是必不可少的,而所有的动画效果都是通过CAAnimation类的子类(CAAnimation是抽象类)来完成的。CAAnimation类的子类包括了 CAAnimationGroup,CAPropertyAnimation,CATransition,而CAPropertyAniamtion(同为抽象类)也衍生了CABasicAnimation和CAKeyframeAnimation。用UIView的animation实现的动画本质上也是通过CALayer来实现的,iOS系统中CALayer的很多属性都是隐含有动画效果的,如果不想要隐式动画或者想要显示动画效果,都可以通过CATransaction来设置是否显示动画效果。同时,在CATransaction内可同时修改多个属性,然后再一并同时渲染,另外CATransaction还是可嵌套的。 CABasicAnimation是一个最多只能有两个关键帧的动画,而 CAKeyframeAnimation除了可含有多个关键帧,而且还可以修改每个关键帧的速度。 CATransition能够为层提供移出以及移入屏幕的效果。苹果提供的所有动画类型在http://iphonedevwiki.net/index.php/CATransition这里有介绍,但是api只开放了其中的四种,当然你可以调用未公开的api,但是假如苹果以后出于安全还是什么原因调整接口的话,就不一定能用了,所以最好还是不要调用私有api,况且还有许多可以替代的方法,例如 @"flip”,@"pageCurl”这些type是属于未公开的,//成为第一响应者 [self becomeFirstResponder];