OC特点
- 支持C语法
- 支持面向对象特性
- 兼容性好,可以同时在项目中使用OC、C++,也可以引入C、C++库文件
- OC中没有命名空间机制,也没有包的概念,为了区分不同的类,在类名加前缀
- OC中关键字表示都以@开头,用于区分C和C++的关键字,字符串也以@开头,如@public、@protected、@private、@”Hello World”
文件名后缀
语言 | 头文件后缀 | 主文件后缀 |
---|---|---|
c | .h | .c |
c++ | .h | .cpp |
oc | .h | .m |
oc与c++ | .h | .mm |
OC基本数据类型
-
OC支持C语言中所有的数据类型。
基本数据类型:int、double、float、char等
构造类型:数组、结构体、枚举
空类型:void
typedef自定义类型 -
BOOL类型
YES、NO -
Boolean类型
true、false -
class 类型
-
id 类型
-
nil
-
SEL
-
block
类与属性
1、 类的声明语法
@interface Person : NSObject{
属性声明
}
方法声明
@end
特点:
- @interface:相当于Java中的class
- 类名后面的冒号:相当于Java中的extends
2、类的实现语法
@implementation XYZPerson
方法实现{
}
@end
3、完整例子
Person.h
# import <Foundation/Foundation.h>
@interface Person : NSObject{
@public
NNString *_name;
int _age;
}
//两种多个参数写法
- (void)eat:(NNString *)foodName:(NNString *)foodName2;
- (void)eat2:(NNString *)foodName and:(NNString *)foodName2;
@end
Person.m
# import <Foundation/Foundation.h>
@implementation Person
- (void)eat:(NNString *)foodName:(NNString *)foodName2
{
NSLog(@"我爱吃%@和%@",foodName,foodName2);
}
- (void)eat2:(NNString *)foodName and:(NNString *)foodName2
{
NSLog(@"我爱吃%@和%@",foodName,foodName2);
}
@end
4、创建对象
//第一种创建方式:创建一个可用的对象
Person *p=[Person new];
//new方法的内部会分别调用两个方法来完成2件事情
//1、使用alloc方法来分配存储空间(返回分配的对象)
//2、使用init方法来对对象进行初始化
//1、调用类方法+alloc分配存储空间,返回未经初始化的对象
Person *p1=[person alloc];
//2、调用对象方法-init进行初始化,返回对象本身
Person *p2=[p1 init];
//第二种创建方式:以上2步简化为
Person *p=[[Person alloc] init];
//默认初始化完毕后,所有成员变量的值都为0
//用完对象要释放内存
[lisi release];
究竟new方式和alloc/init方式有什么区别?
- new和alloc/init在功能上是一致的,分配内存并完成初始化
- 采用new方式只能采用默认的init方法完成初始化
- 采用alloc的方式可以用自定义的构造方法完成初始化
5、访问对象属性
//调用类的属性,语法:对象->属性名
p->_age;
p->_name;
//或者:(*对象名).对象属性
(*p)._name
6、调用方法
//调用无参方法,语法:[对象名 方法名]
[p eat]
//调用有参方法,语法:[对象名 方法名:参数]
[p eat:@"吃虾"and:@"红烧肉"]
//[p eat:@"吃虾":@"红烧肉"]
//[p eat:@"吃虾":@"红烧肉"]
7、@property和@synthesize
在头文件中声明属性
//编译器会自动补出其set和get方法
@property int age;
在m文件中实现
//编译器会自动生成set和get方法的实现,默认已经自动@synthesize属性的值
@synthesize age;
构造方法
1、默认的构造方法
- (instancetype)init{
if(slef = [super init]){
//初始化
}
return self;
}
2、自定义构造方法
一般构造方法都以init开头,这样并不是复写系统默认的构造方法,而是再添加一个构造方法
- (instancetype)initWithDict:(NSDictionary *)dict{
if(slef = [super init]){
//初始化并赋值
self.name = dict[@"name"];
}
return self;
}
函数
1、减号表示对象方法,语法:-(返回值类型)方法名:(参数类型)参数名
@interface Person : NSObject
-(Void) someMethod;
-(Void) someMethodWithValue:(someType)Value;
@end
特点:
- 函数的返回类型和参数类型必须用括号
- 函数的形参用冒号表示
2、加号表示静态方法(类方法),语法:+(返回值类型)方法名:(参数类型)参数名
@interface NSString: NSObject
+(id) string;
+(id) stringWithString:(NSString *)astring;
+(id) stringWithFormat:(NSString *)format,...;
@end
区别:
- 对象方法可以直接访问属性,静态方法不能访问属性
- 静态方法可用类名直接调用方法,而对象方法不行
点语法
声明对象并提供get和set方法
#import <Foundation/Foundation.h>
@interface Person : NSObject{
int _age;
}
- (void)setAge:(int)age;
- (int)age;
@end
实现对象
#import "Person.h"
@implementation Person
- (void)setAge:(int)age{ //set方法
_age = age;
}
- (int)age{ //get方法
return _age;
}
@end
点语法的使用
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]){
@autoreleasepool {
Person *person = [[Person alloc] init];
person.age = 10;//点语法,等效与[person setAge:10];
//这里并不是给person的属性赋值,而是调用person的setAge方法
int age = person.age;//等效与int age = [person age];
//这里调用person的set方法
NSLog(@"age is %i", age);
[person release];
}
return 0;
}
为什么有些使用_age,有些语法使用self.age?
属性值:_age
点语法:self.age
- 下划线是一种编程规范,_age是直接拿到age这个属性,不通过getAge方法获取,建议在init里面使用_age
- self.age相当于调用[self getAge],系统自动生成的代码(_age = age),其实也是_age,如果你重写了getAge方法,返回的值就不一样了
静态变量
1、OC与Java或C的区别
- OC中的静态变量:它是私有的全局变量,不能直接通过类名访问,它只作用于它声明所在的.m文件中
- C或者Java中的静态变量:可以直接通过类名拿到这个变量,在其他类中可以进行修改
2、静态变量全局化
不是说OC中静态变量不能使用在其他类中,可以通过静态方法向外提供该静态变量,在h文件中定义静态变量和向外提供静态变量的方法。
#import <UIKit/UIKit.h>
//静态变量
static int selectIndex;
@interface TBC_SendPassword : UITabBarController
//提供静态变量
+(int)getSelectIndex;
@end
在m文件中覆写该方法,提供静态变量,你可以在m文件中修改对应的selectIndex的值
+(int)getSelectIndex{
return selectIndex;
}
在其他类中需要使用该类的静态变量,首先在h文件中导入头文件
在m文件中直接通过静态的方法的使用,获取对应的值
#import "TBC_SendPassword.h"
if([TBC_SendPassword getSelectIndex] != 0){
return;
}
NSLog
//定义一个字符串,str存放是内存地址
NSString *str = "你好";
NSLog(@"str的地址=%p,str的值=%@",str,str);
//打印OC字符串要用@""
NSLog(@"Hello OC");
//用C语言打印字符串
printf("Hello OC");
***注意:***不能用C语言打印OC字符串,也不能用OC语言打印C字符串
NSString
//创建字符串
NSString * str = @"Hello";
//字符串长度,OC中英文都占1个字节
[str length]
//创建字符串对象
NSString * str1 = [NSString new]
//复制字符串
NSString * str2 = [[NSString malloc]initWithString:str];
//格式化字符串
NSString * str3 = [NSString stringWithFormat:@"图片 xx %02d- %02d",1,9];
//字符串拼接
NSString *newString = [NSString stringWithFormat:@"%@%@",str1,str2];
NSArray
//常用的创建方式
NSArray *array1 = [[NSArray alloc] initWithObjects:@“1”,@“2”,@“3”,@“4”,@“5”, nil];
NSArray *array2 = @[@“a”,@“b”,@“c”];
NSArray *array3 = [[NSArray alloc] initWithArray: array1];
NSArray *array4 = [[NSArray alloc] initWithContentsOfFile:@""];
NSArray *array5 = [[NSArray alloc] initWithContentsOfURL:[NSURL URLWithString:@""]];
//数组的长度
int count = (int)array1.count;
//取出数组中最后一个元素
NSString *str = [array1 lastObject];
//取出数组中首个元素
str = [array1 firstObject];
//根据下标取出数组中的元素
str = [array1 objectAtIndex:3];
//获取元素在数组中对应的下标(如果元素不存在,则输出-1)
int index = (int)[array1 indexOfObject:@“3”];
NSMutableArray
NSMutableArray是长度可变数组,也就是说当数组前面的元素被删除后,后面的元素会往前移,而NSArray是长度不可变数组
//创建NSMutableArray
NSMutableArray *mArray = [NSMutableArray array];
//添加元素
[mArray addObject:@"name"];
//移除元素
[mArray removeObject:@"name"];
//移除所有元素
[mArray removeAllObjects];
//取出元素
mArray[2];
强制类型转换
//字符转int
int intString = [newString intValue];
//int转字符
NSString *stringInt = [NSString stringWithFormat:@"%d",intString];
//字符转float
float floatString = [newString floatValue];
//float转字符
NSString *stringFloat = [NSString stringWithFormat:@"%f",intString];
NSBundle
NSBundle是一个目录,其中包含了程序会使用到的资源,相当于项目中的主目录文件夹,NSBundle用得最多的是获取Plist文件,并获取Plist的内容,Plist文件可以简单理解为小数据库类型的文件,它在项目初始化时默认会创建一个info.plist文件,里面会存储系统的默认配置信息
//打印沙盒路径
NSLog(NSHomeDirectory());
//创建NSBundle
NSBundle *bundle = [NSBundle mainBundle];
//获取NSBundle里myPic.png文件的路径的两种方法
NSString *path = [mainBundle pathForResource:@"myPic" ofType:@".png"];
NSString *path = [mainBundle pathForResource:@"myPic.png" ofType:nil];
//获取NSBundle里的Plist文件
NSString *plistPath = [mainBundle pathForResource:@"myList.plist" ofType:nil];
//通过Plist路径获取字典
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:plistPath];
//通过Plist路径获取数组
NSArray *array = [NSArray arrayWithContentsOfFile:plistPath];
kvc
OC中的KVC操作就和Java中使用反射机制去访问类中private权限的变量一样
1、kvc与对象
单个对象赋值:通过kvc的方式,可以省去自动解包和装包操作
//通过kvc方式设置属性
Person *p = [[Person alloc] init];
[p setValue:@"jiangwei" forKey:@"name"];
[p setValue:@22 forKey:@"age"];
//通过kvc方式读取属性
NSString *name = [p valueForKey:@"name"];
单个对象对对象赋值:对象中包含另一个对象
Book *book = [[Book alloc] init];
Author *author = [[Author alloc] init];
//通过kvc方式设置对象
[book setValue:author forKey:@"author"];
单个对象对数组赋值:对象中存在数组属性,数组装的是另一个对象
//author中的issueBook字段是个NSArray
//通过kvc方式获取数组的大小,语法:NSArray.@count
NSNumber *count = [author valueForKeyPath:@"issueBook.@count"];
//通过kvc方式获取书籍价格的总和,语法:NSArray.@sum+字段名
NSNumber *sum = [author valueForKeyPath:@"[email protected]"];
//通过kvc方式获取书籍的平均值,语法:NSArray.@avg+字段名
NSNumber *avg = [author valueForKeyPath:@"[email protected]"];
//通过kvc方式获取书籍的价格最大值和最小值,语法:NSArray.@max+字段名
NSNumber *max = [author valueForKeyPath:@"[email protected]"];
NSNumber *min = [author valueForKeyPath:@"[email protected]"];
2、kvc与字典
通过获取字典字段,将字典转换为属性
self.name = dict[@"name"];
self.icon = dict[@"icon"];
通过kvc方式进行赋值,自动将字段与属性匹配,前提是字段名和字典名必须相同
[self setValuesForKeysWithDictionary:dict];
日期格式化
//取出当前时间
NSDate *currentDate = [NSDate date];
//设置时间格式
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
//时间的格式
formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
//获取时间的字符串
NSString *date = [formatter stringFromDate:currentDate];