iOS入门学习笔记

xiaoxiao2021-10-27  37

oc和c的差别

OC中用#import导包OC不考虑重复包含OC头文件用.h结束完全兼容c语言 语法和函数

object-c基础语法

第一讲:OC简介及基本语法

Objective-C简称OC是在C语言的基础上,增加了一层最小的面向对象语法,完全兼容C语言,也就是可以在OC代码中混入C语言代码,甚至是C++代码。可以使用OC开发Mac OS X平台和IOS平台的应用程序。简单的介绍了一下OC,下面我们来看看OC的基本语法,学习OC之前我们先学习了C语言,因为OC是在C语言的基础上的一门开发语言,因此OC的很多基本语法跟使用方法跟C语言有类似的地方但是也有其独特的地方。

1. 关键字

OC中的关键字基本上所有的都是以@开头,但也有少数不是以@开头的,下面是一些较常用的关键字:

@interface、@implementation、@end @public、@protected、@private、@selector @try、@catch、@throw、@finally @protocol、@optional、@required、@class @property、@synthesize、@dynamic self、super、id、_cmd、__block、__strong、__weak、

2. 字符串以@开头

比如@"Hello"是OC中的字符串,而"Hello"则是C语言中的字符串

3. OC程序的开发过程

OC程序的开发跟C语言类似,从 .m源文件编译成 .o目标文件再链接成 a.out可执行文件

4. 程序框架

OC程序的入口也是main函数

在编写第一个OC程序时用到了OC的输出函数NSLog,但调用NSLog需要包含Foundation框架,OC中一般使用#import <Foundation/Foundation.h>来包含Foundation框架,每个框架都有自己的主头文件:即最主要的头文件。主头文件名字一般跟框架名称一样,包含了框架中的所有其他头文件,Foundation框架的主头文件名称就是Foundation.h,只需要包含Foundation框架的主头文件,就可以使用整个框架的东西。

其中#import的作用:跟C语言中#include一样,用来拷贝某个文件的内容,#import可以自动防止文件内容被拷贝多次,也就意味着头文件中不用加入相应的预处理指令。

#import <Foundation/Foundation.h> //OC程序的入口:main函数 int main() {   //printf("第一个OC程序\n");//OC完全兼容C语言程序   NSLog(@"第一个OC程序"); //NSLog输出内容会自动换行   return 0; }

5. NSLog与printf的区别

NSLog接收OC字符串作为参数,printf接收C语言字符串作为参数

NSLog输出后会自动换行,printf输出后不会自动换行

使用NSLog需要

#import <Foundation/Foundation.h>

使用printf需要

#include <stdio.h>

6. Foundation框架的作用

开发OC、iOS、Mac程序必备的框架

此框架中包含了很多常用的API(应用编程接口)

框架中包含了很多头文件,若想使用整个框架的内容,包含它的主头文件即可:

#import <Foundation/Foundation.h>

7. BOOL的使用

BOOL类型的本质 typedef signed char BOOL;

BOOL类型的变量有2种取值:YES、NO

#define YES (BOOL)1 #define NO (BOOL)0

BOOL的输出(当做整数来用)

NSLog(@"%d %d", YES, NO);

第二讲:类和对象

OC是一门面向对象的开发语言,而C语言是面向过程的,因此在开发思想上要把面向过程和面向对象好好区分开来,体会其中的不同之处。面向过程关注的是解决问题需要哪些步骤,而面向对象关注的是解决问题需要哪些对象。

1. 类的设计

在C语言中完整的写一个函数需要函数的声明和定义(也就是实现),而OC中类似,完整的写一个类需要类的声明和实现

类的设计主要包括:类名,属性和行为

设计类名注意点:

类名的第一个字母必须是大写不能有下划线多个英文单词,用驼峰标识

2. 方法(行为)的设计

OC中方法就是行为,主要包括方法名,参数,返回值(声明和实现)方法不能放在大括号里面

注意点:

只要是OC对象的方法,必须以减号 - 开头,类方法以+开头OC方法中任何数据类型都必须要用()扩住OC方法中的小括号():只有一个作用,用来扩住数据类型

3. 类的声明和实现

OC中类的声明值得是用来声明对象的属性跟行为,声明对象的属性(实例变量或者叫成员变量) , 成员变量默认情况下会做一个初始化,所有成员变量默认都是0

声明在@interface和@end之间进行,实现在@implementation和@end之间进行

