来源:http://blog.csdn.net/depthlove2011/article/details/18502909
MVC模式:(model+view+controller):是一种帮你把代码功能和显示划分出来的设计模式; model:较为底层的数据引擎,负责管理实体中所继承的数据; view:和用户交互界面; controller:连接二者的桥梁; cocoa frameworks 有两个框架: foundation foundation 是cocoa中最基本的一些类;再mac应用程序中负责对象管理,内存管理,容器等相关数据; uikit: uikit:为程序提供可视化的底层构架,包括窗口,视图,控件类和管理这些对象的控制器。这一层中的其它框架允许你访问用户联系人和图片信息,以及设备上的加速器和其它硬件特征; code4app.com UI(User Interface)编程 9.3第八周,周一 创建ios项目 1.打开iOS中的application; 2.UIViewController:视图控件,通过点击,触摸来控制程序 3.UIView :视图; 4.在项目中创建一个文件。在 iOS的cocoa touch创建一个 ulviewcontrollersubclass类然后在AppDelegate.m中找到application函数,在 self.window.backgroundColor = [UIColor whiteColor];后写如下代码 RootViewCotroller *rvc=[[RootViewCotroller alloc]initWithNibName:@"RootViewCotroller" bundle:nil]; self.window.rootViewController=rvc; [rvc release]; 代码含义:创建根控件,并把新创建的根控件赋值给窗口的根控件;注意释放; 5.label控件的创建和属性: 可以用视图界面创建;然后修改属性; 6.代码实现label 1.IBOutlet :是个宏。控件和根界面控件内容建立联系 2.atomic:原子操作;线成保护;就是在几个线程中调用同一段内容时导致所用内容混乱,进行枷锁机制 nonatomic:不加锁机制;能提高效率; 把控件打包,并和界面添加的控件建立联系: 3.在RootViewCotroller.m文件中在viewDidLoad(加载函数)函数中设置lable的属性; 4.iPhone 横向320 竖向480 横条占20; 所以一般是320*460 创建给label并在屏幕上定位 CGRect rect={0,100,100,40}; //创建定位结构体; 坐标原点是左上角;四个参数分别是距左框的距离;距上框的距离;label控件的宽度,高度; UILabel *label=[[UILabel alloc] initWithFrame:rect]; UILabel *label=[[UILabel alloc] 可一直接生成UIrect; initWithFrame:CGRectMake(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat width#>, <#CGFloat height#>)] 5.UIView * 指所有可视控件; 6.设置背景色 [label1 setBackgroundColor:[UIColor blueColor]]; 7.设置label的字体; [label2 setFont:[UIFont systemFontOfSize:20]]; label1.font=[UIFont italicSystemFontOfSize:30]; 8.设置字体的颜色 label2.textColor=[UIColor redColor]; 9.设置字体的对齐方式; label1.textAlignment=UITextAlignmentLeft; 10.自动调整字体 label1.adjustsFontSizeToFitWidth=YES; 当文字数量多时可以自动调整字体大小 如果不设置就会变成省略; 字体省略方式: label2.lineBreakMode=UILineBreakModeHeadTruncation; 这个是截去头,还有尾截,和中间截去; label2.lineBreakMode=UILineBreakModeClip; 表示在已有控件写多少是多少,不写省略符 label1.lineBreakMode=UILineBreakModeCharacterWrap; 字符换行,指只要需要换行就换行不考虑单词的整体性; label1.lineBreakMode=UILineBreakModeWordWrap; 以一个整个单词换行,不允许把整个单词分开写到不同的行;保持单词完整性; 设置自动调整的最小限制 label1.minimumFontSize=10; 11.设置行数: label1.numberOfLines=3; 注:如果行高不够的话它不能显示完整; 字体省略方式 12.设置高亮颜色 label1.highlightedTextColor=[UIColor whiteColor]; 设置高亮的状态时的颜色; label1.highlighted=YES; 把label设置为高亮状态; 13.设置阴影色 label1.shadowColor=[UIColor blackColor]; 设置阴影颜色; label1.shadowOffset=CGSizeMake(-2,-2 );//只有长和宽 没有 起始位置 设置阴影位置;是相对字体的位置; 14.IOPhone的图标默认大小时57*57; 9.4周二 1. IBAction 时void型的,为了连接某个触发; 2.button创建 button1=[UIButton buttonWithType:UIButtonTypeRoundedRect] 注:这样创建的button不是alloc出来的不用释放; 后面参数时button 的外观; 3.button设置位置: button1.frame=CGRectMake(120, 280, 80, 40); 4.button 设置title [button1 setTitle:@"click here" forState:UIControlStateNormal]; 注:由于button继承view control所以它可以设置状态; 状态的作用? 答:可以在不同状态下展示不同的button 特点; 1.高亮状态下设置 [button1 setTitle:@"click ready" forState:UIControlStateHighlighted]; 2.禁用状态设置 [button1 setTitle:@"forbid using" forState:UIControlStateDisabled]; button1.enabled=NO; button设置成不可用,但是还可以更改button 的属性 5. 设置button的title的属性; button1.titleLabel.font=[UIFont systemFontOfSize:20]; 注:button是复合了label所以可以调用title label,设置它的 文本属性就是设置button的文本属性; 6设置 颜色 [button1 setTitleColor:[UIColor yellowColor] forState:UIControlStateNormal]; 7.给button添加事件 [button1 addTarget:self action:@selector(onclick) forControlEvents:UIControlEventTouchUpInside]; addTarget:指触发的对象; action:触发的事件; forControlEvets:是表示如何点击按钮触发; 8.局部声明button,如何使用button使其执行动作; 在事件函数头传递button对象;谁调用它就传递谁的地址; -(void)onclick:(UIButton *)seder [button addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchUpInside]; 注意:传递调用函数带参数有冒号; 9.添加图片 UIImage *image=[UIImage imageNamed:@"03.gif"]; [button setBackgroundImage:image forState:UIControlStateNormal]; [button setBackgroundImage:image1 forState:UIControlStateHighlighted]; 10.得到图片大小 CGSize size=image.size; NSLog(@"%f %f",size.width,size.height); 11.让button一直处于选择状态; button.selected=YES; button会一直处于一个状态而不改变? 到底什么意思 12. 判断button状态执行操作; if(button.state==UIControlStateNormal){ } 13.移出事件 [sender removeTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchDragOutside]; 14.点击滑动的妙用;可以在作程序时加入实现触屏效果; [button addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchDragInside]; [button addTarget:self action:@selector(onclick:) forControlEvents:UIControlEventTouchDragOutside]; 9.6周四 UIView (视图) 1.什么是uiview 在应用程序中看的见摸的着的是视图。相当于java中容器; viewController相当于底板; 2.创建视图 UIView *view=[[UIView alloc] initWithFrame:CGRectMake(20, 20, 280, 420)]; 3.将视图添加到父视图 [self.view addSubview:view]; 注意:子视图是父视图的子类,后添加的视图在最上曾; 4.在视图view中添加label(label 是view的子类) [view addSubview:label]; 注:由于ui中的控件都是视图,所以可以在任意视图加载其他视图; 把一些视图装到另一个视图是为了保证视图的整体性; 注:在button上添加label点击label就是点击button label相当于透明;而在上添button就是点谁谁响应; 5. CGRectframe :坐标 CGRectbounds:边界 button.bounds=CGRectMake(0, 0, 50, 50); CGPointcenter:中点 该是图的中点在父视图的相对坐标; button.center=CGPointMake(160, 230); 指视图的中心位置在父视图的相对位置 得到视图的终点坐标: button.center.x; button.center.y; 6.视图层次 视图子类是个数组; 视图先添加的在下,后添加在上; 交换视图位置: [button1 exchangeSubviewAtIndex:0 withSubviewAtIndex:1]; 1.遍历视图 for (UILabel * l in button1.subviews) { l.text=[NSString stringWithFormat:@"%d",i++]; } 2.插入视图 [button1 insertSubview:label3 atIndex:1]; 将视图label3插入到视图button1的第二位; [button1 insertSubview:label2 aboveSubview:label1]; 将视图label2插到label1上; [button1 insertSubview:label1 belowSubview:label3]; 3.将视图从父类视图中移出; [label2 removeFromSuperview]; 4.[button1 delete:label2]; 5.将视图放到最上层 ; [button1 bringSubviewToFront:label1]; 注:写代码时把子视图写到一块,父视图写到一块 6.把视图放到最上下层 [button1 sendSubviewToBack:label1]; 7.判断某个视图是某个视图的子视图 返回类型是bool类型; [label1 isDescendantOfView:button1]; 7.tag 视图的标志; 可以标志视图。是set 和get函数,设置和取得可以用“.”操作 button1.tag=1; 8.label1.superview 表示label1的父视图; 9. 隐藏视图 :label1.hidden=YES; 默认为no。 应用:可以让视图重叠换灯片放映,或动画;如果父视图隐藏,子视图也随之消失 10.视图可能会超出父视图的范围;这时可以更改父视图边界属性裁减出边界 的子视图 button1.clipsToBounds=YES; UIImageView 1.初始化: UIImageView *imageview=[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"2.jpg"]]; imageview.frame=CGRectMake(20, 20, 140, 220); imageview.contentMode=UIViewContentModeScaleAspectFit; 让添加的图片按比例填充; 3.imageview和label都不能触发事件 但是可以给他们添加事件 //点击事件 搞清楚是单击还是双击 来处理事件 //声明点击手势 初始化点击手势识别器 当单击判断失败 在触发单击;先判断,不知道是单击还是双击 UITapGestureRecognizer *tgr=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onclick)];//来添加事件 tgr.numberOfTapsRequired=1;//区分单击还是双击 tgr.numberOfTapsRequired=2; [tag addTarget:self action :@selecter(press:)];//事件 //创建敲击事件的接收器; [imageview addGestureRecognizer:tgr];//这个视图来响应,把手势加到视图上面 4. imageview.UserInteractionEnabled=YES; //是否能和用户交互; 5.三中图片填充方式 imageview.contentMode=UIViewContentModeScaleAspectFit; imageview.contentMode=UIViewContentModeScaleAspectFill; //按比例添满会超出边界。所以如果超出可以裁减 imageview.clipsToBounds=YES; imageview.contentMode=UIViewContentModeScaleToFill; //添满 6.创建视图还可以在appDelegate.m中的application中声明实现 7. 子视图按某中形式随父视图扩大或缩小;不同的扩大缩小方式特点可以或 labelsub.autoresizingMask=UIViewAutoresizingFlexibleWidth; labelsub.autoresizingMask=UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 控制视图按比例的开关; labelsub.autoresizesSubviews=NO; MVC:设计思想: model:内存数据 view :可视控件;controller:控制代码; 单例:从头到尾使用的类 RootController *rvc=[[RootController alloc]initWithNibName:@"RootController" bundle:nil];//有xib文件时创建连接文件,以后最好没有xib文件,xib文件降低速度 以后初始化要不创建xib文件初始化方法是: RootController *rvc=[[RootController alloc]init]; kvo/kvc:? notification:? 窗口: iphono内存占用量不超过20Mb 全屏做法 1.记下此时的控件fram 2.修改控件的大小,使其全屏 3.把改图像拉到顶层; 4.修改tag 字体新设置: label.font=[UIFont fontWithName:@"宋体" size:30]; timer 1.创建定时器,一但创建就开始运行; NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(changLabel) userInfo:nil repeats:YES]; 2,定时器停止;一旦停止就释放,相当于release; [timer invalidate]; 3,打开定时器 [timer fire] 4.动画效果 ' UITextField:对话框 同样是个view 1.创建 UITextField *field=[[UITextField alloc] initWithFrame:CGRectMake(40, 20, 250, 60)]; 2.设置边框 UITextField *field=[[UITextField alloc] initWithFrame:CGRectMake(40, 20, 250, 60)]; 3.在文本框后面设置清除键 field.clearButtonMode=UITextFieldViewModeAlways; 4.设置初始文本 field.placeholder=@"username"; 5。设置文本变为隐藏; field.secureTextEntry=YES; 6.设置textfield的自定义函数 首先在.h文件中提交协议 <UITextFieldDelegate> 这样就可以自定义textfield 函数;注:自定义函数如果是返回bool类型的函数说明这个函数是一个监听函数;自定义都是进行某些动作时自动调用; 7.-(void)textFieldDidBeginEditing:(UITextField *)textField 当文本框进入编辑模式时自动调用 8.退出编辑模式时调用函数; -(void)textFieldDidEndEditing:(UITextField *)textField { ( (UILabel *)[self.view.subviews objectAtIndex:0]).text=textField.text; } 9.点击键盘上return后调用的函数 -(BOOL)textFieldShouldReturn:(UITextField *)textField 10.关闭键盘函数; [textField resignFirstResponder]; return NO; 11.限定输入字符的长度函数 -(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { //textfield表示谁调用该函数, if (string.length>0) //string 表示当前输入的字符; return textField.text.length<10; //而textField.text的值是还没有加入刚输入的string return YES; } 9.10 第九周 多控制器操作: 一.多控制器间的切换; 思想:1.在每个视图控制器界面添加按钮点击触发事件创建新的视图控制器;然后把当前控制器交给新建的控制器; 2.在新建的视图控制器中等使用完该控制器后,把控制器释放;由于创建是在前一个控制器中释放的所以这里释放不是简单的release; 方法:一 1.在父控制器中创建新控制器,并把但前的控制界面交给新控制器 ViewController* vc2=[[ViewController2 alloc] init]; vc2.view.frame=CGRectMake(0,0,320,460); [self.view addSubview:vc2.view]; [self addChildViewController:vc2]; 注:由于这样vc2 是在原控制器上加载所以它会默认流出原视图导航栏,要想让新控制器全部占满屏幕就要更改视图的大小; 2. 然后用完vc2在最后把vc2从原控制器中移出 [self.view removeFromSuperview]; [self removeFromParentViewController]; 注:由于创建vc2时原有的控制器可vc2关联,原有的view和vc2的view关联;所以在清理时得把这两项分别清理; 注:这中添加清理的方法使用高版本;为了程序的适用性通常用第二种方法; 二: 1.在父控制器中创建新控制器;并把当前的控制器设置为vc2,并添加动画效果 ViewController* vc2=[[ViewController2 alloc] init]; [self presentModalViewController:vc2 animated:YES]; //添加新的controller而且带动画效果;animated:是否要动画效果 2 在用完vc2时移出该控制器; [self dismissModalViewControllerAnimated:YES]; //释放当前的controller 动画效果:只要把新的位置改变放到这些代码之间; [UIView beginAnimations:nil context:nil];//动画设置开始; [UIView setAnimationDuration:0.2];//设置动画时间; text.frame=CGRectMake(<#CGFloat x#>, <#CGFloat y#>, <#CGFloat width#>, <#CGFloat height#>)//对象的新状态; [ UIView commitAnimations];//开始动画; 9。11周二 注:系统对象不开辟空间不能打印retaincount自己声明的类的对象不开辟空间可以打印retaincount 导航条UINavigationBar 1.导航条按钮初始化三种方法: 1.普通初始化 UIBarButtonItem *rigthButton=[[[UIBarButtonItem alloc] initWithTitle:@"next" style:UIBarButtonItemStylePlain target:self action:@selector(click:)] autorelease]; 第一个参数是按钮标题;第二个参数是按钮的样式;第三个参数是触发事件调用那个类中的方法第四个参数是触发的事件 2.用图片初始化 UIBarButtonItem *rightButtton= [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"5.png"] style:UIBarButtonItemStylePlain target:self action:@selector(click:)]; 注:这样初始化的按钮有按钮框,图片存在按钮框里要想只显示图片要自定义按钮然后用按钮初始化;如第三种方法; 3.自定义控件初始化 //自定义的透明按钮 上面一般是要加上图片 让后点击图片 UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom]; [button setImage:[UIImage imageNamed:@"5.png"] forState:UIControlStateNormal]; 创建button 按钮,样式设置为普通,也就是没有样式; button.frame=CGRectMake(0, 0, 30, 30); 注:必须设置button 的frame否则不显示 [button addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; 给button添加事件 UIBarButtonItem *rightButton=[[UIBarButtonItem alloc] initWithCustomView:button]; 初始化导航条button 4.运用系统功能按钮初始化uibarbutton UIBarButtonItem *rightButton=[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCamera target:self action:@selector(click:)]; 2.添加副标题//导航栏添加副标题 self.navigationItem.prompt=@"subtile"; 导航条高度是44; 3.把导航条按钮设置成数组;可多加按钮,按钮一多会把别的控件挤偏;但是不能覆盖;如果加的太多只能显示先加入的; self.navigationItem.rightBarButtonItems=[NSArray arrayWithObjects:<#(id), ...#>, nil] 注:UIBarButtonItem 有些属性和unbutton不一样,UIBarButtonItem不能设置 //设置导航栏的颜色 4.设置导航条色调 // tintColor:色调 控制器的导航条 的 色调 self.navigationController.navigationBar.tintColor=[UIColor purpleColor]; 5.颜色色透明度 1.黑色透明度 self.navigationController.navigationBar.barStyle=UIBarStyleBlackTranslucent; 2.其他颜色透明度 self.navigationController.navigationBar.translucent=YES; self.navigationController.navigationBar.alpha=0.8 slider.frame=self.navigationController.navigationBar.bounds;//从边界开始设定大小 重点 6.更改导航条背景 //更改背景图片ios5.0以后的方法 //判断。如过是5.0以上的版本用以下方法; if (__IPHONE_OS_VERSION_MIN_REQUIRED>=__IPHONE_5_0) { [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@""] forBarMetrics:UIBarMetricsDefault]; } 如果是5.0以下的可以创建类别 //通过类别创建图像 @implementation UINavigationBar(Custom) -(void)drawRect:(CGRect)rect{ UIImage *image=[UIImage imageNamed:@""]; [image drawInRect:rect]; } 7.隐藏导航条 [self.navigationController setNavigationBarHidden:YES animated:YES]; 8.直接跳转到某页 1.创建数组把控制页面全部加载进来; NSMutableArray *array=[NSMutableArray arrayWithArray:self.navigationController.viewControllers]; 2.设置跳转到哪页 [self.navigationController popToViewController:[array objectAtIndex:0] animated:YES]; 能够设置的常项 创建一个可变空数组; NSMutableArray *array1=[[NSMutableArray alloc]initWithCapacity:0]; 用数组设置navigationController的ViewControllers //[self.navigationController setViewControllers:array]; self.navigationController.viewControllers=array; 9.在子导航条中去除自带得返回上一级得button self.navigationItem.hidesBackButton=YES; ToolBar工具条 1.创建工具条:为单个viewcontroller添加toolbar UIToolbar *toobar=[[UIToolbar alloc] initWithFrame:CGRectMake(0,372,320, 44)]; 注:一定要注意创建导航条后当前的viewcontroller的坐标原点已经改变是加上导航条后的的高度;导航条的高度是44; toolbar.tintColor=[UIColor purpleColor]; toolbar的颜色设置;和导航条设置一样; toobar.hidden=NO; 注:toolbar的hidden属性默认是yes,所以加toolbar要把hidden设置为no; 2. 在导航条中有toolbar属性;所以要想每页都加toolbar 就可以在这里把导航条的toolbar的hidden属性设置为no; ]; UINavigationController *nv=[[UINavigationController alloc]initWithRootViewController:vc]; nv.toolbarHidden=NO; nv.toolbar.tintColor=[UIColor purpleColor]; [nv setNavigationBarHidden:YES animated:YES]; 3.把按钮写成一个数组然后添加到toolbar [array addObject:button]; //设置viewcontroller的toolbar以数组初始化; //toobar的button不能调整大小; // self.toolbarItems. [self setToolbarItems:array animated:YES]; 4.验证两个coloer属性; tinkcoloer: 9.12 周三 //六个控件 UISlider 滑条控件//滑动条控件 滑条初始化: UISlider *sl=[[UISlider alloc]initWithFrame:CGRectMake(30, 60, 280, 30)]; 1.滑条的高度不用设置因为系统默认 ;但是可以设置背景图改变滑条的高度;具体看滑条的图片设置 创建label用来显示滑动的数值 UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 40)]; view控件的tag属性可以作为区分视图的标志想查找它时可以在另一个函数中写 UILabel *label=(UILabel *)[self.view viewWithTag:100]; label.tag=100; 设置滑条的最大值和最小值; sl.minimumValue=0.0; sl.maximumValue=20.0; 给滑条添加事件,由于滑条的值是可变的所以监听它时用值改变事件监听,以后一般遇到值可以不断改变的view控件要用值改变事件监听; [sl addTarget:self action:@selector(valuechang:) forControlEvents:UIControlEventValueChanged]; // 设置默认滑条位置; sl.value=10.0; 设置大小端图像; sl.maximumValueImage=[UIImage imageNamed:@"5.png"]; 设置滑条轨迹的颜色 sl.minimumTrackTintColor=[UIColor purpleColor]; sl.maximumTrackTintColor=[UIColor redColor]; sl.thumbTintColor=[UIColor greenColor]; //点击按钮分高亮状态和非高亮状态;所以要注意设置那个状态; [sl setThumbImage:[UIImage imageNamed:@"5.png"] forState:UIControlStateNormal]; //设置滑条的最大最小图像;注:1滑点滑动部分变大图像会被拉伸,如果图像到达原大小在压缩不会变化;2.如果滑条设置背景图片就会改变滑条的宽度,而且只能是改变minimumValueImag此时的图片高度就是滑条的高度;原因:因为滑条的大端是开始的占空间大小;显示的滑动进度是在原有基础上添加的所以大端改变整个滑条才会改变 [sl setMinimumTrackImage:[UIImage imageNamed:@"5.png"] forState:UIControlStateNormal]; [sl setMaximumTrackImage:[UIImage imageNamed:@"5.png"] forState:UIControlStateNormal]; 简单的滑条触发事件测试:滑条值的改变显示在label控件上; -(void)valuechang:(UISlider *)sender { UILabel *label=(UILabel *)[self.view viewWithTag:100]; label.text=[NSString stringWithFormat:@"%.0f",sender.value]; } UISwitch:开关控件//创建开关控件 初始化switch对象 UISwitch * _swith=[[UISwitch alloc] initWithFrame:CGRectMake(100, 100, 0, 0)]; 给with添加事件注意 事件控制是UIControlEventValueChanged [_swith addTarget:self action:@selector(sw:) forControlEvents:UIControlEventValueChanged]; 设置with的打开时背景色 _swith.onTintColor=[UIColor blackColor]; 注:不用设置switch的宽高。因为时系统默认;设置没有作用; 给switch添加switch事件:状态改变一次触发一次 -(void)sw:(UISwitch *)swith { if (switch.on==YES) NSLog(@"yes"); else NSLog(@"no"); } UIActivityIndicatorView:加载缓控件 //加载缓冲页面;初始化 UIActivityIndicatorView *aiv=[[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(100, 100, 0, 0)]; 设置当停止时隐藏 aiv.hidesWhenStopped=NO; 设置旋转图标的样式。一共有三种 aiv.activityIndicatorViewStyle=UIActivityIndicatorViewStyleWhiteLarge; 设置缓冲图标的颜色 注:要先设置样式在设置颜色,因为样式是带颜色,能覆盖以前的颜色; aiv.color=[UIColor blueColor]; 缓冲图标开始,停止动画; [aiv startAnimating]; [aiv stopAnimating]; UIProgressView:进度条 初始化进度条 UIProgressView *pgv=[[UIProgressView alloc] initWithFrame:CGRectMake(50, 100, 220, 0)]; 设置进度条的tag属性; pgv.tag=100; pgv.progressViewStyle=UIProgressViewStyleBar; //颜色设置 pgv.progressTintColor=[UIColor purpleColor]; pgv.trackTintColor=[UIColor blackColor]; //进度条图片设置 pgv.progressImage=[UIImage imageNamed:@""]; pgv.trackImage=[UIImage imageNamed:@""]; //用时间控制器模拟时间进度条; [NSTimer scheduledTimerWithTimeInterval:0.2 target:self selector:@selector(refresh:) userInfo:nil repeats:YES]; //用函数对进度条做试验 -(void)refresh:(NSTimer *)timer { UIProgressView *pv=(UIProgressView *)[self.view viewWithTag:100]; [pv setProgress:pv.progress+0.1 animated:YES]; if (pv.progress==1) { NSLog(@"%d",[timer retainCount]); [timer invalidate]; // [timer release]; //注意在ui中运用封装好的函数生成的控件不要给他们release它有他自动释放或需要调用释放函数;所以不必管它 NSLog(@"%d",[timer retainCount]); } UITextView 文本编辑器 文本编辑器和文本框一样有代理函数在.h文件开头需引入; @interface ViewController : UIViewController<UITextViewDelegate> 它的代理函数和文本框的基本相同,不同的有两个 -(void)textViewDidChange:(UITextView *)textView:(UITextView *)textView -(void)textViewDidChangeSelection:(UITextView *)textView 注:在调用代理函数时一定要textview的代理设置为调用函数所在的类; 文本框的一些属性设置: 1.初始化文本框 UITextView *textView=[[UITextView alloc]initWithFrame:CGRectMake(0, 0, 320, 100)]; 2.文本框的颜色,对齐方式,字体设置 textView.textColor=[UIColor grayColor]; textView.textAlignment=UITextAlignmentLeft; textView.font=[UIFont systemFontOfSize:30]; 3。自动纠错关闭; textView.autocorrectionType=NO; 4.大写模式;除此之外还可以设置字母不大写;句首字母大写。单词开头字母大写; textView.autocapitalizationType=UITextAutocapitalizationTypeAllCharacters; 5.键盘模式: textView.keyboardType=UIKeyboardTypePhonePad;//打电话模式 textView.returnKeyType=UIReturnKeyGo;返回模式变为go //根据输入框需要输入的内容不同要设置键盘的样式 UIStepper 计步器//创建一个计步器 1.初始化 //ValueChanged 点击是要用这种模式 UIStepper *stepper=[[UIStepper alloc]initWithFrame:CGRectMake(100, 200, 100, 40)]; 2.给stepper添加触发事件,还是注意 forControlEvents:UIControlEventValueChanged的设置 [stepper addTarget:self action:@selector(stepper:) forControlEvents:UIControlEventValueChanged]; 3.设置stepper的最大最小值 stepper.minimumValue=0; stepper.maximumValue=50; 4. //常按可以自动加默认是yes 长按就一直进行 stepper.autorepeat=YES;//autorepeat是否连续的执行这一操作或者响应 //最小和最大间循环; stepper.wraps=YES; //设置每次增长值 stepper.stepValue=2; //设置按键时是否显示每次加的值;如果设为no常按键会加到走好几个步长的值 stepper.continuous=NO;//continue单位时间内是否响应 UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(50, 50, 100, 50)]; label.font=[UIFont systemFontOfSize:30]; [self.view addSubview:label]; label.tag=100; -(void)stepper:(UIStepper *)stepper { UILabel *label=(UILabel *)[self.view viewWithTag:100]; label.text=[NSString stringWithFormat:@"%f",stepper.value]; } UISegmentedControl 分段控制器;//创建分段控制器 1.分段控制器初始化 UISegmentedControl *sc=[[UISegmentedControl alloc]initWithItems:[NSArray arrayWithObjects:@"a",@"b",@"c",[UIImage imageNamed:@"5.png"], nil]]; 2 分段控制器设置frame sc.frame=CGRectMake(100, 100, 150, 40); 3. 为分段控制器添加监听事件; [sc addTarget:self action:@selector(sc:) forControlEvents:UIControlEventTouchUpInside]; //注这个触发事件监听是ValueChanged,为了监听按钮 4。控制类型控制类型一共有四种; sc.segmentedControlStyle=UISegmentedControlStyleBordered; 5。按钮自动弹起开启;默认是no; sc.momentary=YES; 6。添加新按钮;可以是文字,或图像; [sc insertSegmentWithTitle:@"e" atIndex:3 animated:YES]; [sc insertSegmentWithImage:<#(UIImage *)#> atIndex:<#(NSUInteger)#> animated:<#(BOOL)#>] 7.在段控制器中区分点击那个按钮的个属性 //一共有多少个按钮; int i=sc.numberOfSegments; //当前点击的按钮位置; int j=sc.selectedSegmentIndex; //移出当前点击的段; [sc removeSegmentAtIndex:j animated:YES]; //移出所有的段; [sc removeAllSegments]; UIGesture 手势事件 1.移动手势 1.创建移动手势的对象: UIPanGestureRecognizer *pan=[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)]; 2.把此对象添加到操作的对象中; [imagview addGestureRecognizer:pan]; 3.实现移动对象的方法 -(void)pan:(UIPanGestureRecognizer *)pan { CGPoint point=[pan translationInView:self.view]; //这个函数是得到触点在屏幕上与开始触摸点的位移值 imagview.center=CGPointMake(imagview.center.x+point.x, imagview.center.y+point.y); //让图像的中心位置变化;中心变化图像位置就移动了 ,但是注意位移时如果不清空translation就会多移动一倍;所以每次要让pan的位置零; [pan setTranslation:CGPointMake(0, 0) inView:self.view]; } 2.扩大缩小手势 1.创建扩大缩小手势的对象 在创建时就带了要触发的事件 手势器 UIPinchGestureRecognizer *pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)]; 2.记录下开始图像的大小,在扩大缩小函数时使用;原因是扩大尺寸是在图像的现有大小上乘,而图像的尺寸是变化的所以会使图像扩大缩小的太过火;所以纪录原图像大小一直在这个基础上扩大 size=CGSizeMake(imagview.bounds.size.width,imagview.bounds.size.height ); 3.图像添加扩大缩小手势; [imagview addGestureRecognizer:pinch]; 4.图像扩大缩小手势触发的事件; -(void)pinch:(UIPinchGestureRecognizer *)pinch { 改变图像的大小;pinch.scale是触摸点的相对于原有位置的位移量的倍数。 imagview.bounds=CGRectMake(0, 0,size.width*pinch.scale, size.height*pinch.scale); 为了防止每次扩大缩小都要从原图开始,所以操作结束释放触点一次就要把当前的尺寸记下,下次变化在这个基础上改变; if (pinch.state==UIGestureRecognizerStateEnded) { size=CGSizeMake(imagview.bounds.size.width, imagview.bounds.size.height); } gesture.scale=1.0f;//这个很重要 3.旋转手势 //电话在手机里面优先级是最高的 1.旋转角度对象的初始化 UIRotationGestureRecognizer *rotation=[[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)]; 2.给旋转图像添加旋转对象 [imagview addGestureRecognizer:rotation]; 3.旋转时触发的函数 -(void)rotation:(UIRotationGestureRecognizer *)rotation { 让图像旋转某个角度,这个交度使相对原图旋转的角度。所以必须有个判断语句,如果释放一次触点就要把当前位置记下,否则图像还会回到原来状态; imagview.transform=CGAffineTransformMakeRotation(f+rotation.rotation); if (rotation.state==UIGestureRecognizerStateEnded) { f=f+rotation.rotation; } } 4.tap的一些属性 可以给image添加tap事件 tap.numberOfTapsRequired=2;//点击几次触发事件,点击次数必须是连续点击 tap.numberOfTouchesRequired=2;//设置触摸点数 只有两个触点存在时点击才能触发事件 5.触摸时自动调用的触摸函数一共有四个 触点事件调用时UITouch对象产生后自动调用的属性;由于单击的话只有一共对象;所以不论有几个touch对象都时指当前鼠标触点?那为什么还要创建触点对象呢?而anyobject之外还能做什么 1. 触摸开始触发的事件 //开始触屏的时候touchesBegan -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"began"); 建立触摸对象 触摸对象是任意触点;但是事实是当前鼠标点击的点;但是怎么得到另一个点的坐标? UITouch *touch=[touches anyObject];//anyObject 任何触摸的东西都储存在里面 if(touch.tapCount==1) { NSLog(@"这是一个单击事件"); } else if(touch.tapCount==2) { NSLog(@"这是一个双击事件"); } CGPoint point=[touch locationInView:self.view]; NSLog(@"%f %f",point.x,point.y); // 可以调用touch开始点和touch结束点做加减得到移动大小, 但是这样做很麻烦,ui有封装好的方法 UIPanGestureRecognizer // touch只调用第一触电大小,怎么得到第二个点?} //手指离开屏幕的时候 2.触摸事件结束触发事件 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"end"); } 3.cancell实在移动时突然被其他进程打断时调用。比如突来电话 -(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event { NSLog(@"cancel"); } 4.触点移动时触发的事件; //手指移动发生的事件 -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch=[touches anyObject]; CGPoint point=[touch locationInView:self.view]; UIImageView * imageView=(UIImage *)[self.view viewWithTag:101]; CGRect NSLog(@"move"); } [performSelector:@selector(single Tag)withObject:nil afterDelay:delaytime]//实现函数的调用,延时调用,相当于多线程 9.13周四 1.各个控制器间的关系: window 的rootviewcontroller可以是uinavigationcontroller ,uitabbarcontroller ,uiviewcontroller uinavigationconroller 上可以添加uiviewcontroller uitabbarcontroller上可以添加uiviewcontrolller 也可以添加uinavigationcontroller 到此基本上控制器的关系弄清了; 1.UITabBarController :标签控制器,分栏控制器 当uitabbarcontroller含的uitabbaritem很多时,编译器会自动隐藏以省略号表示,点击省略号就可以查看不显示的item 1.初始化: UITabBarController *tc=[[UITabBarController alloc]init]; 2.创建视图控制器然后创建 UITabBarItem并把它赋给视图控制器的 tabBarItem ViewController *vc=[[[ViewController alloc]init]autorelease]; UITabBarItem *item=[[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemSearch tag:0]; 注:可以自定义item 也可以用系统中定义好的; vc.tabBarItem=item; 3.创建导航条;用于放人UITabBarController 由此可知uitabbarcontronller和uinavigationcontroller的包含关系; UINavigationController *nc=[[UINavigationController alloc]initWithRootViewController:vc]; 4.添加导航控件和视图控件; tc.viewControllers= [NSArray arrayWithObjects:nc,vc1,vc2, nil]; 5.让根控制器为标签控制器 self.window.rootViewController=tc; 2.解决不显示第二个以后的标签问题 1.原因:如果把每个控制器的标签生成写在viewdidload里面由于为了节省内存开始只会加载一个控制器。所以只能显示第一个标签; ViewController1 *vc1=[[[ViewController1 alloc]init]autorelease]; //注如不使用vc1显示是没有其图,因为还不加载它的程序 vc1.view.backgroundColor=[UIColor blueColor]; 2.解决方法:1.init函数中生成控制器标签生成代码;在创建控制器时就会执行; 2. 在appdelegate中生成控制器的标签 3.在appdelegate 中调用控制器的函数 3.本地存储: NSUserDefaults:一旦运行数据就会被存储下来,每次运行程序以前的纪录下来的数据仍然有; //只能保存NSString NSNumber NSData,NSDictionary; NSArray;这五种类型;(其他的是需要强转的 类似于 图片的) //保存到本地,一旦保存,再运行还有数据,所以可以达到数据在不通页面间的传递 NSUserDefaults *userDefault=[NSUserDefaults standardUserDefaults]; //为本地存储添加数据;类似于字典的用法 [userDefault setObject:@"adba" forKey:@"key"]; //同步操作,保存到本地; [userDefault synchronize]; 同步了才可以保存到本地的 //获取以前存储的数据; NSString * str=[userDefault objectForKey:@"key"];//根据关键字取出对应的用户默认数据 NSLog(@"%@",str); //实现UITabBarControllerDelegate代理的方法 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { NSLog(@"You selected: %d",tabBarController.selectedIndex); //只是一个单例 NSUserDefaults *ud=[NSUserDefaults standardUserDefaults];//用来存储数据的数据库 创建一个指针来存储和取出数据 [ud setInteger:tabBarController.selectedIndex forKey:@"LAST_PAGE"]; [ud synchronize];//将新添加的数据存盘 } //下面4个方法 不是属于类的方法 是系统本来已经提供的方法 只跟视图控制器的出现和消失有关系的 //视图将要出现的时候 - (void)viewWillAppear:(BOOL)animated; // Called when the view is about to made visible. Default does nothing //视图已经出现的时候 - (void)viewDidAppear:(BOOL)animated; // Called when the view has been fully transitioned onto the screen. Default does nothing //视图将要消失的时候 - (void)viewWillDisappear:(BOOL)animated; // Called when the view is dismissed, covered or otherwise hidden. Default does nothing //视图已经消失的时候 - (void)viewDidDisappear:(BOOL)animated; // Called after the view was dismissed, covered or otherwise hidden. Default does nothing 4.数据字典:NSDictionary:用于存储数据可以和数组联合起来用; 1.字典的初始化方法 1.直接用数值初始化: NSDictionary *dic1=[[NSDictionary alloc]initWithObjects:[NSArray arrayWithObjects:@"",@"", nil] forKeys:[NSArray arrayWithObjects:@"",@"", nil]] ; 2.用数组初始化 NSArray *array=[[NSArray alloc]initWithObjects:@"23",@"100",@"zhang" ,nil]; NSArray *array2=[[NSArray alloc] initWithObjects:@"年龄",@"体重",@"姓名", nil]; NSDictionary *dic1=[[NSDictionary alloc]initWithObjects:array forKeys:array2]; 3.用其他字典初始化 NSDictionary *dic=[[NSDictionary alloc]initWithDictionary:dic1]; 4.用网络URL初始化 NSDictionary *dic5=[NSDictionary alloc]initWithContentsOfURL:<#(NSURL *)#> 2.通过key来找到对应的值; NSLog(@"%@",[dic objectForKey:@"key"]); 3.创建动态字典 用法和普通字典一样; NSMutableDictionary *dic3=[NSMutableDictionary dictionaryWithCapacity:0]; 4.为动态字典添加内容; [dic2 setObject:@"180" forKey:@"身高"]; [dic2 setObject:@"56" forKey:@"weight"]; [dic2 setObject:@"13" forKey:@"age"]; NSNumber 数值对象 1.初始化数值对象 用一个基础数据类型初始化,如整形,浮点,字符都可以; NSNumber *num=[NSNumber numberWithInt:vc.tabBarItem.tag ]; 2.把数值对象添加到数组中; [array addObject:num]; 3.把nsstring类型转换成值;和把数值类型转换成整形 int i=1; NSString *str=[NSString stringWithFormat:@"%d",i]; int a=[str intValue];//其他数值形式的也可以类似转换 如float b=[str floatValue]; UITabBarController的代理函数; uitabbarcontroller 中当item很多时会有省略;还可以调整uitabbaritem的排放顺序调整在主页显示的页面;这时会需要tabbarcontroller 的代理类 1.当某个viewcontroller被选择时触发的事件; 应用:每当页面显示时有些提示信息…….. -(void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { NSLog(@"didSelectViewController"); // NSLog(@"%d",tabBarController.tabBarItem.tag); NSLog(@"%d",viewController.tabBarItem.tag); } 2.在某个viewcontroller选择时触发的事件 -(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController { NSLog(@"shouldSelectViewController:"); NSLog(@"%d",viewController.tabBarItem.tag); return YES; } 3 将要结束用户自定义item时;既点击导航栏中的done时调用用法:可以提示用户确实要这样更改吗。 -(void)tabBarController:(UITabBarController *)tabBarController willEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed { NSLog(@"willEndCustomizingViewControllers"); //NSLog(@"%d",viewControllers) NSLog(@"%d",changed); } 4.将开始进行用户自定义item时调用;既点击了导航栏中的edit时调用此函数; -(void)tabBarController:(UITabBarController *)tabBarController willBeginCustomizingViewControllers:(NSArray *)viewControllers { } 5.结束用户自定义item后调用既单击了done ;用法可以纪录此时的新的item用于永久性更改,下次运行此程序保持这个状态; -(void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed { NSMutableArray *array=[NSMutableArray arrayWithCapacity:0]; for (UIViewController *vc in viewControllers) { NSNumber *num=[NSNumber numberWithInt:vc.tabBarItem.tag ]; [array addObject:num]; // NSLog(@"%d",vc.tabBarItem.tag); //把nsstring转换成数据类型 // int i=1; // NSString *str=[NSString stringWithFormat:@"%d",i]; // int a=[str intValue]; } NSUserDefaults *userdefault=[NSUserDefaults standardUserDefaults]; [userdefault setObject:array forKey:@"num"]; NSLog(@"didEndCustomizingViewController"); } 如何保存用户更改的uitabbaritem位置? 1.在用户用编辑item顺序后执行done,这时在调用的didEndCustomizingViewControllers 函数传递的参数viewControllers 纪录了此时新的排列顺序;这时要用本地存储记下这个顺序;注意因为每个viewcontroller在初始化时设置了自己的tag值,所以只记下tag值就可以找到对应的viewcontroller -(void)tabBarController:(UITabBarController *)tabBarController didEndCustomizingViewControllers:(NSArray *)viewControllers changed:(BOOL)changed { 初始化可变数组用于存储tag值 NSMutableArray *array=[NSMutableArray arrayWithCapacity:0]; 遍历新设置的控制器顺序;并把tag值按顺序存储到可变数组中 for (UIViewController *vc in viewControllers) { NSNumber *num=[NSNumber numberWithInt:vc.tabBarItem.tag ]; [array addObject:num]; } 定义本地存储对象; NSUserDefaults *userdefault=[NSUserDefaults standardUserDefaults]; 把可辨数组存入到本地存储中 [userdefault setObject:array forKey:@"num"]; NSLog(@"didEndCustomizingViewController"); } 2. 在加载函数中可以先判断本地存储是否有数据;如果没有就是用户还未设置过,那item顺序要按加载顺序排列;如果非空的话就把本地存储的数据的赋值给viewcontrollers; NSMutableArray *array=[NSMutableArray arrayWithCapacity:0]; for (int i=0; i<6; i++) { UIViewController *vc=[[UIViewController alloc]init]; [array addObject:vc]; UITabBarItem *item=[[UITabBarItem alloc]initWithTitle:[NSString stringWithFormat:@"vc%d",i+1] image:[UIImage imageNamed:@"1.png"] tag:i]; vc.tabBarItem=item; [item release]; [vc release]; } UITabBarController *tabbar=[[UITabBarController alloc]init]; tabbar.viewControllers=array; 注:没有alloc的对象一定不要release;如button一般创建不用alloc;注意注注意 9.14 周五 实现键盘弹起时页面也跟着弹起键盘的高度 1.基本思想: 1. 创建两个通知用于监听键盘弹起和落下 //面试重点:通知;通知中心是管理通知的; [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; //监听者一般是哪个控件创建谁监听器就谁监听 //name是监听的信号; //selecto监听到信号后触发的事件; //object 指监听某个对象,一般是全局监听所以是nil [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; 2.在监听键盘弹起的事件中记下键盘高度,然后把view提高键盘高度 -(void)keyboardWillShow:(NSNotification *)noti { 键盘弹起时触发的事件; //获得键盘的高度, 将传递过来的消息信息纪录达字典;从字典中找到关键字为键盘框架的数据让然后把它转换成cgrect类型读取它的高度 NSDictionary *dic=[noti userInfo]; CGRect rect=[[dic objectForKey:UIKeyboardFrameEndUserInfoKey]CGRectValue]; float h=rect.size.height; NSLog(@"%f",h); //设置动画 使键盘高度提高; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.25]; self.view.frame=CGRectMake(0, 20-h, 320, 460); //注意是20减去键盘的高度;因为view是加载在window上的它的frame是相对于window的。这就要注意了,a控件添加到b控件上a的frame就是相对于b的frame [UIView commitAnimations]; } 3.收起键盘 键盘弹出和收起是随文本编辑开始和退出自动弹出和收起,所以要想让文本框退出编辑模式必须有个事件触发,而在touchesbegan的系统函数中只要鼠标点击就能触发,所以一般在这个里面让textfield退出编辑模式; [ resignFirstResponder]; 就是textfield退出编辑模式的函数; -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { UITextField * textfield=(UITextField *)[self.view viewWithTag:100]; [textfield resignFirstResponder]; } 4.不使用键盘时让view以动画跳下来; -(void)keyboardWillHide:(NSNotification *)noti { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.20]; self.view.frame=CGRectMake(0, 20, 320, 460); [UIView commitAnimations]; } 弹出消息框 注:弹出消息框所用代理为UIAlertViewDelegate 这是提示框, 这个不用添加到窗口的!!! 1.创建消息框对象 UIAlertView *alertview=[[UIAlertView alloc]initWithTitle:@"error" message:@"帐号错误" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil]; 让消息框展示出来 [alertview show];//这是系统自动调用的函数 [alertview release]; 2.在消息框对象的代理函数中执行操作 消息框有四个代理函数,点击函数最常用 -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 通过传递过来的button序号知道那个button进行了操作执行相应的命令 //按钮从左边计数; if (buttonIndex==0) { self.view.backgroundColor=[UIColor yellowColor]; } else self.view.backgroundColor=[UIColor brownColor]; } 从相册和相机获取图片 思想: 1.创建获取图片按钮和接收图像的的视图控件 imageview =[[UIImageView alloc]initWithFrame:CGRectMake(100, 80, 100, 100)]; [self.view addSubview:imageview]; UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame=CGRectMake(100, 190, 120, 20); [button addTarget:self action:@selector(buttonClick) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:button]; //提示框 2.在button触发的事件中生成UIActionSheet对象去选择从哪里获取图片 -(void)buttonClick { UIActionSheet *as=[[UIActionSheet alloc]initWithTitle:@"选择图片来源" delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"相机" otherButtonTitles:@"相册", nil]; //可以生成多个按钮 [as showInView:self.view]; 展示这个动作页面; [as release]; } 3.通过调用UIActionSheet的代理函数获取图片;所以头文件必须声明他的代理一般用到是点击函数,通过传递按钮的排列序号知道那个按钮被点击触发相应的事件 -(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex==2) { return; } // 取消按钮序号是2,所以如果指针是2,表明触发了取消,注意对应的序号要和创建时一致; UIImagePickerController *pc=[[UIImagePickerController alloc]init]; //创建图片获取控制器;根据点击按钮不同从不同的资源获取图片; // 防止触发虚拟机不能完成的事件发生崩溃,提前做一下判断,如果不是虚拟机就执行操作; if(buttonIndex==0 && TARGET_IPHONE_SIMULATOR) { [pc release]; return; } if(buttonIndex==0){ pc.sourceType=UIImagePickerControllerSourceTypeCamera; } else if(buttonIndex==1) { //pc.sourceType=UIImagePickerControllerSourceTypePhotoLibrary; pc.sourceType=UIImagePickerControllerSourceTypeSavedPhotosAlbum; //区分这两个属性的不同第一个 } pc.delegate=self; //这个对象设置代理需要遵从两个协议UIImagePickerControllerDelegate, 和导航控制协议 因为图片控制器也是个导航控制器UINavigationControllerDelegate //把控制器交给图像资源获取控制器 [self presentModalViewController:pc animated:YES]; [pc release]; } 在系统中的图片获取器中点击按钮可以触发的事件 //点击图片调用的函数 -(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)editingInfo { imageview.image=image; [picker dismissModalViewControllerAnimated:YES]; } //点击取消触发的事件 -(void)imagePickerControllerDidCancel:(UIImagePickerController *)picker { [picker dismissModalViewControllerAnimated:YES]; } 9.17 第十周 周一 UIScrollView 滚动视图 注:苹果的内存复用机制:视图很大超过了屏幕显示的范围,在显示的只是屏幕上的内容,为了减少内存使用把不现实的那用从内存中去除; 1.滚动视图的初始化 UIScrollView *sv=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; frame:是滚屏在视图上占用的大小; 2.给滚动视图添加控件时,如果控件有事件响应的话,系统设置了一个定时器,如果在限定事件内拖动的话,该控件就失去了响应机会,拖动视图也会跟着拖动; UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame=CGRectMake(100, 100, 100, 50); //注意按钮的响应时间,如果按钮在没响应前滑动,此时就相当于视图滑动 3.设置滚屏的大小,这个属性很重要 显示的是内容的大小 体现了滚动视图的经典 sv.contentSize= CGSizeMake(320, 460*2); 滚屏的真实大小; 4.初始位置设置 //偏移量 是一个点 有x值与 y值 sv.contentOffset=CGPointMake(90, 90); // contentOffset.x 与 contentOffset。y //注:x,y是屏幕的框架原点相对于滚屏的原点的位置;当滚屏超出手机框架时这两个值比为正数; 5.竖直和水平滚动条是否显示;默认时显示滚动条//这条很重要 sv.showsVerticalScrollIndicator=NO;//是否显示竖直方向的滚动条 sv.showsHorizontalScrollIndicator=NO;//是否显示水平方向的滚动条,默认是显示的 ,不显示设置成NO 6.反弹效果的设置;设为yes后可以反弹;设为no就不能反弹; sv.bounces=YES; //总是反弹,即使大小和边框一样也可以有反弹效果; sv.alwaysBounceHorizontal=YES; sv.alwaysBounceVertical=YES; 7.设置为不可滚动;即使大于框架 sv.scrollEnabled=NO; //添加图片视图,视图用addSubview的方法来添加,把图片添加到滚动视图上面 [sv addSubview:imageView]; //再把滚动视图添加到 总试图上面 [self.view addSubview:sv ]; //设置显示内容尺寸 sv.contentSize=CGSizeMake(260*4, 400); //设置按照页码滚动 sv.pagingEnabled=YES;//这样设置是保证 一页一页的显示出来 不可能只显示一半,用户不喜欢看到这个效果; //设置边缘弹动效果//主要是给用户感觉的 sv.bounces=YES;//可以弹动的 也可以sv.bounces=NO;此时到边缘就不能滚动,不会出现一些不该出现的空白 //改变滚动条偏移量 当前显示内容的偏移量; sv.contentOffset=CGPointMake(100, 0); 使用:代理的三部曲,每一个协议方法都是这么来做的 遵守协议(什么控制器遵守什么协议 写在尖括号里面) 委托代理(A.delegate=self) 实现方法(完成的方法); 8.滚动条的代理函数 1.当屏幕滚动时调用的函数 -(void)scrollViewDidScroll:(UIScrollView *)scrollView { NSLog(@"%f %f",scrollView.contentOffset.x,scrollView.contentOffset.y); } 2. 将要开始拖动时调用 -(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView 3.滚动结束后调用 手指抬起开始减速的瞬间 开始回调 //用这个方法来实现拖动的时候 页的对应 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { NSLog(@"endDrag"); } 4.滚屏结束时调用 -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView 5.滚屏将开始减速时调用 -(void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView 用一个类来封装一下,封装就是派生出一个类,写自己的类, 9.用滚动视图来显示图片的缩放;注:滚屏只能执行单一功呢,要么让他做缩放功呢,要么让他实现滚屏; 1.创建滚动视图 super viewDidLoad]; UIScrollView *sv=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; 2.设置最大最小缩放 //缩放和滑动止只能选一 sv.maximumZoomScale=5.0; sv.minimumZoomScale=0.5; 3. 创建视图控件,然后添加到滚屏中。 imageview=[[UIImageView alloc]initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"5.png"]]]; imageview.frame=CGRectMake(100, 100, 50, 50); [sv addSubview:imageview]; [imageview release]; 4.用到滚屏的函数要给它设置代理 sv.delegate=self; 处理用户响应事件,需要重载那三个触摸的方法,开始,触摸到,末尾, 5.在滚屏的放大缩小函数中写实现功能 -(UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { static int i=0; if (scrollView!=myScrollView) { return [scrollView.subviews objectAtIndex:i]; i++; } else return NULL; } 封装一个类达到的效果 简化代码,很有好处 10.运用滚动屏实现广告条展示; 设计思想:滚动广告起始和最后广告条实现不间断的无限循环;所以要多家一个视图,最后一个视图和第一个一样,这样可以保证不间断; UIScrollView *sv=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, 320, 200)]; sv.contentSize=CGSizeMake(320, 200*9); sv.scrollEnabled=NO; //视图的可滚动属性设为no不可滚动; sv.tag=100; [self.view addSubview:sv]; sv.showsVerticalScrollIndicator=NO; for (int i=0; i<9; i++) { UIImageView *imageview=[[UIImageView alloc]initWithFrame:CGRectMake(0, i*200, 320, 200)]; imageview.image=[UIImage imageNamed:[NSString stringWithFormat:@"17_%d.jpg",i]]; [sv addSubview:imageview]; [imageview release]; } //创建计时器来控制图片定时更替 NSTimer *timer=[NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(timer:) userInfo:nil repeats:YES]; } -(void)timer:(NSTimer *)timer { UIScrollView *sv=(UIScrollView *)[self.view viewWithTag:100]; //当滚屏滚到最后一幅图时,让滚屏从头开始 if(sv.contentOffset.y==200*8)//偏移量contentOffset,画布向左偏移是正的,向右偏移是负的,这是原则; { sv.contentOffset=CGPointMake(0, 0); } [sv setContentOffset:CGPointMake(0, sv.contentOffset.y+200) animated:YES]; } UIPageControl 分页显示 页面控制器 1.初始化对象 UIPageControl *pc=[[UIPageControl alloc]initWithFrame:CGRectMake(0, 440, 80, 20)]; 2.设置页数 pc.numberOfPages=4;//设置小点的个数 pc.tag=100; 3.为分页点添加事件 [pc addTarget:self action:@selector(pc:) forControlEvents:UIControlEventTouchUpInside]; 4.在滑动页面时,为每页定位 开发者无法判断用户判断到哪一页,所以只有委托UIScrollView的方法 使用这个函数之前要实现UIScrollViewDelegate代理 -(void)scrollViewDidScroll:(UIScrollView *)scrollView { UIPageControl *pc=(UIPageControl *)[self.view viewWithTag:100]; pc.currentPage=scrollView.contentOffset.x/320;//改变原点的颜色 } 5.注意要想给滚屏分页,除了创建分页对象还要让滚屏设置分页属性 sv.pagingEnabled=YES; //遵从UIScrollViewDelegate协议,实现UIScrollViewDelegate里面的方法 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {//当页面开始减速的瞬间回调函数 int pageNumber=scrollView.contentOffset.x/320;//contentoffset 内容的偏移量 myPageontrol.currentPage=pageNumber; } 9.18周二 必须实现的 @required - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; UITableView 表视图 1.初始化表格控件 UITableView * tableview=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460-44) style:UITableViewStyleGrouped]; tableview.tag=100; 2.给表格控件添加代理。注意它有两个代理//必须是两个代理 tableview.delegate=self; tableview.dataSource=self; 3.表格控件的代理函数 //delegate 行数和单元格函数必须实现。否则程序无法运行; 1.行数 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return dataarray.count;//有的时候每一行都是一样的 } 1,复用机制;要重点了解; 2,只有一列,两列的话就是有两个tableView; 3,有数据源对象,代理对象,tableView本身的对象; 2.cell单元格//多少个格子要完成;每个格子里面是什么东西; 一定要完成这两个协议,否则UITableView会崩溃 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 为每个单元个加一个标志,便于取得//每个格子的标题 NSString *strID=@"ID";//代表的是某种类型的cell;字不是写的一样,但都是一种 从表格对象中得到移出屏幕得对象; UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:strID];//用队列的方式去找cell if (cell==nil) { //空值的情况,重现创建一个 //顶多分配20个,然后不会再去分配了。然后反复的使用,0到10 是可以被替换的,不是一下子分配一万个,内存考虑 cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:strID]autorelease]; // UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(10, 10, 40, 20)]; // label.text=[NSString stringWithFormat:@"%d",indexPath.row]; // [cell addSubview:label]; // label.tag=100; } // indexPath.row; 行数 //// indexPath.section 段数 section代表的是组数,分组的时候就出来了 // UILabel *label=(UILabel *)[self.view viewWithTag:100]; // label.text=[dataarray objectAtIndex: indexPath.row]; //添加图片 cell.imageView.image=[UIImage imageNamed:@"5.png"]; //添加细节名称表明可以展开cell cell.detailTextLabel.text=@"open"; //表示有更多内容的展示风格//表格栏的尖尖 一半的中括号 cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator; //选择时变色设置 cell.selectionStyle=UITableViewCellSelectionStyleNone; // 设置cell文本 从数组中取出来 可以把文字统一放到数组里面去 cell.textLabel.text = [dataarray objectAtIndex:indexPath.row];//主标题 //添加细节名称表明可以展开cell 副标题 cell.detailTextLabel.text=@"open"; return cell; } 删除或添加cell 先删除数据,再添加数据源 ,分为两步, 因为它有两个代理 ,其中一个就是数据源代理 3. 段数 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } 4.行高 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // 可以设置每个行行高 // if (indexPath.row==1) { // return 20; // } return 50; } 5.段头标题 -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return @"abc"; } 6.段尾标题 -(NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { return @"tial"; } 7.删除和添加 设置每个单元格的可编辑属性默认是yes所以当让它处于编辑模式时这个函数可以不写 //设置元素的可编辑性 -(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } //更改单元格的编辑属性;可以设置为删除和插入 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath{ return UITableViewCellEditingStyleInsert;//插入模式; } //可以滑动弹出删除键删除,也可以设置编辑按钮,点击编辑按钮删除 -(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 删除时既要从屏幕上删除,又要从数组中删除, [dataarray removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight]; } 注意:如果表格分很多段,就必须分段操作; 1.分几段,就创建几个数组,以防删除不同段内容相互影响,导致崩溃; 2.在给每段单元格添加标题时也要分段添加;返回行数时也要按段来返回数组的行数; 3.在删除单元格时要根据段不同删除不同的数组元素; //删除按钮改名为 -(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { return @"2334"; } 7.为选择cell添加操作;下面操作为点击就会跳到新页面;作为选择cell操作的时候来用的 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UIViewController *vc=[[UIViewController alloc]init]; vc.title=[NSString stringWithFormat:@"%d",indexPath.row]; [self.navigationController pushViewController:vc animated:YES];//push之后再去加载; } 8.//didSelectRowAtIndexPath作为cell选择操作的时候用 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { UISearchBar * search = (UISearchBar *)[self.view viewWithTag:102]; //是否是第一响应事件 if ([search isFirstResponder]) { //若果是的画 就响应 [search resignFirstResponder]; } } 9.为表格添加索引,点击就会跳到对应位置,分段的话每个标记代表一段 -(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [NSArray arrayWithObjects:@"a",@"b",@"c", nil]; } 10.移动某个cell -(BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } -(void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { //注意从前往后和从后往前移动不同 NSString *str=[dataarray objectAtIndex:sourceIndexPath.row]; // NSString *str1=[dataarray objectAtIndex:destinationIndexPath.row]; if(sourceIndexPath.row<destinationIndexPath.row){ [ dataarray insertObject:str atIndex:destinationIndexPath.row+1 ] ; [dataarray removeObjectAtIndex:sourceIndexPath.row]; } else { [dataarray insertObject:str atIndex:destinationIndexPath.row]; [dataarray removeObjectAtIndex:sourceIndexPath.row+1]; } } 注意有导航条时table的高要减掉导航条的高; //@required里面的方法是必须要实现的;@optional里面的方法可以实现也可以不实现 @interface VC01 : UIViewController <UITableViewDelegate, UITableViewDataSource> //UITableView实现不了的,就用代理,让别人帮他实现,实现里面需要的方法 9.19 周二 搜索条一般搜索条 -(void)viewDidLoad { [super viewDidLoad]; dataArray=[[NSArray alloc]initWithObjects:@"dwew",@"dfas",@"aads",@"we", nil]; 注:在搜索设置时数组创建一定要用alloc;而且release 要在最后的dealloc中;因为数组用于更新数据,不断的使用如果不用alloc创建可能会被释放导致数组不可用; _tableview=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; _tableview.delegate=self; _tableview.dataSource=self; 注:写tableview 的协议; [self.view addSubview:_tableview]; //创建搜索条 UISearchBar *search=[[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 320, 88)]; search.delegate=self; 注:注意添加uisearchbar的协议; //添加搜索栏 mSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 320, 44)]; [mSearchBar setTag:102]; _mTableView.tableHeaderView = mSearchBar; search.showsScopeBar=YES; search.scopeButtonTitles=[NSArray arrayWithObjects:@"a",@"b",@"c", nil]; 注:添加范围条;两个函数必须连用;要对其添加事件要在下面函数中添加,这个事件是在点击button时触发 -(void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope search.showsCancelButton=YES; 注:添加取消键 search.showsSearchResultsButton=YES; 注:设置搜索键 出发事件要和下面的函数连用 一般用于撤销键盘实现搜索功能; -(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar 注:将搜索条添加到tableview中; _tableview.tableHeaderView=search; } // 添加取消按钮,点击取消按钮时触发; -(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { [searchBar resignFirstResponder]; searchBar.text=@""; } // 如果设置搜索列表键为真,将添加了搜索列表键到搜索列表的后面,点击时触这个事件; -(void)searchBarResultsListButtonClicked:(UISearchBar *)searchBar{ searchBar.text=@"resultslistbutton"; } //点击键盘上的搜索键时触发; -(void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { [self searchBar:searchBar textDidChange:searchBar.text]; } //当添加了范围界定条时点击上面的按钮触发 -(void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope { if (selectedScope==0) { searchBar.text=@"a"; } else if(selectedScope==1){ searchBar.text=@"b"; } else searchBar.text=@"c"; [self searchBar:searchBar textDidChange:searchBar.text]; //调用自己的函数;对数据进行搜索;从此也得知,非键盘输入的数据要搜索必须通过调用搜索函数出发,或者在键盘状态加入非键盘输入的数据; } //返回表格的行数;根据是否是搜索状态还非搜索状态反会不同的数据 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (isSearch==YES) { return searchArray.count; } else return dataArray.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"ID"]; if (cell==nil) { cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ID"]autorelease]; } if (isSearch==YES) { NSLog(@"%@",searchArray); cell.textLabel.text=[searchArray objectAtIndex:indexPath.row]; } else{ cell.textLabel.text=[dataArray objectAtIndex:indexPath.row]; } return cell; } //搜索条中的内容改变时调用;但有个问题就是一旦开始搜索取消后原内容不显示因为这个函数只有搜索条中输入值时才调用;所以搜索取消不显示原有数据;但是如果在结束编辑中调用此函数就不会出现此情况; 但是此时如果有取消键的话又必须在取消键中添加内容让取消后清空搜索框并加载原又数据;所以下面的三个函数是联系起来的 -(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { if (searchBar.text==nil||[searchBar.text isEqualToString:@""]) { isSearch=NO; [_tableview reloadData];//自动刷新, 自动刷新数据 } NSPredicate *predicate=[NSPredicate predicateWithFormat:@"SELF contains [cd] %@",searchBar.text]; self.searchArray=[dataArray filteredArrayUsingPredicate:predicate]; isSearch=YES; [_tableview reloadData]; } -(void)searchBarTextDidEndEditing:(UISearchBar *)searchBar{ [self searchBar:searchBar textDidChange:searchBar.text]; } -(void)searchBarCancelButtonClicked:(UISearchBar *)searchBar { searchBar.text=@""; isSearch=NO; [_tableview reloadData]; [searchBar resignFirstResponder]; } 运用搜索控制器来实现搜索功能 -(void)viewDidLoad { dataarray=[[NSArray alloc]initWithObjects:@"da",@"dee",@"ded",@"rtt", @"esdf",@"effy",@"qqo",@"ett",@"sdfa",@"dfg",nil]; 注:创建搜索数组,数组必须用alloc初始化而且不能被release; tableview=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStylePlain]; tableview.delegate=self; tableview.dataSource=self; tableview.tag=100; 注:要为tableview添加tag属性便于知道搜索状态应为处于搜索状态时搜索控制器就会覆盖住表格框;所以通过判断此时是的tableview是那个可以知道更新那个数组数据; [self.view addSubview:tableview]; [tableview release]; UISearchBar *searchbar=[[UISearchBar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; tableview.tableHeaderView=searchbar; 注:创建搜索展示控制器 把导航条添加进去;把文本控制设置为本类; searchdisplay=[[UISearchDisplayController alloc]initWithSearchBar:searchbar contentsController:self]; 注:设置代理,和搜索资源搜索代理; searchdisplay.delegate=self; searchdisplay.searchResultsDataSource=self; searchdisplay.searchResultsDelegate=self; 注意:此时搜索控制器不用释放,因为这个搜索器需要不断被调用; [searchbar release]; } 根据此时那个tableview被使用返回数据; -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (tableView.tag==100) { return dataarray.count; } return searcharray.count; } //设置单元格; -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"ID"]; if (cell==nil) { cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ID"]; } if (tableView.tag==100) { cell.textLabel.text=(NSString *)[dataarray objectAtIndex:indexPath.row]; } else cell.textLabel.text=(NSString *)[searcharray objectAtIndex:indexPath.row]; return cell; } -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 3; } //更新数据前对数据进行过滤;得到过滤的数据;此函数是个实时监控函数; -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{ NSPredicate *predicate=[NSPredicate predicateWithFormat:@"SELF contains [cd] %@",searchString]; self.searcharray=(NSArray *)[dataarray filteredArrayUsingPredicate:predicate]; NSLog(@"%@",searcharray); return YES; } //返回tableview中和对应段指针相对应的section的title;相当于为每段设置了一个名字 -(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { return [NSArray arrayWithObjects:UITableViewIndexSearch,@"a",@"b",@"c",nil]; //注意这里添加了一个搜索,所以搜索指针对应发生改变;在下面的函数返回时要注意 } //返回和title和index一致的section -(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index { if (index==0) { [tableView setContentOffset:CGPointMake(0, 0)]; } return index-1; } //设置section的头标题; -(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [NSString stringWithFormat:@"%d",section]; } 注意:有些对象没有被释放要写dealloc函数; 设置控件的收起和放下 (void)viewDidLoad { [super viewDidLoad]; array=[[NSArray alloc]initWithObjects:@"小红",@"小梅",@"小李", nil]; tableview=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStylePlain]; tableview.delegate=self; tableview.dataSource=self; tableview.sectionHeaderHeight=30; //设置tableview的section头标题的高;便于以后添加控件和控件大小相适应 [self.view addSubview:tableview]; [tableview release]; p[0]=1;//p是有两个元素的整形数组做为开关;如果设置几段需要几个开关,就让数组元素个数是几 p[1]=1; } //根据数组元素的值确定段是打开还是收起; //简称设置行数 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (p[section]==0) { return 0; } return array.count;//直接返回 } //设置组数 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 2; } //创建表格单元格 -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"ID"]; if (cell==nil) { cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ID"]autorelease]; } cell.textLabel.text=[array objectAtIndex:indexPath.row]; return cell; } //为表格的段头添加view让此view加载label和button,并为button添加事件用于控制开关的打开和关闭;既置0和置1; -(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { UIView *view=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 30)]; view.backgroundColor=[UIColor blueColor]; UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 80, 30)]; label.backgroundColor=[UIColor clearColor]; if (section==0) { label.text=@"我的好友"; } else label.text=@"黑名单"; [view addSubview:label]; UIButton *button=[UIButton buttonWithType:UIButtonTypeCustom]; button.tag=section; //注意添加button的tag用于鉴别是哪个button; button.frame=CGRectMake(0, 0, 320, 30); [button addTarget:self action:@selector(buttonclick:) forControlEvents:UIControlEventTouchUpInside]; [view addSubview:button]; return view; } //button事件用于控制开关状态; -(void)buttonclick:(UIButton *)sender { if (p[sender.tag]==0) { p[sender.tag]=1; } else p[sender.tag]=0; [tableview reloadSections:[NSIndexSet indexSetWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationFade]; //重新加载section根据button的不同来决定加载那个section 之 所以可以这样适应为button。tag是根据section设置的;此时加载section需要的数据是nsindexset类型搜一要把button的tag转换成此类型; } 为解决问题:怎么让section头宽度变大? 解决方法:设置tableview的section的头高 设置代码为:tableview.sectionHeaderHeight=30; cell的层次 view在cell上contentview又在view上其他控件又加在了content view上 cell的contentView cell上面的内容视图 9.20周四 和xib文件连用创建表格 创建表格框,然后创建xib文件,并把xib文件中的默认视图删除;添加tableviewcell 可以在里面添加其他控件; -(void)viewDidLoad { [super viewDidLoad]; UITableView * tableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320,460) style:UITableViewStylePlain]; tableView.delegate=self; tableView.dataSource=self; [self.view addSubview:tableView]; [tableView release]; } //设置行数 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 20; }/ //在创建cell的函数中将xib创建的文件添加到tableview中; -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell * cell=[tableView dequeueReusableCellWithIdentifier:indexPath.row%2==0?@"ID":@"ID2"]; if(cell==nil){ //cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ID"]; cell=[[[NSBundle mainBundle] loadNibNamed:indexPath.row%2==0?@"MYcell":@"MYCell2" owner:self options:nil]objectAtIndex:0]; //和xib中的文件绑定; } //设置cell颜色要注意是设置contentview的颜色应为它覆盖在cell上; // cell.contentView.backgroundColor=[UIColor redColor]; //cell也是个view 上有contentview 其实label也是加再contentview上 return cell; } //自定义的cell注意在创建自定义cell类在写继承时是继承UITableViewCell; 创建cell类后在初始化文件中写上初始化的cell特性,既需要更改什么属性,加在其他控件; - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { self.myLabel=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 40)]; myLabel.textAlignment=UITextAlignmentCenter; myLabel.backgroundColor=[UIColor greenColor]; [self addSubview:myLabel]; [myLabel release]; } return self; } //在控制器中创建cell时创建自定义cell -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //复用池,每次显示满屏dequeueReusableCellWithIdentifier方法 复用机制 CustomCell *cell=(CustomCell *)[tableView dequeueReusableCellWithIdentifier:@"ID"]; if (cell==nil) { cell=[[CustomCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ID"]; } //加载文本从资源文件中获取; NSString *str=[NSString stringWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"ui" ofType:@"rtf"] encoding:NSUTF8StringEncoding error:nil ]; // NSString *str=[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"c" ofType:@"rtf"] encoding:NSUTF8StringEncoding error:nil]; cell.myLabel.text=str; return cell; } 9.24 周一 第十一周(网络 在使用不同的网络协议传输时都要先加入协议文件;如果用到他们的对应函数时要写协议,设置代理 1.json 格式网络传输 在网络中传输请求时用的时是字符串。他们用{}[]链接起来;其中{}表示字典;[]表示数组;解析时只要分清层次需要从哪取数据就用相应的数组或对象取数据; 1.网络数据解析 //{ "title":"harry pottery", "price":"999$"} NSString *json=@"{\"title\":\"harry pottery\",\"price\":\"99999\"}"; //双引号里面不能在有双引号,所以加双引号前要加反斜杠; NSDictionary *dic=[json JSONValue]; NSString *str=[dic objectForKey:@"title"]; NSLog(@"%@",str); //[{"a","b","c"}] json=@"[\" a\", \"b\",\"c\"]"; NSArray *array=[json JSONValue]; for (NSString *s in array) { NSLog(@"%@",s); } /* { "books":[ { "title": "harry1" }, { "title":"harry2" } ] "num":"7" } */ /* } */ json=@"{\"key1\":[{\"key2\":\"value2\"},\"value3\" ]}"; NSDictionary *dic1=[json JSONValue]; array=[dic1 objectForKey:@"key1"]; dic=[array objectAtIndex:0]; NSString *st=[dic objectForKey:@"key2"]; NSLog(@"%@",st ); 2 .SBJson网络传输数据:要加入第三方协议:SBJson 冰岛入SBJson.h头文件 NSData *data=[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://localhost/1.gif"]]; UIImage *image=[UIImage imageWithData:data]; UIImageView *imageview=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 200)]; imageview.image=image; [self.view addSubview:imageview]; 3.SDWebImage 网络传输 //使用SDWebImage 传输数据,而且它是个自带缓存打开过,再打开时还存在; 在使用图片按钮传输时要引人头文件 #import "UIImageView+WebCache.h" #import "UIButton+WebCache.h" NSURL *url=[NSURL URLWithString:@"http://localhost/1.gif"]; UIImageView *image =[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 200)]; [image setImageWithURL:url]; [self.view addSubview:image]; [image release]; 4.ASIHTTPRequest网络传输??????? 首先要导人四个库文件libz.1.2.5.dylib,CFNetwork.framework, SystemConfiguration.framework,MobileCoreServices.framework 引人头文件 #import "ASIHTTPRequest.h" 同时要添加ASIHTTPRequest.h协议;设置代理 NSURL *url=[NSURL URLWithString:@"http://localhost/1.gif"]; //使ASIHTTPRequest 传输数据;注意这个需要加第三方协议 ASIHTTPRequest *request=[ASIHTTPRequest requestWithURL:url]; request.delegate=self; [request startSynchronous]; //开始同步 [UIApplication sharedApplication].networkActivityIndicatorVisible=YES; //网络请求,如果为yes,就一直旋转 -(void)requestFinished:(ASIHTTPRequest *)request { UIImageView *imageview=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 200)]; imageview.image=[UIImage imageWithData:request.responseData]; [self.view addSubview:imageview]; } 5.异步传输 这种异步传输需要代理 <NSURLConnectionDataDelegate> /异步传输数据:优点:在传输数据没有完成前,可以对网页上的其他东西进行操作; [super viewDidLoad]; NSURL *url=[NSURL URLWithString:@"http://localhost/1.gif"]; //创建请求 NSURLRequest *request=[NSURLRequest requestWithURL:url]; //发送请求 [NSURLConnection connectionWithRequest:request delegate:self]; data1=[[NSMutableData alloc]init]; imageview=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 200)]; [self.view addSubview:imageview]; } //异步传输链接的代理函数: //链接响应时调用 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { NSLog(@"didreceiveresponse"); } //加载完成时调用 -(void)connectionDidFinishLoading:(NSURLConnection *)connection { imageview.image=[UIImage imageWithData:data1]; NSLog(@"connectiondidFinishload"); } //反复调用不断接收新数据 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { [data1 appendData:data]; NSLog(@"didreceivedata"); } //链接发生错误时响应; -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLog(@"error"); } xml 首先导人GData 文件, 然后通过在项目头文件中Build Phases中第三个选项中数添加libxml2 文件并将其移动到项目下面, 然后在 BuildSettings中在search paths中在 Header Search Paths 中添加路径/use/include/libxml2 这样就可用xml 读取网络文件了; 1.将网络编码文件存入字符串; NSString *xmlstr=[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"xml" ofType:@"txt"] encoding:NSUTF8StringEncoding error:nil]; 2.将字符串转变成GDataXMLDocument 类行的文件; 获取文件 GDataXMLDocument *xmldoc=[[GDataXMLDocument alloc]initWithXMLString:xmlstr options:0 error:nil]; 3.从文件中获取根元素; //获取跟元素 GDataXMLElement * rootEle=[xmldoc rootElement]; 4.获取元素的值 rootEle.stringValue 5.获取根元素下面的某项值,用所在位置获取;也可以通过数组把他们全都放到数组,在从数组中获取; GDataXMLElement *sysele=(GDataXMLElement *)[rootEle childAtIndex:0]; GDataXMLElement cityele=[sysele childAtIndex:0]; NSArray *array=[sysele children]; 6.获取元素的 XMLString属性值; 获取属性stringValue值 属性名值name array =[intel children]; for (GDataXMLElement * itemele in array) { //itemele.attributes 是元素得属性 是个数组; for (GDataXMLElement * item in itemele.attributes) { //打印元素属性;会将每个属性和值一起打印出来; NSLog(@"%@",item.XMLString); //打印属性得值 NSLog(@"%@",item.stringValue); //打印属性名字 NSLog(@"%@",item.name); } } 7.通过元素名获取元素; //通过元素名获取元素 GDataXMLElement *codeele=[[sysele elementsForName:@"areaCode"] objectAtIndex:0]; 8.通过路径获取获取元素; //XPATH 通过路径获取元素 注意通过路径取出的元素因为不知道保函几个元素,所以是数组类行要想取得得用objectindexat 根据位置获取其中得某一个; //绝对路径 GDataXMLElement *cityele=[[xmldoc nodesForXPath:@"root/systemConfig/CityName" error:nil] objectAtIndex:0]; NSLog(@"%@",cityele.stringValue); //通过层次写; cityele=[[xmldoc nodesForXPath:@"//CityName" error:nil] objectAtIndex:0]; NSLog(@"%@",cityele.stringValue); //获取在这个层次得所以item NSArray *array=[xmldoc nodesForXPath:@"//Item" error:nil]; //获取某个目录下得item并通过item[i]打印它的元素;注意是从元素标号1开始; array=[xmldoc nodesForXPath:@"//intentionLevel/Item[1]" error:nil]; GDataXMLElement *tem =[[xmldoc nodesForXPath:@"//Item" error:nil] o bjectAtIndex:0]; GDataXMLElement *ele =[tem.attributes objectAtIndex:0]; //元素得属性指针开始从0位置; NSLog(@"%@",ele.stringValue); //打印最后一个元素 array=[xmldoc nodesForXPath:@"//intentionLevel/Item[last()]" error:nil]; //打印某个范围内的元素通过位置号判断 array=[xmldoc nodesForXPath:@"//intentionLevel/Item[position()<3]" error:nil]; //获取不同节点下的元素 array=[xmldoc nodesForXPath:@"//intentionLevel/Item[position()<3]|// ****/item[2]" error:nil]; //通过关键字获取值; array=[xmldoc nodesForXPath:@"//intentionLevel/Item[@key=2]" error:nil]; array=[xmldoc nodesForXPath:@"//intentionLevel/Item[@key<3]" error:nil]; 在接收取出来的元素时,一般取出来的是数组,要用数组接,如果是单个元素要用数组的object 0去转换成对象;然后再取其中的属性; 网页刷新 准备工作: 1.再刷新网页时用到了第三方代理,在引入函数前要先添加文件 EGOTableViewPullRefresh 2。添加库文件:QuartzCore.framework 3.加入代理:1.UITableViewDelegate, 2.UITableViewDataSource, 3.EGORefreshTableHeaderDelegate viewdidload函数内容: 1.创建获得内容得数组; dataArray=[[NSMutableArray alloc]initWithObjects:@"a",@"b",@"c",@"d" ,nil]; 2.创建table 并设置代理; table=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 460) style:UITableViewStylePlain]; table.delegate=self; table.dataSource=self; [self.view addSubview: table]; [table release]; 3.创建刷新视图 refreashview=[[EGORefreshTableHeaderView alloc]initWithFrame:CGRectMake(0, -460, 320, 460)]; refreashview.delegate=self; 4.添加刷新视图到table中; [table addSubview:refreashview]; //更新上次刷新时间,如果没有只返回date化上次更新时间不跟着刷新 [refreashview refreshLastUpdatedDate]; } 代理函数内容 加载时调用是table 它是个bool值,时时自动调用 -(BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView *)view { NSLog(@"isloading"); return isloading; //是否正在刷新,如果返回no就会在次加载数据,会让数据加载过多 } 时间函数timer调用得方法 -(void)refresdata { //更新数据; [dataArray addObject:@"new"]; [table reloadData]; [refreashview egoRefreshScrollViewDataSourceDidFinishedLoading:table]; 一但更新完以后就要把加载函数反回得bool值改变为no便于下次加载; isloading=NO; } //加载更新出发得更新函数; -(void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView *)view { isloading=YES; [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(refresdata) userInfo:nil repeats:NO]; //注意这里得重复要设置为no,调用一次这个函数才添加一个timer, NSLog(@"didTrigger"); } //屏幕滚动时调用 -(void)scrollViewDidScroll:(UIScrollView *)scrollView { // 调用这个函数用于调用加载函数并根据不同的状态设置位置; [refreashview egoRefreshScrollViewDidScroll:scrollView]; } -(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { 根据现在更新的状态,打开加载的控制器; [refreashview egoRefreshScrollViewDidEndDragging:scrollView]; } //添加上次刷新时间; -(NSDate *)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView *)view { return [NSDate date]; } //创建tableview的基本函数; -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return dataArray.count; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"ID"]; if ( cell==nil) { cell=[[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ID"] autorelease]; } cell.textLabel.text=[dataArray objectAtIndex:indexPath.row]; return cell; } -(void)dealloc { [dataArray release]; [super dealloc]; } 9.26 周三 数据库操作; 进入数据库 sqlite3 data.db 退出数据库 .quit 创建表 create table Students(name, score); 插入数据前看是否有表,没表就创建 create table if not exists Students(name,score); 插入数据 insert into Students values('kety',89); 删除表 drop table Stufents 删除某项数据 delete from Students where name='hau'; 修改数据 update Students set score=55 where name='hahan'; 排序: 降序排; 默认升序排 select * from Book order by price desc; 排序后显示前几项 select * from Book order by price desc limit 5; 查询某个条件范围的全部数据 select * from Book where price>40; 查询内容中的某一项 select name from Book; 两个表关联查询 select Students.name, Student1.pro, Students.score from Students join Student1 on Students.name=Student1.name; 查询纪录数量; select count(*)from Students; 前台操作和数据库链接 注意:在操作前要导入文件libsqlite3.dylib 导入头文件#import "sqlite3.h"; self.PATH=[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:@"data.db"]; 注意: PATH 是接收路径的字符串变量,注意前面要加上self; //路径的创建,stringByAppendingPathComponent 给字符串拼接时加斜杠; //NSDocumentDirectory 永久保存数据; 在出发事件中进行后台操作; 增加纪录 -(void)add { //打开数据库 sqlite3 *sql; int res =sqlite3_open([PATH UTF8String], &sql); if (res!=SQLITE_OK) { NSLog(@"open error"); return; } //创建表 NSString *sqlStr=@"create table if not exists Students(name,score)"; res=sqlite3_exec(sql, [sqlStr UTF8String], NULL, NULL, NULL); if (res!=SQLITE_OK) { NSLog(@"Create error"); sqlite3_close(sql); return; } sqlStr =[NSString stringWithFormat:@"insert into Students values('%@','%@')",namefield.text,scorefield.text]; res=sqlite3_exec(sql, [sqlStr UTF8String], NULL, NULL, NULL); if (res!=SQLITE_OK) { NSLog(@"insert error"); } sqlite3_close(sql); } 删除纪录 -(void)del { sqlite3 *sql; int res =sqlite3_open([PATH UTF8String], &sql); if (res!=SQLITE_OK) { NSLog(@"open error"); return; } NSString *sqlStr=[NSString stringWithFormat:@"delete from Students where name='%@'",namefield.text]; res=sqlite3_exec(sql, [sqlStr UTF8String], NULL, NULL, NULL); if (res!=SQLITE_OK) { NSLog(@"delete error"); } sqlite3_close(sql); } 更新纪录 -(void)upd { sqlite3 * sql; int res =sqlite3_open([PATH UTF8String],&sql ); if (res!=SQLITE_OK) { NSLog(@"open error"); return; } NSString *sqlStr=[NSString stringWithFormat:@"update Students set score='%@' where name='%@'",scorefield.text,namefield.text]; res=sqlite3_exec(sql, [sqlStr UTF8String], NULL, NULL, NULL); if (res!=SQLITE_OK) { NSLog(@"UPDATE ERROR"); return; } sqlite3_close(sql); } 查询纪录 -(void)sel { sqlite3 *sql; int res=sqlite3_open([PATH UTF8String], &sql); if (res!=SQLITE_OK) { NSLog(@"open error"); return; } 创建预处理 sqlite3_stmt *stmt; NSString *sqlStr=@"select *from Students"; res=sqlite3_prepare_v2(sql, [sqlStr UTF8String], -1, &stmt, NULL); if (res!=SQLITE_OK) { NSLog(@"prepare error"); return; } while (sqlite3_step(stmt)==SQLITE_ROW) { char *name=(char *)sqlite3_column_text(stmt, 0); char *score=(char *)sqlite3_column_text(stmt, 1); NSLog(@"%s %s",name,score); } sqlite3_close(sql); } 创建新的线程:作用在主线程执行时同时调用另一个线程使不同操作同时执行;用于网络和数据库传送数据时不影响执行其他内容 创建新线程: //开辟新线程;把读取网络和数据库的内容可以开辟新线程, [NSThread detachNewThreadSelector:@selector(thread ) toTarget:self withObject:nil]; 想要在新线程中执行的内容可以可以写到新线程调用的函数中 -(void)thread { //通过函数跳回主线程; [self performSelectorOnMainThread:@selector(main1) withObject:nil waitUntilDone:nil];//延时调用函数 } 计时器也可以开辟新线程;所以在网络和数据库传输数据时可以用计时器来替代进程 //timer也会开辟新线程;可以用来代替线程函数; [NSTimer scheduledTimerWithTimeInterval:0.0 target:self selector:@selector(timer) userInfo:nil repeats:YES]; 在数据库操作时添加,删除,更新的操作思想: 1.打开数据库; 2.创建操作语句; 3.执行语句; 4.关闭数据库; 9.27 周四 引入第三方协议和后台数据库链接; 1.先引入数据库文件libsqlite3.dylib 再添加第三方文件FMDB, 引入头文件 #import "FMDatabase.h" 2.实现增,删,改,查功能 -(void)add { //绑定数据库 FMDatabase *db=[FMDatabase databaseWithPath:PATH]; BOOL res =[db open]; if (res==NO) { NSLog(@"open error"); return; } //执行语句; res=[db executeUpdate:@"create table if not exists Students (name,score)"]; if (res==NO) { NSLog(@"creat error"); [db close]; return; } res=[db executeUpdate:@"insert into Students values(?,?)",namefield.text,scorefield.text]; if (res==NO) { NSLog(@"insert error"); } [db close]; // NSData *data=[NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"" ofType:@"png"] ]; } //delete -(void)del { FMDatabase *db=[FMDatabase databaseWithPath:PATH]; BOOL res =[db open]; if (res==NO) { NSLog(@"open error"); return; } res=[db executeUpdate:@"delete from Students where name =?",namefield.text]; if (res==NO) { NSLog(@"delete error"); } [db close]; } -(void)upd { FMDatabase *db=[FMDatabase databaseWithPath:PATH]; BOOL res=[db open]; if (res==NO) { NSLog(@"open error"); return; } res=[db executeUpdate:@"update set score=77 from Students where name=?",namefield.text]; if (res==NO) { NSLog(@"update error"); } [db close]; } -(void)sel { FMDatabase *db=[FMDatabase databaseWithPath:PATH]; BOOL res=[db open]; if (res==NO) { NSLog(@"open error"); return; } 预处理数据 FMResultSet *set=[db executeQuery:@"select * from Students"]; 遍历数据 while ([set next]) { NSString *name=[set stringForColumn:@"name"]; NSString *score=[set stringForColumnIndex:1]; NSLog(@"%@ %@",name ,score); } 如果图片经过编码转换成data类型存入数据库取出来的方式如下; 1.从预处理中取出图片的二进制编码 NSData *data=[set objectForColumnIndex:1]; 2.创建存放图片的控件; UIImageView *image=[[UIImageView alloc]initWithFrame:CGRectMake(50, 300, 100, 100)]; 3.将数据转换成image添加到控件中; image.image=[UIImage imageWithData:data]; [self.view addSubview:image]; [db close]; } sdafggfdhfjgsdfhgjfgkhljkgjfhgfdsaDFGH 其他类型数据存入数据库 在数据库存储中,可以存储nsstring,nsnumber ,nsdata ;如果想储存其他类型的数字需要将其内容都转换成nsdata类型; 将image转换成data类型;然后通过获取data再将其转换成image类型: 1.创建image UIImage *image= [UIImage imageNamed:@"5.png" ]; 2.创建data用于存入数据; NSMutableData *data=[NSMutableData dataWithCapacity:0]; 3.创建编码器 NSKeyedArchiver *arch= [[NSKeyedArchiver alloc]initForWritingWithMutableData:data]; 4.编码图片; [arch encodeObject:image forKey:@"image"]; 5.完成编码 [arch finishEncoding]; 6.释放; [arch release]; 7.创建解码器 NSKeyedUnarchiver *unaarev=[[NSKeyedUnarchiver alloc]initForReadingWithData:data]; 8.解码图片; UIImage *image1=[unaarev decodeObjectForKey:@"image"]; 9.解码完成 [unaarev finishDecoding]; 10.释放 [unaarev release]; 11.展示图片 UIImageView * image2=[[UIImageView alloc]initWithFrame:CGRectMake(30, 300, 100, 100)];; image2.image=image1; [self.view addSubview:image2]; 聊天对话框的的气泡拉伸思想: 为了达到不矢真,横向延伸要用用竖向的一条像素按所需长度复制;竖向延伸要拿横向的一条像素按所需长度延伸; 具体实现: //聊天气泡拉伸 1.创建气泡 image =[UIImage imageNamed:@"5.png"] cap:帽子扩展延伸; 2。拉伸气泡函数 image=[image stretchableImageWithLeftCapWidth:14 topCapHeight:14]; image2.image=image; NSString *str=@"abcdet"; //得到str的尺寸; CGSize size=[str sizeWithFont:[UIFont systemFontOfSize:12.0] constrainedToSize:CGSizeMake(200, 1000) lineBreakMode:UILineBreakModeWordWrap]; 10.8 周一 向服务器上传数据 1.先添加第三方文件ASIHTTPRequst 导人第三方文件:#import "ASIFormDataRequest.h" 然后添加四个数据库文件 libz.1.2.5.dylib ,MobileCoreServices.framework, Systemconfiguration.framework;, CFNetwork.framework 2. 实现上传: 1.创建与服务器链接对象;//192.168 .88.8 局域网 获得局域网服务器的网址 NSURL *url=[NSURL URLWithString:@"http://169.254.59.31/pk.php"]; 2.创建向服务器发出请求的对象; ASIFormDataRequest *asiform=[ASIFormDataRequest requestWithURL:url]; 3.设置上传内容:上传内容可以是文件,也可以是二进制数据 一种函数 [asiform setFile:[[NSBundle mainBundle]pathForResource:@"5" ofType:@"jpg"] forKey:@"image"]; 第二种函数:[asiform setFile:[[NSBundle mainBundle]pathForResource:@"5" ofType:@"jpg"] withFileName:@"2.png" andContentType:@"image/jpg" forKey:@"image"]; 不同点:第二种会在服务器端显示你所设置的文件名,如果是二进制数据后者会显示类型,如果是图片会显示图片的缩略图,如果用第一种不能显示其缩略图; 4.设置代理,这样就可以使用其函数了;包括上传成功失败的函数 5.最后让其上传执行 [asiform startSynchronous]; -(void)viewDidLoad { [super viewDidLoad]; /* 网络接口路径 169.254.59.31/pk.php 图像上传 post 参数 图像 image 返回:不同内容代表不同的是否成功 {} */ //创建链接 NSURL *url=[NSURL URLWithString:@"http://169.254.59.31/pk.php"]; //创建数据请求 ASIFormDataRequest *asiform=[ASIFormDataRequest requestWithURL:url]; 1. [asiform setFile:[[NSBundle mainBundle]pathForResource:@"5" ofType:@"jpg"] forKey:@"image"]; 2. [asiform setFile:[[NSBundle mainBundle]pathForResource:@"5" ofType:@"jpg"] withFileName:@"2.png" andContentType:@"image/jpg" forKey:@"image"]; NSData *data=[NSData dataWithContentsOfFile:[[NSBundle mainBundle]pathForResource:@"5" ofType:@"jpg" ]]; //上传data类型的内容显示类型; [asiform setData:data forKey:@"image"]; //上传data类型以文件命名,在服务器端显示上传内容; [asiform setData:data withFileName:@"5.jpg" andContentType:@"image/jpg" forKey:@"image"]; asiform.delegate=self; [asiform startSynchronous]; } //用于提示上传是否成功或失败; -(void)requestFailed:(ASIHTTPRequest *)request { NSLog(@"error"); } -(void)requestFinished:(ASIHTTPRequest *)request { NSLog(@"ok"); } 10.9周二 mp3播放器制作 1.加载库文件 AVFoundation.framework和QuartzCore.framework;( 没弄明白这个文件的作用,因为加不加他没什么作用)然后引入头文件 #import <AVFoundation/AVFoundation.h> #import <QuartzCore/QuartzCore.h> 2.mp3实现代码 -(void)viewDidLoad { [super viewDidLoad]; //创建播放按钮,并分别为添加事件 UIButton *play=[UIButton buttonWithType:UIButtonTypeRoundedRect]; play.frame=CGRectMake(20, 100, 80, 30); [play addTarget:self action:@selector(play) forControlEvents:UIControlEventTouchUpInside ]; [play setTitle:@"play" forState:UIControlStateNormal]; [self.view addSubview:play]; UIButton *pause=[UIButton buttonWithType:UIButtonTypeRoundedRect]; pause.frame=CGRectMake(120, 100, 80, 30); [pause setTitle:@"pause" forState:UIControlStateNormal]; [pause addTarget:self action:@selector(pause) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:pause]; UIButton *stop=[UIButton buttonWithType:UIButtonTypeRoundedRect]; stop.frame=CGRectMake(220, 100, 80, 30); [stop addTarget:self action:@selector(stop) forControlEvents:UIControlEventTouchUpInside]; [stop setTitle:@"stop" forState:UIControlStateNormal]; [self.view addSubview:stop]; //创建数据链接 NSURL *url=[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:@"withyou" ofType:@"mp3"]]; player=[[AVAudioPlayer alloc]initWithContentsOfURL:url error:Nil]; //提前载入随时准备播放 [player prepareToPlay]; //创建滑条用于控制音量,声道和播放速率 UISlider *volslider=[[UISlider alloc]initWithFrame:CGRectMake(50, 50, 200, 0)]; //音量控制 volslider.minimumValue=0.0; volslider.maximumValue=1.0; //声道 volslider.minimumValue=-1.0; volslider.minimumValue=1.0; // 变速 player.enableRate=YES;// 开启加速功能; volslider.minimumValue=0.5; volslider.maximumValue=2.0; volslider.value=1.0; //为滑条添加滑动事件,注意出发事件是滑条值改便时; [volslider addTarget:self action:@selector(volslider:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:volslider]; [volslider release]; //创建进度条,控制音频播放进度 UISlider *proslider=[[UISlider alloc]initWithFrame:CGRectMake(50, 20, 220, 0)]; //设置进度条最大最小播放百分比 proslider.minimumValue=0.0; proslider.maximumValue=1.0; proslider.value=0.0; proslider.tag=100; [proslider addTarget:self action:@selector(progressSlider:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:proslider]; [proslider release]; //e ,j 是防止暂停,停止点击超过一次时多次释放timer导致崩溃 e=1; j=1; //设置代理 player.delegate=self; //设置音频频率显示条 for (int i=0; i<4; i++) { pro[i]=[[UIProgressView alloc]initWithFrame:CGRectMake(50*i, 440, 200, 0)]; [self.view addSubview:pro[i]]; [pro[i] release]; //旋转进度条,因为要的是弧度所以参数要改变成弧度制 pro[i].transform=CGAffineTransformMakeRotation(270 *M_PI/180); //设置铆点用于设置旋转围绕点; pro[i].layer.anchorPoint=CGPointMake(0.0, 0.0); } //音频可控用于进度条随音频变动 player.meteringEnabled=YES; } //播放完成时调用 -(void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag { NSLog(@"success"); } //进度条随音频改变 -(void)progressSlider:(UISlider *)slider { player.currentTime=player.duration*slider.value; } -(void)volslider:(UISlider *)slider { //声音大小控制 player.volume=slider.value; //声道控制 player.pan=slider.value; //播放速度控制 player.rate=slider.value; } //时间控制器调用的函数 -(void)refresh { UISlider *proslider=(UISlider *)[self.view viewWithTag:100]; proslider.value=player.currentTime/player.duration; [player updateMeters]; //刷新频率 pro[0].progress=[player peakPowerForChannel:0]/-100; pro[1].progress=[player peakPowerForChannel:1]/-100; pro[2].progress=[player averagePowerForChannel:0]/-100; pro[3].progress=[player averagePowerForChannel:1]/-100; } //播放控制 用添加时间器来控制 -(void)play { [player play]; timer=[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:@selector(refresh) userInfo:nil repeats:YES]; e=1; j=1; } //停止控制 注意e,j是分别用于控制停止按钮,暂停时间器释放,避免时间器重复释放导致的崩溃; -(void)stop { if (e==1&&j==1) { [player stop]; [timer invalidate]; //如果按停止键,控制进度条也停止 UISlider *proslider=(UISlider *)[self.view viewWithTag:100]; player.currentTime=0.0; proslider.value=player.currentTime; e=0; j=0; } else if(e==1&&j==0) { UISlider *proslider=(UISlider *)[self.view viewWithTag:100]; player.currentTime=0.0; proslider.value=player.currentTime; e=0; } } //控制暂停 -(void)pause { if (j==1&&e==1) { [player pause]; [timer invalidate]; j=0; } } -(void)dealloc { [player release]; [super dealloc]; } mp4播放器 1.导人库文件 MeduaPlayer.framework. 并导人头文件#import <MediaPlayer/MediaPlayer.h> 2. 代码实现解析 -(void)viewDidLoad { //创建按钮用于播放控制 UIButton *button=[UIButton buttonWithType:UIButtonTypeRoundedRect]; button.frame=CGRectMake(120, 400, 70, 40); [button addTarget:self action:@selector(buttonclick) forControlEvents:UIControlEventTouchUpInside]; //注意播放控制器又两种一种是播放控制器,MPMoviePlayerController 一种是带view的播放控制器;MPMoviePlayerViewController 二者的不同之处是前者要播放时是将其视图加入主控制视图中[self.view addSubview:play.view];,播放是调用播放函数[play play];后者是将播放控制交给MPMoviePlayerViewController:[self presentModalViewController:play animated:YES]; 这样一开始播放会全屏播放; //初始化MPMoviePlayerViewControlle,资源是当前文件 play1=[[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:@"4" ofType:@"mp4"]]]; // play=[[MPMoviePlayerViewController alloc]initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:@"3" ofType:@"mp4"]]]; //初始化MPMoviePlayerController 资源是当前文件 play=[[MPMoviePlayerController alloc]initWithContentURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:@"4" ofType:@"mp4"]]]; //设置播放器的 frame属性 play.view.frame=CGRectMake(0, 0, 320, 300); //UIImageView *image= [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"1.bmp"]]; //设置播放器背景色,虽然能设置,但是不支持使用此属性; play.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:@"1.bmp"]]; //播放器的控制属性,用于控制播放模式默认使嵌入模式; play.controlStyle=MPMovieControlStyleEmbedded; //播放重复模式,可以用于设置重复播放; play.repeatMode=MPMovieRepeatModeOne; [self.view addSubview:play.view]; // play.allowsAirPlay=NO; [self.view addSubview:button]; } //控制播放器播放; -(void)buttonclick { [self presentModalViewController:play animated:YES]; [play play]; } 10.11周四 画图 1.画图工具要新建一个uiview文件 然后在这个文件的.m文件中的- (void)drawRect:(CGRect)rect函数中画图 2.画各中图的方法 //图片的绘制 UIImage* image = [UIImage imageNamed:@"5.png"]; [image drawInRect:CGRectMake(100, 100, 100, 100)]; // 文字 NSString* str = @"ABC"; [str drawInRect:CGRectMake(100, 100, 100, 50) withFont:[UIFont systemFontOfSize:30.0] lineBreakMode:UILineBreakModeClip alignment:UITextAlignmentLeft]; //画直线 创建画纸 CGContextRef ref = UIGraphicsGetCurrentContext(); 画起点: CGContextMoveToPoint(ref, 20, 100); 添加点 CGContextAddLineToPoint(ref, 300, 100); CGContextAddLineToPoint(ref, 150, 300); 封闭图形 CGContextClosePath(ref); //线条颜色 CGContextSetStrokeColorWithColor(ref, [UIColor blueColor].CGColor); 画路径 结束画图 CGContextStrokePath(ref); //线宽 CGContextSetLineWidth(ref, 20.0); //虚线 float length[] = {40,20,40}; CGContextSetLineDash(ref, 0, length, 2); //注意:参数二是从多少像素开始; 参数三是用于实线和间隔循环的数组; 参数四是用于要去数组的前几个数循环; //线段的样式 CGContextSetLineCap(ref, kCGLineCapSquare); //线段连接处的连接样式 CGContextSetLineJoin(ref, kCGLineJoinRound); CGContextStrokePath(ref); //矩形 CGContextRef ref = UIGraphicsGetCurrentContext(); //设置矩形的fram CGContextAddRect(ref, CGRectMake(100, 100, 200, 100)); //设置线宽 CGContextSetLineWidth(ref, 10.0); //设施线的颜色 CGContextSetStrokeColorWithColor(ref, [UIColor greenColor].CGColor); //设置填充色; CGContextSetFillColorWithColor(ref, [UIColor blueColor].CGColor); //注意下面的三个生成图像的方法的不同点 1.第一个只画轮廓 //CGContextStrokePath(ref); 2.只填充图像的内部,不现实边框 //CGContextFillPath(ref); 3.边框和填充都显示,注意后面的参数式fill和stroke都有的,一般fill是内部填充的属性,而stroke是线的属性 CGContextDrawPath(ref, kCGPathFillStroke); //圆 CGContextRef ref = UIGraphicsGetCurrentContext(); 设置圆的框架大小 CGContextAddEllipseInRect(ref, CGRectMake(100, 100, 200, 100)); CGContextStrokePath(ref); CGContextRef ref = UIGraphicsGetCurrentContext(); 画自由圆 设置圆心位置 CGContextMoveToPoint(ref, 150, 150); 画圆,第二,三个 是圆心位置,第四个参数是半径 第五,六个参数数是开始和结束的角,角是弧度制,最后一个参数是顺时针和逆时针旋转1表示顺时针,而表示逆时针 CGContextAddArc(ref, 150, 150, 100, 0, 270 * M_PI / 180, 1); 设置图形填充色 CGContextSetFillColorWithColor(ref, [UIColor purpleColor].CGColor); 填充图形; CGContextFillPath(ref); 重新设置圆点 ,相当于在新的图层上画图,这样可以为每个图形设置不同的颜色; CGContextMoveToPoint(ref, 150, 150); CGContextAddArc(ref, 150, 150, 100, 0, 120 * M_PI / 180, 0); CGContextSetFillColorWithColor(ref, [UIColor orangeColor].CGColor); CGContextFillPath(ref); CGContextMoveToPoint(ref, 150, 150); CGContextAddArc(ref, 150, 150, 100, 120 * M_PI / 180, 270 * M_PI / 180, 0); CGContextSetFillColorWithColor(ref, [UIColor blueColor].CGColor); CGContextFillPath(ref); //画曲线 CGContextRef ref = UIGraphicsGetCurrentContext(); 设置初试点 CGContextMoveToPoint(ref, 20, 400); 画曲线 第二,三个参数是曲线始末两点切线的焦点坐标;后两个参数是末点的坐标; CGContextAddQuadCurveToPoint(ref, 0, 100, 300, 400); CGContextStrokePath(ref); //设置图形的透明度和阴影 CGContextRef ref = UIGraphicsGetCurrentContext(); CGContextAddRect(ref, CGRectMake(100, 100, 150, 150)); CGContextSetLineWidth(ref, 10.0); CGContextSetStrokeColorWithColor(ref, [UIColor blueColor].CGColor); CGContextSetFillColorWithColor(ref, [UIColor redColor].CGColor); //设置图形的透明度 CGContextSetAlpha(ref, 0.5); //设置图形阴影 第二个参数是阴影向又向下的偏移量 ,最后一个参数是羽化程度 CGContextSetShadow(ref, CGSizeMake(20, 20), 10); CGContextDrawPath(ref, kCGPathFillStroke); 动画效果总结 1.以前给uiview 添加动画效果; // [UIView beginAnimations:nil context:nil]; // [UIView setAnimationDuration:1]; // //设置动画快慢 设置动画的方向 // [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; // [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1]; // [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES]; // [UIView setAnimationDelegate: self]; 设置动画各阶段的调用的函数; // [UIView setAnimationWillStartSelector:@selector(start)]; // [UIView setAnimationDidStopSelector:@selector(stop)]; // [UIView commitAnimations]; CATransition 用时要导人库文件QuartzCore.framework 在加入头文件#import <QuartzCore/QuartzCore.h> 初始化 CATransition *trans=[CATransition animation]; 设置动画时间; trans.duration=1.0; 设置动画进入曲线 trans.timingFunction=UIViewAnimationCurveEaseInOut; 设置动画的类型 类型可以直接用字符串;类型为: 1. 1. pageCurl 向上翻一页 2. pageUnCurl 向下翻一页 3. rippleEffect 滴水效果 4. suckEffect 收缩效果,如一块布被抽走 5. cube 立方体效果 6. oglFlip 上下翻转效果 trans.type=@"rippleEffect"; 动画进入类型 // trans.type=kCATransitionFromLeft; trans.subtype=kCATransitionFromTop; 设置次动画; // trans.subtype=kCATransitionFromBottom; 设置动画代理 trans.delegate=self; //动画从多少开始;是整个动画的播放百分比 //trans.startProgress=0.5; //动画结束动画从多少结束 //trans.endProgress=0.8; [self.view.layer addAnimation:trans forKey:nil]; [self.view exchangeSubviewAtIndex:0 withSubviewAtIndex:1]; } -(void)animationDidStart:(CAAnimation *)anim { NSLog(@"strat"); } -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag { //flag 得值表示本次动画是否执行完了 NSLog(@"stop %d",flag); } 注:CATransition动画只能在图层上加,所以要切换页view时也要加到view.layer上;如在切换控制器时做法self.navigationController.view.layer addAnimation:tran forKey:nil]; [self.navigationController pushViewController:rvc animated:NO]; 其中animated的yes或no没关系; 10.12日 地图 1.创建地图需要添加库文件:CoreLocation.framework //服务的 定位的 库文件 MapKit.framework 然后添加创建头文件地图类#import <MapKit/MapKit.h> 因为用到了类的代理函数需添加协议 <CLLocationManagerDelegate,MKMapViewDelegate> 2.代码实线 创建两个类 MKMapView *map; CLLocationManager *localmanager; -(void)viewDidLoad { //创建地图 map=[[MKMapView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; [self.view addSubview:map]; //定位经纬 CLLocationCoordinate2D coordinate=CLLocationCoordinate2DMake(40.035731, 116.351008); //范围 显示比例 越小越精确 MKCoordinateSpan span=MKCoordinateSpanMake(0.5, 0.5); 将经纬度和显示比例添加到 原始方位中,当打开地图时地图上显示此位置; MKCoordinateRegion region=MKCoordinateRegionMake(coordinate, span); map.region=region; //设置地图的显示类型,卫星图,普通地图,修改过的卫星图; //map.mapType=MKMapTypeSatellite; //map.mapType=MKMapTypeHybrid; //设置map代理 map.delegate=self; //创建位置管理对象; localmanager=[[CLLocationManager alloc]init]; // 地图显示精确度。越精确越费电 localmanager.desiredAccuracy=kCLLocationAccuracyBest; //移动100米更新位置一次 localmanager.distanceFilter=100; [localmanager startUpdatingLocation]; localmanager.delegate=self; //添加大头针 大头针类是单独的文件;是普通的继承nsobject文件 用还需添加代理 <MKAnnotation> 实线代理类中的函数 //设置标题 -(NSString *)title { return @"标题"; } //设置副标题 -(NSString *)subtitle { return @"副标题"; } //设置将大头针插到的位置; -(CLLocationCoordinate2D)coordinate { CLLocationCoordinate2D cooridinate=CLLocationCoordinate2DMake(40.035731, 116.351008); return cooridinate; } 为了能多插入几个大头针可以更改他们的属性,位置,我们可以创建一个初始化函数,通过创建不同的对象,实现多大头针; -(id)initWithTitle:(NSString *)title subTitle:(NSString *)subtitle coordinate:(CLLocationCoordinate2D)coordinate { self=[super init]; if (self) { _title=title; _subtitle=subtitle; _coordinate=coordinate; 这三个参数都是自定义属性;在返回函数中可以直接分别返回这几个属性 } return self; } 回到根控制文件创建大头针,用自定义初始化函数初始化大头针; MyAnnotion *myann=[[MyAnnotion alloc]initWithTitle:@"标题" subTitle:@"副标题" coordinate:coordinate]; 给地图添加大头针 [map addAnnotation:myann]; 创建一个长压手势,在手势函数中 UILongPressGestureRecognizer *press=[[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longpress:)]; 给地图添加手势 [map addGestureRecognizer:press]; [map release]; } 长按触发的手势函数; -(void)longpress:(UILongPressGestureRecognizer *)press { 为了防治一直按键不断的产生大头针 要对按键状态进行判断,只有第一次长按才添加大头针 if (press.state==UIGestureRecognizerStateBegan) { CGPoint piont=[press locationInView:self.view ]; CLLocationCoordinate2D coordinate=[map convertPoint:piont toCoordinateFromView:map]; MyAnnotion * annontion=[[MyAnnotion alloc]initWithTitle:@"title" subTitle:@"subtite" coordinate:coordinate]; //为大头针出现时添加动作; [map addAnnotation:annontion]; } } //这是地图的协议方法 //自定义大头针 -(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { //为了节省内存创建大头针队列,只生成能看见的大头针; MKPinAnnotationView *pinView=(MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"ID"]; //判断是否是用户定义;为了防治把系统的定位标志也改成大头针样式,由于是定位,定位时刻进行,所以回不断的产生大头针,和我们自己定义的大头针没有了区分 if ([annotation isKindOfClass:[mapView.userLocation class]]) { return nil; } if(pinView ==nil){ //创建大头针使用我们定义加入地图的大头针; pinView=[[[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"ID"]autorelease]; } //展示标题 pinView.canShowCallout=YES; //设置动画 pinView.animatesDrop=YES; //设置针头颜色 pinView.pinColor=MKPinAnnotationColorPurple; 创建视图用于添加到大头针细节视图中 UIView *leftview=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 20, 20)]; leftview.backgroundColor=[UIColor greenColor]; pinView.leftCalloutAccessoryView=leftview; //添加按钮用于添加到大头针视图细节的右面; UIButton *button=[UIButton buttonWithType:UIButtonTypeDetailDisclosure]; pinView.rightCalloutAccessoryView=button; return pinView; } //定位函数 -(void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { 把用户的位置属性设为yes来展示用户的位置; map.showsUserLocation=YES; 设置显示比例 MKCoordinateSpan span=MKCoordinateSpanMake(0.5, 0.5); 创建原始位置属性,此时经纬可以用函数的参数来设置,当前所处的位置; MKCoordinateRegion region=MKCoordinateRegionMake(newLocation.coordinate, span); 动画添加位置 [map setRegion:region animated:YES]; 更新位置 [localmanager startUpdatingLocation]; } 游戏开发 cocos2d oc cocos2d-x( 中国人维护 不如cocos2d多) 2d-x c++ cocos2d-android java cocos2d-html5 cocos2d-flash cocos2d流程:和电影流程差不多 游戏开始: 1。初始化 libs:游戏引擎; 加库:opencles.framework(计算机图形学) 注:gpu:是数 注意:选择白库时选最短得 plist图片要和png图片名称相同 注:在游戏当中一定要注意产生对象的释放;因为内容比较多,如不释放内存泄漏非常严重; 游戏一:发射打击; 1。加载所需文件: openal.framework ,openGLES.framework,quartacore.framework,audiotoolbox.faramework,avfoundation.framwork,libz.dylib; 添加libs文件cocos2d包,再加上所需图片和音乐; 2.游戏界面只有一个导演,一个舞台,每个界面相当于一个节目;界面切换靠的是导演指导哪个节目上场;每个节目上要添加层靠曾来展示内容; 具体操作是: 1.创建导演,并判断是否能运行最新的导演 BOOL ret = [CCDirector setDirectorType:kCCDirectorTypeDisplayLink]; //这是功能比较强大的导演; if (ret == FALSE) { [CCDirector setDirectorType:kCCDirectorTypeDefault]; CCDirector *director = [CCDirector sharedDirector]; //创建导演,他是个共享函数,程序始终只有一个导演; 这个导演适于所有版本的系统; 2.创建舞台 CGRect rect = self.window.bounds;//得到舞台的尺寸 创建舞台view EAGLView *glView = [[EAGLView alloc] initWithFrame:rect] 3. 导演让屏幕横屏 [director setDeviceOrientation:kCCDeviceOrientationLandscapeLeft]; // 设置屏幕为 风景 // kCCDeviceOrientationLandscapeLeft // 竖屏 Portrait 肖像 4. 关联导演和glview // 让导演知道哪里是舞台 [director setOpenGLView:glView]; 5. 设置游戏刷新率 // 刷新周期 60HZ // [director setAnimationInterval:1/60]; [director setAnimationInterval:1/60.0f]; 6.把舞台添加到窗口 [self.window addSubview:glView]; [glView release]; // glview计数器是多少 2 7.运行第一个节目 CCScene *s = [StartLayer scene]; 调用start layer的类函数用于切换节目 [StartLayer scene] 的类函数要些在StartLayer中方便使用 [director runWithScene:s]; 让导演运行第一个节目; 在运行一个节目时需要注意的点: 1。创建切换节目的类函数; + (id) scene { CCScene *s = [CCScene node]; CCLayer *l = [StartLayer node]; [s addChild:l]; return s; } node函数是继承node的 初始化函数是[[[self alloc] init] autorelease];用这个函数比较简便;但是初始化时如果对象就以两个可以这样初始化;如果对象很多就不要这样初始化;因为自动释放时间不确定容易占用内存; 2.初始化层; 注:一开始加载的东西要放在初始化中; 创建菜单 CCMenuItemFont *startItem = [[CCMenuItemFont alloc] initFromString:@"开始游戏" target:self selector:@selector(beginGame)]; CCMenuItemFont是文字菜单项;有图片菜单项,文本项等等 点击菜单项都会出发事件;点击开始游戏菜单项就要出发新节目;在出发函数中要 CCMenuItem *helpItem = [[CCMenuItemFont alloc] initFromString:@"帮助" target:self selector:@selector(helpGame)]; // CCMenuItemFont创建一个菜单项 // cocos2d CCMenu *menu = [CCMenu menuWithItems:startItem, helpItem, nil]; 创建菜单,同时加入菜单项; [menu alignItemsVertically]; // menuitem竖直对齐 // NSArray [self addChild:menu]; // 把menu加入到self // addChild: 类似addSubview: 点击菜单项都会出发事件;点击开始游戏菜单项就要出发新节目;在触发函数中要要切换节目 2.创建新节目: CCScene *s = [LoadingLayer scene];//这个函数同样是类函数, // 第2个 任何地方都是这样 CCDirector *d = [CCDirector sharedDirector];获取导演; // s 1 [d replaceScene:s]; 让新节目代替旧节目; 这个函数的好处是把旧节目释放;不再占用内存 // [s release]; // 把当前剧场删掉 然后用新的剧场s // 不遵守规矩 // 在LoadingLayer alloc 在StartLayer中release 登陆节目: 节目同样要些创建节目的类函数,和上面的写法一样 登陆时显示的是一个进度条;通过扩大其中一个进度条的长度来模仿数据加载; 初始化函数: 在cocos2d中的精灵相当于ui中的图片 CCSprite *redSprite = [[CCSprite alloc] initWithFile:@"progressbar1.png"]; // 用图片progressbar1.png来创建一个精灵 CCDirector *d = [CCDirector sharedDirector]; CGSize winSize = [d winSize]; // 取得屏幕当前的宽高 设置锚点;锚点相当于图片的基准点; redSprite.anchorPoint = ccp(0, 0); CGSize redSpriteSize = [redSprite contentSize]; // 取得精灵自己的宽高 CGFloat x = (winSize.width-redSpriteSize.width)/2.0f; CGFloat y = (winSize.height-redSpriteSize.height)/2.0f; 设置精灵的位置; redSprite.position = ccp(x, y); // redSprite.position = ccp(winSize.width/2, winSize.height/2); // 指定它中心位置 // 设置锚点在父视图中的坐标 将精灵添加到图层; [self addChild:redSprite]; [redSprite release]; 注意局部对象及时的销毁; yellowSprite = [[CCSprite alloc] initWithFile:@"progressbar2.png"]; // yellowSprite.position = ccp(winSize.width/2, winSize.height/2); yellowSprite.anchorPoint = ccp(0, 0); yellowSprite.position = ccp(x, y); //scale是缩放的意思;可以对整体缩放,也可以缩放x和y; yellowSprite.scaleX = 0.2f; yellowSprite.tag = 100; [self addChild:yellowSprite]; // [NSTimer scheduledTimerWithTimeInterval:<#(NSTimeInterval)#> target:<#(id)#> selector:<#(SEL)#> userInfo:<#(id)#> repeats:<#(BOOL)#> //图层也可以添加计时器;不用再创建timer; [self schedule:@selector(timer:) interval:0.5f]; // 每隔0.5s来调用self timer: 每隔0。5秒调用的函数; - (void) timer:(double)dt { // CCSprite *yellowSprite = (CCSprite *)[self getChildByTag:100]; // getChildByTag:100根据100tag来找ccnode // 如果有就返回 否则 nil // 取得s的在x上的放大比例 < 1 缩小 CGFloat scalex = [yellowSprite scaleX]; scalex += 0.1f; [yellowSprite setScaleX:scalex]; if (scalex >= 1.0f) { // 取消定时器 [self unschedule:@selector(timer:)]; [[CCDirector sharedDirector] replaceScene:[GameLayer scene]]; } } 游戏界面 游戏界面同样是通过类函数创建节目;在初始化函数种需要做的工作是加载背景图,和游戏者。创建随时间调用的函数; CCSprite *bgSprite = [[CCSprite alloc] initWithFile:@"bg.png"]; bgSprite.anchorPoint = ccp(0, 0); bgSprite.position = ccp(0, 0); [self addChild:bgSprite]; [bgSprite release]; // 放一个人 CCSprite *player = [[CCSprite alloc] initWithFile:@"Player.png"]; CGSize playerSize = [player contentSize]; CGSize winSize = [[CCDirector sharedDirector] winSize]; player.position = ccp(playerSize.width/2.0f, winSize.height/2.0f); [self addChild:player]; [player release]; tagetarray=[[CCArray alloc]init]; bulletarray=[[CCArray alloc]init]; [self addTarget]; [self schedule:@selector(targetTimer:) interval:1.0f]; [self schedule:@selector(gameLogic)]; // 如果不写多长时间调用就是每隔1/60.0f 秒调用 // 缺省touch是关闭的 self.isTouchEnabled = YES; 发子弹需要触摸所以要让屏幕可触摸; 创建打击目标调用的函数; -(void)addTarget { 创建精灵; CCSprite * taget=[[CCSprite alloc]initWithFile:@"Target.png"]; 将精灵添加到数组;用于测试是否被子弹打中; [tagetarray addObject:taget]; CGSize winsize=[[CCDirector sharedDirector] winSize]; CGSize tagetsize=[taget contentSize]; 通过随机数获设置精灵的随机高度;注:随机数很大通过取余来控制随机数的范围; CGFloat y= tagetsize.height/2.0f+ arc4random()%(int)(winsize.height-tagetsize.height); CGFloat x=winsize.width; taget.position=ccp(x,y); [self addChild:taget]; [taget release]; CGPoint dispoint=ccp(0, y); 设置动作点,精灵会在设置的时间内从起点运动到目地点; CCMoveTo *move=[[CCMoveTo alloc]initWithDuration:2 position:dispoint]; CGPoint destpoint2=ccp(300,0 ); 动作点可设置跳跃点 CCJumpTo *move2=[[CCJumpTo alloc]initWithDuration:2 position:destpoint2 height:200 jumps:1]; 用来调用某个函数;一般是用来做善后工作; CCCallFuncN *finish= [[CCCallFuncN alloc]initWithTarget:self selector:@selector(finish:)]; 创建队列,调用者会按队列顺序执行; CCSequence *squence=[CCSequence actions:move,move2,finish, nil]; 让对象按队列运行; [taget runAction:squence]; [move2 release]; [move release]; } 触摸函数用于添加子弹;注意触摸函数的写法;函数touch后带es的和ui的触摸函数一样 -(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { 创建音乐引擎; [[SimpleAudioEngine sharedEngine] playEffect:@"pew-pew-lei.caf"]; CCSprite *bulletsprite=[[CCSprite alloc]initWithFile:@"Bullet.png"]; bulletsprite.tag=10; 创建触摸对象 UITouch *onetouch=[touches anyObject]; 获取触摸对象的位置; CGPoint touchpoint=[onetouch locationInView:onetouch.view ]; //注意获取的触摸点时竖屏时的所以得把该点转换成游戏横屏时的触摸点; CGPoint glpoint=[[CCDirector sharedDirector]convertToGL:touchpoint]; CGFloat y=[[CCDirector sharedDirector]winSize].height/2.0f; bulletsprite.position=ccp(20,y); [self addChild: bulletsprite]; CCMoveTo * move=[[CCMoveTo alloc]initWithDuration:1 position:glpoint]; int i=480/glpoint.x; CGPoint point=ccp(490, glpoint.y*i); //int time=sqrt(glpoint.x*glpoint.x+glpoint.y*glpoint.y)*sqrt((480-glpoint.x)*(480-glpoint.x)+(glpoint.y*i)*(glpoint.y*i)); CCMoveTo *move2=[[CCMoveTo alloc]initWithDuration:1 position:point]; CCCallFuncN *finish=[[CCCallFuncN alloc]initWithTarget:self selector:@selector(finish:)]; 把子弹添加到数组;用于判断是否打中目标; [bulletarray addObject:bulletsprite]; CCSequence *sequence=[CCSequence actions:move,move2,finish, nil]; [bulletsprite runAction:sequence]; [bulletsprite release]; [move release]; // [finish release]; } 判断是否大中目标的函数;用循环数组比较比较范围来获取; -(void)gamelogic { for (CCSprite* bullet in bulletarray) { // NSLog(@"%@",bulletarray); CGSize buletsize=[bullet contentSize]; for (CCSprite *taget in tagetarray) { CGSize tagetsize=[taget contentSize]; float x1=buletsize.width; float x2=tagetsize.width; float max=x1*0.4f+x2*0.4f; CGFloat lon =ccpDistance(bullet.position,taget.position ); 通过比较接触范围来判断是否打中; if (lon<=max) { //停止动画函数;在这里没有什么作用; [taget stopAllActions]; [bullet stopAllActions]; 调用释放函数; [self finish:taget]; [self finish:bullet]; return; } } } } -(void)addTarget 从屏幕上释放精灵; -(void)finish:(CCNode *)node { 由于数组中添加了对象,释放时也要从数组中去除; if (node.tag==10) { [bulletarray removeObject:node]; } else [tagetarray removeObject:node]; [node removeFromParentAndCleanup:YES]; } 做游戏地图 要学习 : tieldmap:地图编译器 opengl Box2D 物理引擎 网络:http gel post1 http post2 weibo分享 腾讯微博,uauth2 协议 domain 协议:1.http:// 2.ftp:// 3. baidu.com是真正的域名; www.baidu.com是一台机器是二级域名 参数间用&隔开,参数名=参数值 http://www.baidu.com 是缺省的 http://www.baidu.com /index.html/ 网络访问模式 客户端 发出请求 apache2 调用 访问程序 要点: 网络请求处理 nignx(大量连接时), httplight(联接少的时候),apache2 服务器默认路径是/library/web server/document / document 是放网页的文件夹 读取这个目录下的iOS1时写法:http://localhost/iOS1 XXXX.CGi 是服务器程序 cgi-executables 是放可执行程序的文件 在服务器访问中映射是cgi-bin 访问时写成http://localhost/cgi-bin/iOS post1真实名字是:application/x-www-form-urlencoded 功能强大顺序; post2>post1>get 他们都是上行协议;都是客户端传给服务器端的, 而服务器传给客户端的没有区分也叫响应; 什么时get协议: 在网址上写的直接回车能出来的是get协议 get 时传入到网上的东西.又可以定义为只有请求头没有请求体的请求, 入网址是http://api.douban.com/cgi-bin?srlaction=232 发到网上的时 只有请求头: get : /cgi-bin?srlaction=232\r\n 请求路径和内容 host:api.douban.com\r\n 请求机器 \r\n :请求头的结束标志; post1 发送格式: 请求头: post /cgi-bin/get.cgi\r\n 请求路径 host:localhost\r\n 请求的机器 content-type:application/x-www-form-unlencoded\r\n 请求协议:post1 content-length :78\r\n 请求体长度 r\n 请求体: srclatitude=40.02999&srclongitude=116.3466 get 缺陷:1.网址不可太长<1024 2.不能带密码; 3.不能传文件 post1特点:1.网址小于4g 2.可一带密码; read(0,input ,lengthjl) :0 指从apache2中读数据 套接字:socket tcp:用在稳定的连接:可靠的,速度快 用于:图片,录音,文字 udp不可靠的网络连接;非常快, 用于:视频,文件,文字 tcp:网络传输; 传输思想: 1.服务器端: 1.生成服务器并并设置监听接口 2.在代理的确实接收到套接字函数中 要调用等待读取函数;这里的等待不是新建立的套接字等待而是让服务器底层新开一个线程等待传人数据; 3.在代理的确实接收到数据函数中取得接收到的数据,同时要在建立等待接收数据,等待下一次传输;这时的tag还用先前的;因为tcp网络传输一次建立联系,后面就无须在建立联系;所以省去再和服务器建立联系这个环节; 2.客户端: 1.生成客户端套接字 ; 2. 连接服务器,并设置网络接入入口 3.调用代理的以服务器建立连接成功函数。在这里吧连接开关设置为已连连接 4.将数据发送到服务器 - (void) createServer { allClientSockets = [[NSMutableArray alloc] init]; serverSocket = [[AsyncSocket alloc] initWithDelegate:self]; [serverSocket acceptOnPort:0x1234 error:nil]; // serverSocket在端口0x1234来等待 // 也是异步的bind端口 // serverSocket自动会在0x1234上等待有人来连接我 } - (void) onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket { // 只要有人来连接我 这个函数就会被调用 // newSocket就是系统自动创建的 socket // 如果有10个人连接端口 0x1234那么这个函数就会执行10次 // newSocket // newSocket是自动autorelease NSLog(@"new connection is coming new %@",newSocket); [allClientSockets addObject:newSocket]; int index = [allClientSockets indexOfObject:newSocket]; [newSocket readDataWithTimeout:-1 tag:index+100]; // newSocket来告诉系统来接收到达newSocket的数据 // -1 一直等待 100 表示 // 异步读取数据 } - (void) onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag { int index = [allClientSockets indexOfObject:sock]; NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; recvMsgView.text = [NSString stringWithFormat:@"%@\n%@", recvMsgView.text, s]; [s release]; // 继续发起一个读的操作 [sock readDataWithTimeout:-1 tag:tag]; } #pragma mark - #pragma mark Client Part - (void) createClient { clientSocket = [[AsyncSocket alloc] initWithDelegate:self]; isConnected = NO; } - (void) connectToHost:(NSString *)ip { static int index; if (index++) return; // 异步连接ip:0x1234的机器 [clientSocket connectToHost:ip onPort:0x1234 withTimeout:10 error:nil]; // 还不知道到底有没有连接成功 } - (void) onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port { NSLog(@"已经连接上了 %@:%d", host, port); isConnected = YES; } - (void) sendMessage:(id)arg { NSString *ip = ipField.text; // 192.168.1.23 api.douban.com NSString *msg = msgField.text; NSData *msgData = [msg dataUsingEncoding:NSUTF8StringEncoding]; /* 1. 文字 2. 图片 3 图片+文字 4 文字+语音 // 文字 1 图片 2 语音 3 type: 1 subtype: 1 len : 文字内容 type:2 subtype:2 len: 10240 图片内容 type:3 subtype:1 len:100 文字内容 subtype:2 len:200000 图片内容 type:4 subtype:3 len:1000000 语音内容 subtype:1 文字 */ // 端口 // 第一次发数据就来调用 连接 // 第二次之后就不用连接了 [self connectToHost:ip]; if(isConnected == YES) { [clientSocket writeData:msgData withTimeout:10 tag:111]; // 给clientsocket发送数据 msgData, } else { } } - (void) onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag { // 一旦发送成功 该函数就会得到调用 if (tag == 111) { } } udp 网络传输 基本思想: 1。接收端端: 1.创建接收端套接字; 2.绑定网络端口 3.等待接收数据; 4.调用代理接收到数据的函数;取出数据,并开始调用等待函数等待下次数据传输; 2. 发送端 1.创建发送端套接字 2.得到接收端的ip和接收数据的网络端口;将数据发送到该地址; 3.通过是否发送成功函数通过判断返回的tag值来判断是否发送成功; - (void)viewDidLoad { [super viewDidLoad]; ipField = [[UITextField alloc] initWithFrame:CGRectMake(50, 10, 200, 30)]; ipField.borderStyle = UITextBorderStyleRoundedRect; [self.view addSubview:ipField]; msgField = [[UITextField alloc] initWithFrame:CGRectMake(50, 50, 150, 30)]; msgField.borderStyle = UITextBorderStyleRoundedRect; [self.view addSubview:msgField]; UIButton *b = [UIButton buttonWithType:UIButtonTypeRoundedRect]; b.frame = CGRectMake(220, 50, 80, 30); [b setTitle:@"发送" forState:UIControlStateNormal]; [b addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:b]; recvMsgView = [[UITextView alloc] initWithFrame:CGRectMake(10, 100, 300, 250)]; recvMsgView.backgroundColor = [UIColor groupTableViewBackgroundColor]; [recvMsgView setEditable:NO]; [self.view addSubview:recvMsgView]; // 1. 创建接收socket recvMsgSocket = [[AsyncUdpSocket alloc] initWithDelegate:self]; // 2. 接收的对象要负责绑定bind到本机的一个port [recvMsgSocket bindToPort:0x1234 error:nil]; // recvMsgSocket只能接收 本机的端口为0x1234的数据包 // 192.168.1.11:0x1234 // 什么时候绑定成功 // 3. 接收数据 [recvMsgSocket receiveWithTimeout:-1 tag:200]; //-1 表示让让服务器无限等待,去接受数据;如是正数就表示让服务器等待多长时间去接收数据; // 这个函数不会blocked // 这个函数不会亲自阻塞 // 操作系统来等 10 // 告诉系统接收一次 // 4. ? 数据什么时候来了 recv2 = [[AsyncUdpSocket alloc] initWithDelegate:self]; [recv2 bindToPort:0x1235 error:nil]; // [recv2 receiveWithTimeout:-1 tag:201]; // 1. 创建发送套接字 只是创建一次 senderUdpSocket = [[AsyncUdpSocket alloc] initWithDelegate:self]; // [senderUdpSocket bindToPort:9876 error:nil]; // 发送一方绑定端口是没有意义的 // [senderUdpSocket bindToPort:0x7654 error:nil]; //对于senderUdpSocket如果没有调用bindToPort那么系统会自动给你选择一个没用的随机的端口 } - (BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port { if (tag == 200) { // 证明端口0x1234上有数据来了 // data对方传过来的数据 // host表示是谁传给我的 port不是0x1234是发送方的端口 // host:port是对方的端口和ip // tag就是200 NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSString *s2 = [NSString stringWithFormat:@"%@:%d %@", host, port, s]; [s release]; recvMsgView.text = [NSString stringWithFormat:@"%@\n%@", recvMsgView.text, s2]; [recvMsgSocket receiveWithTimeout:-1 tag:200]; } return YES; } - (void) sendMessage:(id)arg { NSString *ip = ipField.text; // 192.168.1.23 api.douban.com NSString *msg = msgField.text; NSData *msgData = [msg dataUsingEncoding:NSUTF8StringEncoding]; // 端口 short port = 0x1234; // 给ip:port发送消息msg [senderUdpSocket sendData:msgData toHost:ip port:port withTimeout:10 tag:100]; // 给ip地址的机器上的一个端口port 发送消息msgData // 10 timeout 超时 失败 // tag 100 表示本次数据包 // sendData:该函数不会blocked // 该函数不会负责真正的发送 // 只会告诉系统我要发送 tag=100的数据包msgData NSLog(@"aa"); } - (void) onUdpSocket:(AsyncUdpSocket *)sock didSendDataWithTag:(long)tag { // 名字为tag的数据包已经发送完成 if (tag == 100) { NSLog(@"数据包100已经发送成功"); } } 广播:又叫消息,观察者,通知 ARC:内存自动管理 不须要release; 2。不用[super dealloc] 3.不能用aotorelease; 单例:一个对象,一个全局对象; 1.写一个单例 2.单例什么时候释放;不用释放,因为时全局变量 3。如何避免实例化 :将init alloc 函数返回空; 单例命名规则:currentxxxxx, sharedxxxx, aplication xxx arrayWithContentOfFile: 数组解析文件的方法 //创建三个分栏控制器 UITabBarItem *barItem1=[[UITabBarItem alloc]initWithTitle:@"首页" image:[UIImage imageNamed:@"关于.png"] tag:0]; self.vc01.tabBarItem=barItem1; //消息图标 self.vc01.tabBarItem.badgeValue=@"3";//badgeValue是一个属性,指的是消息的提示 self.vc02.tabBarItem.badgeValue=nil;//这样就显示为空 [barItem1 release]; //系统UITableBarItem的图标 UITabBarItem *barItem2=[[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemMostViewed tag:1]; self.vc02.tabBarItem=barItem2; [barItem2 release]; //系统UITableBarItem的图标 UITabBarItem *barItem3=[[UITabBarItem alloc]initWithTabBarSystemItem:UITabBarSystemItemFeatured tag:3]; self.vc03.tabBarItem=barItem3; [barItem3 release]; //将三个视图控制器装入到数组中 // NSArray *arrayVC=[NSArray arrayWithObjects:_vc01,_vc02,_vc03 nil]; NSArray *arrayVC=[NSArray arrayWithObjects:self.vc01,self.vc02,self.vc03, nil]; //将控制器赋给tabBarControl UITabBarController *tabBar=[[UITabBarController alloc]init]; //接收数组viewControllers tabBar.viewControllers=arrayVC; //将tabBar设置根视图控制器 self.window.rootViewController=tabBar; [arrayVC release]; 只要是添加的视图控制器 或是什么管理器的 话 都是加载 根视图控制器rootViewController上面 加上UIlable UIButton view等等都是直接添加到window或是view上面的 addSubview方法 //添加图片视图,视图用addSubview方法来添加 特别是视图 [sv addSubview:imageView]; //在视图上面添加图片的一般方法; for (int i=0; i<9; i++) { //获取每一个图片的 文件名 并且转化成字符串 NSString *strName=[NSString stringWithFormat:@"17_%d.jpg",i+1]; //加载图片 UIImage *image=[UIImage imageNamed:strName]; UIImageView *imageView=[[UIImageView alloc]initWithImage:image]; imageView.frame=CGRectMake(20+ 97*(i%3), 20+130*(i/3), 85,120); //add方法是添加视图的 [self.view addSubview:imageView]; [imageView release]; } //把图片添加到数组里面去 addObject NSString *sirName=[NSString stringWithFormat:@"%d.png",i+1]; UIImage *image=[UIImage imageNamed:sirName]; [imageArray addObject:image ]; //随机数 后面是数组元素的个数 int random=arc4random()%[imageArray count]; 随机数一般都是需要取模的 相当于是确定生成随机数的范围 不至于太大的数 取模规律 8 取模生成的是0,1,2,3,4,5,6,7; 往按钮上面添加图片很重要的方法 使得每一个图片都是可以点的 实际实际上点的都是button [btn setImage:image forState:UIControlStateNormal]; //设置按钮的大小 相当于是确定了图片的大小 和 图片视图是差不多的 btn.frame=CGRectMake(40*i , 40*j, 40, 40); objectAtIndex 只适用于集合(数组)。可根据索引获取对象。如: NSArray *array=[NSArray arrayWithObjects:@"zhangsan",@"lisi",@"wangwu",nil]; NSLog("%@",[array objectAtIndex:0]); 这时输出的值是'zhangsan' .可以看出objectAtIndex 消息是从下标0开始。 objectAtIndex从0开始 即第一个元素的位置是0 objectAtIndex 一般在数组操作中用到。但是这个数组必须是你能控制的,就是说你必须清楚地知道第几个元素是什么内容。 如果你不清楚你需要的元素在什么位置,请用tag标注。 //两个宝石 相同的点了之后 就都隐藏了 不同 的点了没反应 这是函数的实现 -(void)pressButton:(UIButton *)btn { //只被执行一次,以后都不执行了,记录上次的值;如果没有,每次都会执行,避免出现空指针直接nil static UIButton * lastBtn=nil; if (lastBtn==nil) { lastBtn=btn; lastBtn.enabled=NO;//点击 是否可以点击 } else { if (lastBtn.tag==btn.tag) { lastBtn.hidden=YES; btn.hidden=YES; lastBtn=nil; } else { lastBtn.enabled=YES; lastBtn=nil; } } } //横着滚动的情况 特别要注意滚动条的偏移量 横着的画最好与图片的宽度一致,竖着的画最好与图片的宽度一致 //初始化 UIScrollView *sv=[[UIScrollView alloc]initWithFrame:CGRectMake(30, 30, 260, 400)]; //设置滚动条最后移动的背景颜色 sv.backgroundColor=[UIColor redColor]; for (int i=0; i<3; i++) { UIImageView *imageView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"17_%d.jpg",i+1]]]; imageView.frame=CGRectMake(0+i*260, 0, 260,400); //添加图片视图,视图用addSubview的方法来添加,把图片添加到滚动视图上面 [sv addSubview:imageView]; [imageView release]; } //设置显示内容尺寸 sv.contentSize=CGSizeMake(260*3, 400); // 设置按照页码滚动 sv.pagingEnabled=YES; // 设置边缘弹动效果,拉到极端的时候可以弹起来 sv.bounces=YES; //改变滚动条偏移量 sv.contentOffset=CGPointMake(260, 0);//最好设置为CGPointMake(0, 0);上下 横着都不会首影响 //再把滚动视图添加到 总试图上面 [self.view addSubview:sv ]; //竖着着滚动的情况 特别要注意滚动条的偏移量 横着的画最好与图片的宽度一致,竖着的画最好与图片的宽度一致 //初始化 UIScrollView *sv=[[UIScrollView alloc]initWithFrame:CGRectMake(30, 30, 260, 400)]; //设置滚动条最后移动的背景颜色 sv.backgroundColor=[UIColor redColor]; for (int i=0; i<3; i++) { UIImageView *imageView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:[NSString stringWithFormat:@"17_%d.jpg",i+1]]]; imageView.frame=CGRectMake(0, 0+i*400, 260,400); //添加图片视图,视图用addSubview的方法来添加,把图片添加到滚动视图上面 [sv addSubview:imageView]; [imageView release]; } //设置显示内容尺寸 sv.contentSize=CGSizeMake(0, 400*3); // 设置按照页码滚动 sv.pagingEnabled=YES; // 设置边缘弹动效果,拉到极端的时候可以弹起来 sv.bounces=YES; //改变滚动条偏移量 sv.contentOffset=CGPointMake(0, 400);//最好设置为CGPointMake(0, 0);上下 横着都不会首影响 //再把滚动视图添加到 总试图上面 [self.view addSubview:sv ]; //销毁对象,程序结束的时候调用,销毁控制器 - (void)dealloc { //棋盘销毁,首先把棋子都拿掉 self.vc01=nil; self.vc02=nil; self.vc03=nil; self.vc04=nil; self.vc05=nil; self.vc06=nil; [_window release]; [super dealloc]; } self.navigationItem.leftBarButtonItem=barBtnLef;//导航左按钮 self.navigationItem.rightBarButtonItem=barBrnRight;//导航右按钮 //创建左导航按钮 UIButton *btnLeft=[UIButton buttonWithType:UIButtonTypeCustom]; btnLeft.frame = CGRectMake(0, 0, 33, 30); [btnLeft addTarget:self action:@selector(pressLeftNav) forControlEvents:UIControlEventTouchUpInside]; UIImage *imageLeft=[UIImage imageNamed:@"main_left_nav"]; [btnLeft setImage:imageLeft forState:UIControlStateNormal]; UIBarButtonItem *barBtnLef=[[UIBarButtonItem alloc] initWithCustomView:btnLeft]; self.navigationItem.leftBarButtonItem=barBtnLef; //创建右导航按钮,button也有frame 起始位置都是默认的 只需要宽和高就可以了,不一定是添加在window上面,可以添加在视图上面 UIButton *btnRight = [UIButton buttonWithType:UIButtonTypeCustom]; btnRight.frame = CGRectMake(0, 0, 48, 29); [btnRight addTarget:self action:@selector(pressRightNav) forControlEvents:UIControlEventTouchUpInside]; UIImage *imageRight = [UIImage imageNamed:@"main_right_nav"]; [btnRight setImage:imageRight forState:UIControlStateNormal]; //导航栏 有自己特定的按钮的 UIBarButtonItem *barBrnRight=[[UIBarButtonItem alloc]initWithCustomView:btnRight]; self.navigationItem.rightBarButtonItem=barBrnRight; navigationItem指的是导航的各种属性 可以引用导航按钮 标题视图 等等 //导航栏的标题视图titleView UIImageView *ivLogo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo_title"]]; ivLogo.frame = CGRectMake(0, 0, 60, 35); self.navigationItem.titleView = ivLogo;//标题视图 [ivLogo release]; UIView *bgView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; UIImageView *bgImageView=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; [bgView addSubview:bgImageView]; imageview.UserInteractionEnabled=YES;//是否能和用户交互; //特别注意的一点是 button上面同时有标题与 小图片的时候 默认是图片在前面 ,字在后面 NSArray *arrayTopButtonTitle = [NSArray arrayWithObjects:@"照片", @"状态", @"报到", nil]; NSArray *arrayTopBtnImages = [NSArray arrayWithObjects:@"rr_pub_takephoto", @"rr_pub_status", @"rr_pub_checkin", nil]; for (int i=0; i<arrayTopButtonTitle.count; i++) { UIButton *btn = [UIButton buttonWithType:UIButtonTypeRoundedRect]; btn.frame = CGRectMake(5+105*i, 2, 100, 30); [btn setTitle:[arrayTopButtonTitle objectAtIndex:i] forState:UIControlStateNormal]; //把图片放在按钮上面 [btn setImage:[UIImage imageNamed:[arrayTopBtnImages objectAtIndex:i]] forState:UIControlStateNormal]; [topButtonImageView addSubview:btn]; } 经常想做的效果,主界面设置一个好看的图片 让后再添加button 等其他一些东西 //设置主界面的背景 用图片视图作为背景 UIView *bgView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 460)]; UIImageView *bgImageView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"rr_main_background"]]; bgImageView.frame=CGRectMake(0, 0, 320, 460); //把图片视图添加到视图 实际上就是把图片添加到视图 [bgView addSubview:bgImageView]; //是否可以与用户交互 不能交互就不能够点击按钮 topButtonImageView.userInteractionEnabled=YES; [bgImageView addSubview:topButtonImageView]; bgImageView.userInteractionEnabled=YES; 注意的是:最外层view 设置的button不用设置与用户交互 就是可以点击的 而当视图上面还有小视图的时候 而且小视图上面还有button的时候,这个时候必须设置与用户交互YES topButtonImageView.userInteractionEnabled=YES; 否则虽然有button 但是点不动 呵呵; //张贝贝经典改变颜色的程序 -(void)viewDidLoad { [super viewDidLoad]; self.navigationItem.prompt=@"移动滑块后将改变画面颜色"; slider =[[UISlider alloc]init]; slider.frame=self.navigationController.navigationBar.bounds; slider.minimumValue=0.0; slider.maximumValue=1.0; slider.value=0.0; [slider addTarget:self action:@selector(sliderDidChange) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.titleView=slider; label =[[UILabel alloc]init]; label.frame=CGRectInset(self.view.bounds, 10, 10); //表示自动拉伸对齐 label.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight; label.backgroundColor=[UIColor blackColor]; [self.view addSubview:label]; } -(void)viewWillAppear:(BOOL)animated { // [super viewWillAppear:<#animated#>]; [self.navigationController setNavigationBarHidden:NO animated:YES]; [self.navigationController setToolbarHidden:YES animated:YES]; [self.navigationItem setHidesBackButton:YES animated:NO]; } -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [self.navigationItem setHidesBackButton:NO animated:YES]; } //关于颜色的调配 -(void)sliderDidChange { UIColor *color =[[UIColor alloc]initWithRed:(1-slider.value) green:slider.value blue:(1-slider.value)+0.4 alpha:1.0]; label.backgroundColor=color; } //static的用法 交替进行 -(void)changColor { //保留每一次的值 然后在开始 没有static就每次都是针对 黑色的将不会出现 //布尔类型的变量 定义了一个变量 static bool isChange=true; if (isChange) { self.view.backgroundColor=[UIColor redColor]; } else { self.view.backgroundColor=[UIColor blackColor]; } //此时必须还要赋过来 然后才可以 红色与黑色交替变换 isChange=!isChange; } //通知中心 把方法通过一个控制器传递给另外一个控制器 [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(changeBackColor) name:@"CHANGE_COLOR" object:nil]; 两个控制器都必须有同样的通知 都是同一个方法的实现才是可以的 颜色是可以不一样的 //滚动条下面的脚视图 _tableView.tableFooterView = titleView; /* UITableViewCellAccessoryDetailDisclosureButton为蓝色小园按钮,**可点击** */ 上百个视图的画 大项目 用Single View Application来做做设计 很号的理清自己的思路 视图太多了 不好弄 刚开始尽量不要和代码连接在一起! 拖空间 工作的前两年 还是手写代码 //%2d表示显示两位数字 %02d表示只有各位的时候 十位是0 NSString *str = [NSString stringWithFormat:@"%02d:%02d",random1,random2]; //查找的第一响应事件 - (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar { //创建UIControl一层界面 _searchBg = [[UIControl alloc] initWithFrame:CGRectMake(0, 0, 320, 240)]; [_searchBg addTarget:self action:@selector(backgroundTap:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:_searchBg]; [_searchBg release]; return YES; } - (void)backgroundTap:(id)sender { UISearchBar *bar = (UISearchBar *)[self.view viewWithTag:110]; [bar resignFirstResponder]; if (_searchBg) { [_searchBg removeFromSuperview]; } } //一般这种写法是表示自动拉伸对齐 mTableView.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight; 在应用UIBUtton的时候我们有时需要同时设置图片和文字,下面代码仅供参考: UIButton *_backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_backButton setFrame:CGRectMake(12, 8, 64, 28)]; [_backButton setTitle:@"返回" forState:UIControlStateNormal]; //设置button在没有选中的时候显示的字体 _backButton.titleLabel.font = [UIFont systemFontOfSize:14.0f]; //设置button显示字体的大小 [_backButton setBackgroundImage:[UIImage imageNamed:@"backButton.png"] forState:UIControlStateNormal]; //设置button背景显示图片 [self.view addSubview:_backButton]; 出了上面的操作意外,我们还可以同时设置button在选中(按下之后)以及正常状态下(没有选中)显示文字和图片的不同, UIButton *_backButton = [UIButton buttonWithType:UIButtonTypeCustom]; [_backButton setFrame:CGRectMake(12, 8, 64, 28)]; [_backButton setTitle:@"返回" forState:UIControlStateNormal]; [_backButton setTitle:@"Down" forState:UIControlStateHighlighted]; [_backButton setBackgroundColor:[UIColor clearColor]]; [_backButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; _backButton.titleLabel.font = [UIFont systemFontOfSize:14.0f]; [_backButton setBackgroundImage:[UIImage imageNamed:@"backButton.png"] forState:UIControlStateNormal]; [_backButton setBackgroundImage:[UIImage imageNamed:@"DownButton.png"] forState:UIControlStateNormal]; [_toolBar addSubview:_backButton]; //自定义导航条添加按钮,并且添加事件 UIBarButtonItem *btn=[[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStyleBordered target:self action:@selector(btns:)]; //放在左边 self.navigationItem.leftBarButtonItem=btn; 不管有多少行 都是可以用来代替的。。。。 //一般试图器之间发生的关系 都是用一个button 点击事件 然后用导航推出下一个视图 -(void)nextPage:(id)sender { //创建下一个视图控制器的对象 thirdViewController *third = [[thirdViewController alloc]init]; //然后用导航来推出 [self.navigationController pushViewController:third animated:YES]; [third release]; } 同步声明一次 就应该析构一次 @property (strong, nonatomic) UISplitViewController *splitViewController; @synthesize splitViewController = _splitViewController; 这是必须的 因为声明一次 就会出现一个strong 计数器加上1 就需要释放一次 - (void)dealloc { [_splitViewController release]; [super dealloc]; } //需要牢记的内存管理知识 @property (nonatomic, copy) NSString *descrition;//字符串的声明,里面最好是用copy //同步的标准写法 加上下划线 @synthesize descrition = _descrition; //立马还需要调用dealoc函数 析构 自己手动写出 高手的指点 - (void)dealloc { self.descrition = nil; [super dealloc]; } 另外需要注意的是 @property (assign, nonatomic) NSInteger i;//assign是弱引用,计数器不用加1 而且整形的变量是不需要分配内存空间的 没有指针 所以不能给强引用 ,此时不能用到strong的 //本类中声明成员变量的方法 只是为了本类来使用的 其他的类是用不着的 @implementation Vc02 { //只允许本类来使用的成员变量 NSDictionary *_dict; } //成员变量只要是指针变量 就需要调用dealloc来释放 顺序是先release 然后再放空 声明的全局变量需要 self.descrition = nil; 直接放空 就可以了 需要特别的牢记 - (void)dealloc { //成员变量是先释放 然后在放空 [_dict release]; _dict = nil; [super dealloc]; } //设置内容尺寸,能够显示内容的尺寸 根据所有图片的大小来确定的 sv03.contentSize=CGSizeMake(0, 1000); // 设置按照页码滚动 sv03.pagingEnabled=YES; // 设置边缘弹动效果,拉到极端的时候可以弹起来 sv03.bounces=YES; //改变滚动条偏移量,从第三张图片开始 ,从顶部第一张图片开始的,就是0与0,这个偏移量挺重要的 sv03.contentOffset=CGPointMake(0, 320); //再把滚动视图添加到 总试图上面 [self.view addSubview:sv03 ]; [sv03 release]; //添加右边的图片 UIImageView *imageView01=[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"衣装"]]; imageView01.frame=CGRectMake(170, 0, 150, 75); imageView01.userInteractionEnabled =YES; UIButton *button01=[UIButton buttonWithType:UIButtonTypeCustom]; button01.frame=CGRectMake(0, 0, 150, 75); [button01 addTarget:self action:@selector(press01) forControlEvents:UIControlEventTouchUpInside]; //加一个nil 表示透明的button 与下面一句话的意思差不多 //[button setImage:nil forState:UIControlStateNormal]; [button01 setBackgroundColor:[UIColor clearColor]]; [imageView01 addSubview:button01]; [self.view addSubview:imageView01]; [imageView01 release]; UIAlertView 是不用添加到试图上面 的 但是UIActionSheet 是必须要添加到试图上面 全局的成员变量 需要用dealloc函数来释放的 记住; @property(strong,nonatomic)UILabel *lab01; @synthesize lab01; self.lab01=[[[UILable alloc]init]autorelease];//这里用到了点语法,所以计数器是加1的;后面需要一个自动释放池才可以,程序快结束的时候来调用,用点语法才是正常调用了@property与@synthesize 要不然只是声明。。。。全局的成员变量还要用到dealloc来析构一次才可以 一般不建议这样用 ,最好还是用[lab01 release]; //UIActionSheet是最外层的 所以一般不能直接添加到试图view上面 记住!! UIImageView *imageview = (UIImageView *)[self.view viewWithTag:33333]; actionsheet=[[UIActionSheet alloc]initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:@"分享到新浪微博" otherButtonTitles:@"分享到腾讯微博", nil]; actionsheet.delegate=self; [actionsheet showInView:imageview]; [actionsheet release]; //滚动试图在下面 点哪张 加上哪张 -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { UITouch *touch=[touches anyObject]; //鼠标点击的位置 确定下来 CGPoint pt=[touch locationInView:scroll02]; //点击一次的时候 if (touch.tapCount==1) { for (int i=0; i<18; i++) { //根据tag 找到那个图片视图 UIImageView *image=(UIImageView *)[scroll02 viewWithTag:i+1]; //设置与用户交互 image.userInteractionEnabled=YES; // // int tag=image.tag; scroll02.userInteractionEnabled=YES; //判断是否点击到了图片 if (CGRectContainsPoint(image.frame, pt)) { //点到了哪张 就把图片的文件名赋给他 imageName=[NSString stringWithFormat:@"17_%d.jpg",image.tag]; UIImage *image=[UIImage imageNamed:imageName]; UIImageView *imageView=[[UIImageView alloc]initWithImage:image]; imageView.frame=CGRectMake(0, 0, 320, 190); [self.view addSubview:imageView]; [imageView release]; } } } } UITouch 处理用户响应事件,需要重载那三个触摸的方法,开始,触摸到,末尾, //用下载的数据 实例化 xml解析器 GDataXMLDocument *doc=[[GDataXMLDocument alloc]initWithData:downloadData options:0 error:nil]; //解析器 创建成功 (下载的数据 是合法的xml文件) if (doc) { //从解析器中用xpath 语法 查找 我要找的节点 返回值不管怎么样 都是数组类型 NSArray *usersArray=[doc nodesForXPath:@"//user" error:nil]; //xml文档中 的所有的 节点 都是 GDataXMLElement类的 实例(对象) for (GDataXMLDocument *element in usersArray) { // [element childAtIndex: ];//返回的第几个子节点 // [element childCount]; //返回element 节点的子节点 为数组 //[element children]; // [element attributeForName:@""]; 获得element 节点的指定名称 的属性 节点 //获得element节点的所以的属性节点 // [element attribute]; //实例化 模型类 对象 UserItem *item=[[[UserItem alloc]init] autorelease]; //从当前节点中查找 指定名称的子节点 elementsForName 所有的节点 都是element // NSArray *subArray=[element elementsForName:@"uid"]; // //uid节点 // // GDataXMLElement *uidElement=[subArray lastObject]; // // //获取节点的 文本信息 // item.uid=[uidElement stringValue]; item.uid=[self elementString:element name:@"uid"]; item.username=[self elementString:element name:@"username"]; item.realname=[self elementString:element name:@"realname"]; item.headimage=[NSString stringWithFormat:@"http://192.168.88.8/sns%@",[self elementString:element name:@"headimage"]] ; [dataArray addObject:item]; } isLoading=NO; [self.tableView reloadData]; } 高亮情况下的button的实现方式(相当于设置两张图片,一张是为默认准备的,一张是高亮准备的) //默认的情况是出现一张图片 UIButton * rightbtn = [UIButton buttonWithType:UIButtonTypeCustom]; [rightbtn setImage:[UIImage imageNamed:@"NextMenuButton.png"] forState:UIControlStateNormal]; //高亮的时候是出现另外一张图片 [rightbtn setImage:[UIImage imageNamed:@"NextMenuButtonSelected.png"] forState:UIControlStateHighlighted]; rightbtn.frame = CGRectMake(200, 0, 40, 40); [rightbtn addTarget:self action:@selector(pressrightbtn) forControlEvents:UIControlEventTouchUpInside]; [navbar addSubview:leftbtn]; [navbar addSubview:rightbtn]; 自定义导航栏以及导航栏上面的 按钮 的基本方法 //自己定义导航栏 UINavigationBar * navbar = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, 320, 40)]; //导航栏设置背景图片 [navbar setBackgroundImage:[UIImage imageNamed:@"NavigatorBarBg"] forBarMetrics:UIBarMetricsDefault]; //创建这个对象很重要的 UINavigationItem * item =[[UINavigationItem alloc] init]; //导航栏上面的返回按钮 UIBarButtonItem * btn1 = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStyleDone target:self action:@selector(pressbtn1)]; btn1.tintColor = [UIColor yellowColor]; item.leftBarButtonItem = btn1; [btn1 release]; //没有这句话 回来的时候就推不过去的 [navbar pushNavigationItem:item animated:YES]; [item release]; [self.view addSubview:navbar]; [navbar release]; //这么重要的函数老师居然没有讲 我靠!! //此函数 如果是 return YES则就是四个方向都是支持的 竖着,倒着,左横,右横; 但系统默认只是正着的状态 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { // Return YES for supported orientations return (interfaceOrientation == UIInterfaceOrientationPortrait); // return YES; }