iOS入门学习笔记

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文件的扩展名保存为plist
  • writeToFile只能写入数组中保存的元素都是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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值