在使用类创建对象之前,会将类加载进内存,类的内存里面只放方法列表,创建的每个对象内部默认有一个指针(isa指针),这个指针指向这个对象所对应的类,所有的对象共用相同的类里面的方法。

类的声明跟实现常见错误:

只有类的声明,没有类的实现

漏了@end ,@interface和@implementation嵌套

两个类的声明嵌套

成员变量没有写在括号里面

方法的声明写在了大括号里面

语法细节:

成员变量不能在{}中进行初始化、不能被直接拿出去访问

方法不能当做函数一样调用

成员变量\方法不能用static等关键字修饰,别跟C语言混在一起(暂时忽略)

类的实现可用写在main函数的后面,主要在声明后面就行了

4. 方法跟函数的区别

方法:

对象方法都是以减号-开头

对象方法的声明必须写在@interface和@end之间

对象方法的实现必须写在@implementation和@end之间

对象方法只能由对象来调用

对象方法归类\对象所有

函数:

函数能写在文件中的任意位置(@interface和@end之间除外),函数归文件所有,函数可以定义在@implementation和@end之间,这个是没有问题完全可以

函数调用不依赖于对象

函数内部不能直接通过成员变量名访问某个对象的成员变量

5. 方法的声明和实现

@interface JiSuanQi : NSObject - (double)pi; // 方法名叫pi,不带参数的方法 // OC方法中,一个参数对应一个冒号 // 方法名叫pingFang: ,要连上冒号,为了防止方法名的冲突,冒号也是方法名的一部分 - (int)pingFang:(int)num; // 带一个参数的方法 // 方法名叫: sumWithNum1:andNum2: - (int)sumWithNum1:(int)num1 andNum2:(int)num2; // 带两个参数的方法,可读性好 冒号前面加一些描述信息,来描述后面的参数是干嘛用的 @end

因此注意在定义方法名时要注意一些规范,保证可读性好,类似于 sumWithNum1:andNum2:这种的方法名。

第三讲:三大特性

第三讲我们主要讲OC的三大特性,OC是一门面向对象的语言,面向对象的开发语言一般共同的特点就是具有三大特性:封装,继承和多态。下面我们来学习一下OC的三大特性。

一、 封装

封装就是对类中的一些字段,方法进行保护,不被外界所访问到,有一种权限的控制功能。

封装的好处:过滤不合理的值,屏蔽内部的赋值过程,让外界不必关注内部的细节。

1. set方法和get方法

set方法

作用:提供一个方法给外界设置成员变量值,可以在方法里面对参数进行相应过滤

命名规范:

(1)方法名必须以set开头

(2)set后面跟上成员变量的名称,成员变量的首字母必须大写

(3)返回值一定是void

(4)一定要接收一个参数,而且参数类型跟成员变量类型一致

(5)形参的名称不能跟成员变量名一样

get方法

作用:返回对象内部的成员变量

命名规范:

(1)肯定有返回值,返回值类型肯定与成员变量类型一致

(2)方法名跟成员变量名一样

(3)不需要接收任何参数

2. 成员变量的命名规范:一定要以下划线 “_” 开头

作用:

让成员变量和get方法的名称区分开

可以跟局部变量区分开,一看到下划线开头的变量,一般都是成员变量

3. 经典错误

#import <Foundation/Foundation.h> @interface Person : NSObject @end @implementation Person @end int main() { Person *p = [Person new]; // OC是在运行过程中才会检测对象有没有实现相应的方法 [p test];//实现中没有test方法 return 0; }

报错:-[Person test]: unrecognized selector sent to instance 0x7fd2ea4097c0

给Person对象发送了一个不能识别的消息:test

4. 类方法和对象方法

(1)对象方法:

*减号 - 开头

*只能由对象来调用

*对象方法中能访问当前对象的成员变量(实例变量)

(2)类方法:

*加号 + 开头

*只能由类(名)来调用

*类方法中不能访问成员变量(实例变量)

(3)类方法的好处和使用场合:

*不依赖于对象,执行效率高

*能用类方法尽量用类方法

*场合:当方法内部不需要使用到成员变量时,就可以改为类方法

*可以允许类方法和对象方法同名

5. self关键字

self关键字是个指针,self指向方法调用者,代表着当前对象,当成员变量和局部变量同名时,采取就近原则,访问的是局部变量,用self访问成员变量,区分同名的局部变量

self用途:

(1)谁调用了当前方法,self就代表谁,(指向了当前对象-方法调用者)

* self出现在对象方法中,self就代表对象

* self出现在类方法中,self就代表类

(2)在对象方法中利用“self->成员变量名”访问当前对象内部的成员变量

(3)[self 方法名] 调用当前对象的某一个方法,可以调用其他对象方法或者类方法

常见错误:

*低级错误:用self去调用函数

*类方法中用self调用对象方法,对象方法中用self调用类方法

*self死循环

二、 继承

继承是类中的一个重要的特性,他的出现使得我们没必要别写重复的代码,可重用性很高。继承的一些专业术语:父类\超类:superclass 子类:subclass\subclasses

1.继承的好处:

*抽取重复代码

*建立了类之间的关系

*子类拥有父类中的所有成员变量和方法

*注意点:基本上所有类的根类是NSObject

2. 方法的重写

重写:子类重新实现父类中的某个方法,覆盖父类以前的做法

注意:

*父类必须声明在子类的前面,实现可以放在子类的后面

*子类不能拥有和父类相同的成员变量

*调用某个方法时,优先去当前类中找,如果找不到,去父类中找

*坏处:耦合性太强:类之间的关系太紧密了,当某个父类不见了,子类就用不了

3. 继承的使用场合

当两个类拥有相同属性和方法的时候,就可以将相同的东西抽取到一个父类中

当A类完全拥有B类中的部分属性和方法时,可以考虑让B类继承A类

4. 继承和组合

当某个类想拥有另一个类当中的东西,考虑两种方式,一种是继承一种是组合

继承:xx 是 xxx 代表什么什么(子类)是什么什么(父类)

组合:xxx 拥有 xxx

类A {   int _age;   int _no; } 类B {   A *_a; // B里面拥有A,这个是组合   int _weight; }

在实际的使用中,要注意逻辑和设计,区分好继承和组合的使用。

5. super关键字

super的作用和使用场合:

*直接调用父类中的某个方法

*super处在对象方法中,那么就会调用父类的对象方法

*super处在类方法中,那么就会调用父类的类方法

*使用场合:子类重写父类的方法时想保留父类的一些行为

三、 多态

多态指的是某一类事物的多种形态,OC对象具有多态性

多态的体现:Person *p = [Student new]; p->age = 10; [p walk];

1. 多态的使用注意

*没有继承就没有多态

*代码的体现:父类类型的指针指向子类对象

*好处:如果函数\方法参数中使用的是父类类型,可以传入父类,子类对象

*局限性:父类类型的变量 不能 直接调用子类特有的方法。必须强制转为子类类型的变量后,才能直接调用子类特有的方法。

2. 代码中的注意点

Animal *a = [Dog new]; //[a run];run方法为Dog独有,不能直接访问 Dog *d = (Dog *)a;//强制转换为Dog *类型才能调用run方法 [d run];

控件学习

第一课 UILabel和Button

UILabel 类似于TextView,属性基本一致。

//创建UI控件函数 - (void) createUILabel { //textview UILabel* label=[[UILabel alloc] init]; //background label.backgroundColor=[UIColor grayColor]; //text label.text=@"先帝创业未半而中道崩殂"; //在屏幕上的位置 和 自身大小 //p1 :距x轴位置 //p2: 距Y轴位置 //p3: width //p4: height label.frame=CGRectMake(100,100 , 160, 80); //textsize 文字大小 label.font=[UIFont systemFontOfSize:24]; //textcolor 文字颜色 label.textColor=[UIColor blueColor]; //阴影 label.shadowColor=[UIColor redColor]; label.shadowOffset=CGSizeMake(0, 3); //gravity label.textAlignment=NSTextAlignmentCenter; //默认是1,>0文字会按照设置的行数显示,=0会自动z计算 label.numberOfLines=0; [self.view addSubview:label]; }

button视图的实现和使用

-(void)creatUIRectButton{ //创建一个btn对象,根据类型来创建button //圆角类型btn,UIButtonTYpeRoundedRect //通过类方法来创建 buttonWithType:类名+方法名 UIButton* btn=[UIButton buttonWithType:UIButtonTypeRoundedRect]; //设置按钮的位置 btn.frame=CGRectMake(100, 100, 100, 40); //设置按钮的文字内容和颜色 [btn setTitle:@"正常" forState:UIControlStateNormal]; // [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal]; //按下状态 [btn setTitle:@"按下" forState:UIControlStateHighlighted]; // [btn setTitleColor:[UIColor blueColor] forState:UIControlStateHighlighted]; //背景颜色 btn.backgroundColor=[UIColor blueColor]; //设置按钮的风格颜色,会被上面覆盖,优先级没有titlecolor高 [btn setTintColor:[UIColor whiteColor]]; //字体大小 btn.titleLabel.font=[UIFont systemFontOfSize:18]; //点击事件 //3个参数 //目标(谁来实现)、函数对象(出发动作要干什么)、什么动作触发 //UIControlEventTouchUpInside当手指离开并手指在按钮范围内 [btn addTarget:self action:@selector(pressBtn:) forControlEvents:UIControlEventTouchUpInside]; //按钮标识 btn.tag=101; [self.view addSubview:btn]; }

Button的点击事件

-(void) pressBtn:(UIButton*) btn{ switch (btn.tag) { case 101: NSLog(@"press01 up"); break; case 102: NSLog(@"press02 up"); break; default: break; } }

图片背景的Button,方法和Android差不多

-(void) createImageBtn{ //创建一个可以显示 图片的按钮 UIButton* btnImage=[UIButton buttonWithType:UIButtonTypeCustom]; btnImage.frame=CGRectMake(100, 300, 100, 100); UIImage* icon01=[UIImage imageNamed:@"common_password_icon"]; UIImage* icon02=[UIImage imageNamed:@"common_open_mine"]; [btnImage setImage:icon01 forState:UIControlStateNormal]; [btnImage setImage:icon02 forState:UIControlStateHighlighted]; [btnImage addTarget:self action:@selector(pressBtn:) forControlEvents:UIControlEventTouchUpInside]; btnImage.tag=102; [self.view addSubview:btnImage]; }

第二课 UIViewControl的生命周期和UIIView

生命周期

初始化方法,只会加载一次,里面是UIView的使用

//只会加载一次 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. NSLog(@"视图第一次加载,并且只会加载一次"); //uiview是ios中的视图对象,显示在屏幕上的虽有对象的基础类 //他是一个矩形对象,有背景颜色,可以显示,有层级关系 UIView* view=[[UIView alloc] init]; //frame是uiview的属性 view.frame=CGRectMake(100, 200, 100,100); view.backgroundColor=[UIColor blueColor]; //将新建的视图显示在父视图上, //1.显示在屏幕上 //2.作为子视图管理起来 [self.view addSubview:view]; //i隐藏视图 yes //默认是no view.hidden=NO; //设置透明度 //alpha=1不透明 //=0透明 //=0.5 半透明 view.alpha=1; //设置是否显示不透明 view.opaque=NO; //讲自己从父视图移除 // [view removeFromSuperview]; //关于uiview的层级 //先添加的先绘制 UIView* view01=[[UIView alloc] init]; view01.frame=CGRectMake(120, 240, 100,100); view01.backgroundColor=[UIColor greenColor]; UIView* view02=[[UIView alloc] init]; view02.frame=CGRectMake(140, 260, 100,100); view02.backgroundColor=[UIColor orangeColor]; //将新建的视图显示在父视图上, //1.显示在屏幕上 //2.作为子视图管理起来 [self.view addSubview:view]; [self.view addSubview:view01]; [self.view addSubview:view02]; //调整视图到最前方 // [self.view bringSubviewToFront:view]; // [self.view sendSubviewToBack:view02]; self.view.backgroundColor=[UIColor whiteColor]; }

当视图即将显示时

//当视图即将显示时 //显示前-正在显示-被隐藏 //参数表示是否有动画切换 - (void)viewWillAppear:(BOOL)animated { NSLog(@"视图即将显示"); }

视图即将消失

//视图即将消失 //当前视图还显示在屏幕上 - (void)viewWillDisappear:(BOOL)animated{ NSLog(@"视图即将消失"); }

当视图已经显示到屏幕后的瞬间调用此函数

//当视图已经显示到屏幕后的瞬间调用此函数 //当前视图已经显示在屏幕上 - (void)viewDidAppear:(BOOL)animate { NSLog(@"视图已经显示"); }

当视图从屏幕上消失

//当视图从屏幕上消失 //当前视图已经从屏幕上消失 - (void)viewDidDisappear:(BOOL)animated { NSLog(@"视图已经消失"); } 2018-10-20 12:54:43.792602+0800 IosTest[35286:2553222] 视图第一次加载,并且只会加载一次 2018-10-20 12:54:43.792960+0800 IosTest[35286:2553222] 视图即将显示 2018-10-20 12:54:43.848378+0800 IosTest[35286:2553222] 视图已经显示 2018-10-20 12:54:45.957212+0800 IosTest[35286:2553222] 视图即将消失 2018-10-20 12:54:46.474963+0800 IosTest[35286:2553222] 视图已经消失

第三课 UISwitch、UIProgressView和UISlider

UISwitch:

//初始化 _mySwitch=[[UISwitch alloc] init]; //宽度和高度无法改变 _mySwitch.frame=CGRectMake(100, 100, 80, 40); //设置开关状态 _mySwitch.on=YES; [_mySwitch setOn:YES]; [_mySwitch setOn:YES animated:YES]; //开启状态的颜色 [_mySwitch setTintColor:[UIColor orangeColor]]; //开关圆点的颜色 [_mySwitch setThumbTintColor:[UIColor redColor]]; //默认的颜色 [_mySwitch setTintColor:[UIColor blueColor]]; //开关控件添加事件 [_mySwitch addTarget:self action:@selector(swtOn:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:_mySwitch];

开关事件

- (void) swtOn:(UISwitch*) swt { if(swt.on){ NSLog(@"开关被打开"); }else{ NSLog(@"开关被关闭"); } }

UIProgressView

_progressView=[[UIProgressView alloc] init]; //高度不能变更 _progressView.frame=CGRectMake(50, 100, 200, 40); _progressView.progressTintColor=[UIColor redColor]; //0-1 设置进度值 _progressView.progress=0.5; _progressView.progressViewStyle=UIProgressViewStyleDefault; _progressView.trackTintColor=[UIColor blueColor]; [self.view addSubview:_progressView];

UISlider 滑动条

_slider=[[UISlider alloc] init]; //高度不能变更 _slider.frame=CGRectMake(10, 200, 300, 40); _slider.maximumValue=1; //可以为负值 _slider.minimumValue=0; _slider.value=0.3; //滑块左侧的颜色 _slider.minimumTrackTintColor=[UIColor redColor]; //滑块右侧的颜色 _slider.maximumTrackTintColor=[UIColor greenColor]; //滑块的颜色 _slider.thumbTintColor=[UIColor blueColor]; [_slider addTarget:self action:@selector(slideValue:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:_slider];

滑动事件监听

-(void) slideValue:(UISlider*) slider { _progressView.progress=_slider.value-_slider.minimumValue/_slider.maximumValue-_slider.minimumValue; }

第四课 NSTimer定时器

可以在每隔固定时间发送一个消息 通过此消息来调用相应的时间函数 通过此函数可在固定时间段来完成一个根据时间间隔的任务

UIButton* btn=[UIButton buttonWithType:UIButtonTypeRoundedRect]; btn.frame=CGRectMake(100, 100, 80, 40); [btn setTitle:@"启动定时器" forState:UIControlStateNormal]; [btn addTarget:self action:@selector(pressStart) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btn]; UIButton* btnStop=[UIButton buttonWithType:UIButtonTypeRoundedRect]; btnStop.frame=CGRectMake(100, 150, 80, 40); [btnStop setTitle:@"停止定时器" forState:UIControlStateNormal]; [btnStop addTarget:self action:@selector(pressStop) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:btnStop]; UIView* view=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 80, 80)]; view.backgroundColor=[UIColor orangeColor]; view.tag=103; [self.view addSubview:view];

创建并开始定时器函数

-(void) pressStart { //NSTimer的类方法创建一个定时器并启动这个定时器 //p1:每个多长时间调用定时器函数,以秒为单位 //p2:表示实现定时器的函数的对象 //p3:定时器函数对象 //p4:可以传入定时器里的一个参数, //p5:定时器是否重复 YES为重复 //返回一个新建好的定时器对象 _timerView=[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(uploadTimer:) userInfo:@"小明" repeats:YES]; }

停止函数

-(void) pressStop { if (_timerView!=nil) { //停止计时器 [_timerView invalidate]; } }

定时器函数 移动view

//定时器函数 -(void) uploadTimer:(NSTimer*) timer { NSLog(@"test......name=%@",timer.userInfo); UIView* view=[self.view viewWithTag:103]; view.frame=CGRectMake(view.frame.origin.x+5, view.frame.origin.y+5, 80, 80); }

第五课 UIStepper步进器和UISegmentedControl分栏器

定义步进器 按照一定的数值来调整某个数值 UIStepper* _stepper; 分栏器 UISegmentedControl* _segControl;

_label=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; _label.textAlignment=NSTextAlignmentCenter; [self.view addSubview:_label]; _stepper=[[UIStepper alloc] initWithFrame:CGRectMake(100, 100, 80, 40)]; _stepper.maximumValue=100; _stepper.minimumValue=0; _stepper.value=10; _label.text=[NSString stringWithFormat:@"%f",_stepper.value]; //每次步进的值 _stepper.stepValue=5; //是否可以重复响应事件操作 _stepper.autorepeat=YES; //是否将步进结果通过事件函数响应出来 _stepper.continuous=YES; [_stepper addTarget:self action:@selector(stepChange:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:_stepper]; //高度不可变,宽度可变 _segControl=[[UISegmentedControl alloc] initWithFrame:CGRectMake(10, 200, 300, 40)]; [_segControl insertSegmentWithTitle:@"1" atIndex:0 animated:YES]; [_segControl insertSegmentWithTitle:@"2" atIndex:1 animated:YES]; [_segControl insertSegmentWithTitle:@"3" atIndex:2 animated:YES]; _segControl.selectedSegmentIndex=1; [_segControl addTarget:self action:@selector(segChange:) forControlEvents:UIControlEventValueChanged]; [self.view addSubview:_segControl];

两个函数

-(void) segChange:(UISegmentedControl*) seg { NSLog(@"%ld",_segControl.selectedSegmentIndex); } -(void) stepChange:(UIStepper*) step { _label.text=[NSString stringWithFormat:@"%f",_stepper.value]; }

iOS第六课 NSArray与NSMutableArray

什么是NSArray

NSArray是OC中的数组类,开发中建议尽量使用NSArray替代C语言中的数组

NSArray的特点

只能存放任意OC对象, 并且是有顺序的不能存储非OC对象,比如 int \ float \ double \ char \ enum \ struct等它是不可变的,一旦初始化完毕后,它里面的内容就永远是固定的,不能删除里面的元素,也不能再往里面添加元素NSArray使用NSLog()打印,输出的是小括号的格式。NSArray中不能存储nil,因为NSArray认为nil是数组的结束(nil是数组元素结束的标记)。nil就是0,0也是基本数据类型,不能存放到NSArray中。

NSArray的常用方法

获取集合元素个数 -(NSUInteger)count; 获得index位置的元素 - (id)objectAtIndex:(NSUInteger)index; 是否包含某一个元素 - (BOOL)containsObject:(id)anObject; 返回最后一个元素 - (id)lastObject; 返回最后一个元素 - (id)firstObject; 查找anObject元素在数组中的位置(如果找不到,返回-1) - (NSUInteger)indexOfObject:(id)anObject; 在range范围内查找anObject元素在数组中的位置 - (NSUInteger)indexOfObject:(id)anObject inRange:(NSRange)range;

书写NSArray简写形式

NSArray *arr = [NSArray arrayWithObjects:@"lnj", @"lmj", @"jjj", nil]; NSArray *arr = @[@"lnj", @"lmj", @"jjj"]; // 获取数组元素的简写 NSLog(@"%@", [arr objectAtIndex:0]); NSLog(@"%@", arr[0]);

NSArray遍历

增强for 循环的使用

如何使用增强for循环,遍历NSArray数组

//逐个取出arr中的元素, 将取出的元素赋值给obj // 注意: obj的类型可以根据数组中元素的类型来写, 不一定要写NSObject for (NSString *obj in arr) { NSLog(@"obj = %@", obj); }

如何使用OC数组的迭代器来遍历数组

// 每取出一个元素就会调用一次block // 每次调用block都会将当前取出的元素和元素对应的索引传递给我们 // obj就是当前取出的元素, idx就是当前元素对应的索引 // stop用于控制什么时候停止遍历 [arr enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { if (idx == 1) { *stop = YES; } NSLog(@"obj = %@, idx = %lu", obj, idx); }];

数组排序

如何对数据进行排序

NSArray *arr = @[@10, @20, @5, @7, @15]; NSLog(@"排序前: %@", arr); // 注意: 想使用compare方法对数组中的元素进行排序, 那么数组中的元素必须是Foundation框架中的对象, 也就是说不能是自定义对象 elector:@selectoNSArray *newArr = [arr sortedArrayUsingSr(compare:)]; NSLog(@"排序后: %@", newArr);

如何对对象进行排序

Person *p1 = [Person new]; p1.age = 10; Person *p2 = [Person new]; p2.age = 20; Person *p3 = [Person new]; p3.age = 5; Person *p4 = [Person new]; p4.age = 7; NSArray *arr = @[p1, p2, p3, p4]; NSLog(@"排序前: %@", arr); // 按照人的年龄进行排序 // 该方法默认会按照升序排序 NSArray *newArr = [arr sortedArrayWithOptions:NSSortStable usingComparator:^NSComparisonResult(Person *obj1, Person *obj2) { // 每次调用该block都会取出数组中的两个元素给我们 // 二分 // NSLog(@"obj1 = %@, obj2 = %@", obj1, obj2); return obj1.age > obj2.age; //降序 // return obj1.age < obj2.age; //升序 /* 改方法,产生随机数用 if (obj1.age > obj2.age) { // 5 4 return NSOrderedDescending; }else if(obj1.age < obj2.age) { // 4 5 return NSOrderedAscending; }else { return NSOrderedSame; } */ }]; NSLog(@"排序后: %@", newArr);

NSArray和NSString转换

NSArray *arr = @[@"lnj", @"lmj", @"jjj"];

如何将数组中每个元素拼接成字符串

方法一:

// 1.定义一个可变字符串保存拼接之后的结果 NSMutableString *strM = [NSMutableString string]; // 2.遍历数组, 取出数组中的每一个元素, 将元素添加到可变字符串中 for (NSString *str in arr) { [strM appendString:str]; // 3.每次添加完毕之后再添加一个- [strM appendString:@"-"]; } [strM deleteCharactersInRange:NSMakeRange(strM.length - 1, 1)]; NSLog(@"strM = %@", strM);

方法二:

//把数组元素链接成字符串,用**作拼接符将数组元素拼接成一个字符串 NSString *str = [arr componentsJoinedByString:@"**"]; NSLog(@"str = %@", str);

如何通过一个字符串生成一个数组

字符串分割方法

NSString *str = @"lnj**lmj**jjj"; NSArray *arr = [str componentsSeparatedByString:@"**"]; NSLog(@"arr = %@", arr);

NSArray文件读写

如何将数组写入文件中

NSArray *arr = @[@"lnj", @"lmj", @"jjj"]; BOOL flag = [arr writeToFile:@"/Users/xiaomage/Desktop/abc.plist" atomically:YES]; NSLog(@"flag = %i", flag);

将数组写入文件中,有什么注意点

如果将一个数组写入到文件中之后, 本质是写入了一个XML文件 在iOS开发中一般情况下我们会将XML文件的扩展名保存为plistwriteToFile只能写入数组中保存的元素都是Foundation框架中的类创建的对象, 如果保存的是自定义对象那么不能写入 如何从文件中读取数据到NSArray中

从文件中读取一个数组,此方法在字典转模型中,经常用到

NSArray *newArray = [NSArray arrayWithContentsOfFile:@"/Users/xiaomage/Desktop/abc.plist"]; NSLog(@"%@", newArray);

NSMutableArray

可变数组 增删改查

什么是可变数组?和NSArray有什么区别

NSMutableArray是NSArray的子类; NSArray是不可变的,一旦初始化完毕后,它里面的内容就永远是固定的, 不能删除里面的元素, 也不能再往里面添加元素; NSMutableArray是可变的,随时可以往里面添加\更改\删除元素;

如何创建一个空的数组?创建可变数组有什么注意点?

1.创建空数组

NSMutableArray *arrM = [NSMutableArray array]; NSMutableArray *arrM = [[NSMutableArray alloc] init];

2.注意点:

不能通过@[]来创建一个可变数组, 因为@[]创建出来的是一个不可变的数组 如果把一个不可变数组当做一个可变数组来使用, 会引发一个运行时的错误 例如:

NSMutableArray *arrM = @[@"lnj", @"lmj"]; [arrM addObject:@"JJJ"];

如何给可变数组增加内容 方法一:

[arrM addObject:@"lnj"];

方法二:

// 将指定数组中的元素都取出来, 放到arrM中 \ 并不是将整个数组作为一个元素添加到arrM中 [arrM addObjectsFromArray:@[@"lmj", @"jjj"]]; // 注意: 以下是将整个数组作为一个元素添加 // [arrM addObject:@[@"lmj", @"jjj"]]; NSLog(@"%@", arrM);

如何给可变数组插入内容

[arrM insertObject:@"xcq" atIndex:1]; NSRange range = NSMakeRange(2, 2); NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range]; // 插入一组数据, 指定数组需要插入的位置, 和插入多少个 [arrM insertObjects:@[@"A", @"B"] atIndexes:set];

如何删除可变数组中的内容

删除指定元素:

[arrM removeObjectAtIndex:0];

删除数组中最后一个元素

[arrM removeLastObject];

删除index位置的元素

[arrM removeObject:@"A"];

如何替换可变数组中的内容

[arrM replaceObjectAtIndex:1 withObject:@"M"]; //简写: arrM[0] = @"ZS"; NSLog(@"%@", arrM);

如何获取可变数组中的内容

NSLog(@"%@", [arrM objectAtIndex:0]);

第七课 NSCoder的用法

iOS对象序列化与反序列化( NScoder 和 NScoding )

面向对象的程序在运行的时候会创建一个复杂的对象图,经常要以二进制的方法序列化这个对象图,这个过程叫做Archiving. 二进制流可以通过网络或写入文件中(来源于某教材的一段话)

本人的理解是当你于写数据需要本地存储时,即将你的数据写到硬盘上的时候,你就必须对他进行序列化,转换成二进制文件,从而便于在磁盘上的读写,同理在取出的时候必须将其在反序列化,这样才能将数据读出来,就好比加密和揭秘的过程。

为什么我将数据写到plist 中的时候,也是存储到本地的磁盘上,但是我就没有序列化啊?

大家有没有发现,其实plist 的数据是类型是有限制的,就那么几种特定的数据类型,nsstring ,大家有没有尝试过将一个自己定义的类放进去(写进plist ),在读出来? 结果是什么大家可以先猜想。 其实在nsstring 的类的定义中已经添加了协议 即他是实现了nscoding 代理的方法的。 @interface NSString : NSObject

深入

NScoder 和 NScoding NScoding 是一个协议,主要有下面两个方法

//从coder中读取数据,保存到相应的变量中,即反序列化数据 -(id)initWithCoder:(NSCoder *)coder; // 读取实例变量,并把这些数据写到coder中去。序列化数据 -(void)encodeWithCoder:(NSCoder *)coder;

NSCoder 是一个抽象类,抽象类不能被实例话,只能提供一些想让子类继承的方法。

//从二进制流读取对象。 NSKeyedUnarchiver //把对象写到二进制流中去。 NSKeyedArchiver

一个简单的例子

#import <Foundation/Foundation.h> @interface Person : NSObject { NSString *name; char sex; int age; } @property(nonatomic,copy) NSString *name; @property char sex; @property int age; @end

person.m实现文件

#import "Person.h" @implementation Person @synthesize name,age,gender; -(void)encodeWithCoder:(NSCoder *)aCoder { [aCoder encodeObject:name forKey:@"stuName"]; NSNumber *age1 = [NSNumber numberWithInt:age]; [aCoder encodeObject:age1 forKey:@"stuAge"]; NSNumber *gender1 = [NSNumber numberWithChar:gender]; [aCoder encodeObject:gender1 forKey:@"stuGender"]; } -(id)initWithCoder:(NSCoder *)dCoder { name = [dCoder decodeObjectForKey:@"stuName"]; age = [[dCoder decodeObjectForKey:@"stuAge"]intValue]; gender = [[dCoder decodeObjectForKey:@"stuGender"]charValue]; return self; } @end

main.m测试文件

#import <Foundation/Foundation.h> #import "Person.h" int main(int argc, const char * argv[]) { @autoreleasepool { Person *p1 = [[Person alloc]init]; p1.name = @"zhangsan"; p1.age = 22; p1.gender = 'F'; Person *p2 = [Person new]; p2.name = @"lisi"; p2.age = 23; p2.gender = 'M'; NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithCapacity:30]; [dic setObject:p1 forKey:@"person1"]; [dic setObject:p2 forKey:@"person2"]; //把字典内容存入到文件中 if ([NSKeyedArchiver archiveRootObject:dic toFile:@"/Users/mac/Desktop/a.plist"] ) { NSLog(@"chenggong"); } NSMutableDictionary *dic2 = [NSMutableDictionary dictionaryWithCapacity:30]; //从文件中读取内容放入到字典中 dic2 = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/Users/mac/Desktop/a.plist"]; NSEnumerator *enumerator = [dic2 objectEnumerator]; id obj; //遍历字典内容 while (obj = [enumerator nextObject]) { NSLog(@"name = %@,age = %i,gender = %c",[obj name],[obj age],[obj gender]); } } return 0; }
转载请注明原文地址: https://www.6miu.com/read-4832014.html

最新回复(0)