基于
Objective-C基础教程:1天玩转Objective-C语法
【C基础】#if、if、#ifdef、#if defined之间的区别
成员变量和属性区别(@property那点事儿)
- Foundation/Foundation.h是 Foundation 框架的头文件,只要引入了它,就可以使用 Foundation 框架的所有功能了。这是一个核心库
- 在 oc 中,字符串必须要加@,比如:@"hello world"
- Foundation框架中的很多数据类型名、变量名、函数名都是以NS开头,乔布斯以此来纪念自己的公司 NeXTSTEP。
- 头文件(.h)中定义的属性和方法才能被外界访问,类实现文件(.m)中定义的不能被外界访问
- 类在.h文件和.m文件中都可以引入头文件,区别是:在.h文件中引入头文件,.h和.m文件都可以使用这个文件中的资源;如果在.m文件引入头文件,.h文件不能使用该文件中的资源。
- 类定义举例:
#import <Foundation/Foundation.h>
//引入头文件
@interface Person : NSObject{
//声明成员变量(很少用,如果没有声明成员变量的话,可以省略大括号。)
}
//声明属性
@property int age;//基本数据类型(默认会生成对应的 set 和 get 方法。另外会默认生成对应的成员变量_age);语法规定,不能初始化
@property (NSString*) str;//对象类型或引用类型
//声明方法之类方法的创建(+号):
+(int)personWithA1:(float)a1 andA2:(NSString*)a2; //a1,a2分别代表两个参数
//声明方法之对象方法的创建(-号):
-(int)personWithA1:(float)a1 andA2:(NSString*)a2;
@end
- 类实现举例:
#import "Person.h"
//引入头文件
@implementation Person
//对声明的方法进行实现
@end
- 方法调用:(在 oc 中,准确的说是“ 消息传递”)
//调用类方法
[Person personWithA1:2 andA2:@"类方法"];//通过类直接调用
//调用对象方法
Person * obj1=[[Person alloc]init];
[obj1 personWithA1:1 andA2:@"对象方法"];//通过类对象调用
- 点语法的底层实现:(点语法,简单的理解,就是通过“.”的方式通过调用类中的set或get方法操作属性。)重点在于如何改写 set 和 get 方法。
我们写的代码:
//.h 文件
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property NSString * name;
@end
//.m 文件
#import "Person.h"
@implementation Person
@end
完整实现:
//.h 文件
#import <Foundation/Foundation.h>
@interface Person : NSObject{
//编写习惯,一般声明成员变量的时候名字前面加“_”,同时也是为了和下边声明的name相对应。
NSString * _name;
}
@property NSString * name;//通过这行代码,OC底层隐式地声明了两个方法: set 和 get 方法
@end
//.m 文件
#import "Person.h"
@implementation Person
@synthesize name=_name;//将_name和name进行绑定;对在.h文件声明的get方法和set方法做实现
@end
- @propertye常用的修饰词
nonatomic、copy、strong、assign、weak、readwrite、readonly等
assign:用于基础类型
copy:一般使用于字符串,再复制一份
weak:弱引用。
- 有个比喻:对于weak来说,就相当于旁边看放风筝的人,他们只能用手指着你手里的风筝,大喊着“风筝风筝”,他们只能和你一起欣赏风筝,而对于是不是继续放风筝的决定权在你,如果你不在放风筝了,那他们也只能“各回各家,各找各妈”;
- 用OC的语言来表达,就是说用weak声明的属性虽然也可以访问内存,但是要在这块内存没有释放之前,一旦这块内存被释放之后,weak声明的属性将失去作用。
- 结构体是值类型
在OC中struct是值类型的,也就是说当将一个结构体赋值给另一个结构体时,二者实际上是相互独立互不影响的。
直接访问使用结构体变量名.成员名,间接访问使用(*结构体指针名).成员名或者使用结构体指针名->成员名。(总结来说,通过值访问就用点符号,通过指针访问就用->) - id 类型:可以认为是任意类型
- SEL 类型:可以认为是方法的指针类型。在 oc 中表示方法的编号
- 类别:
- 类别能够在原有类的基础上添加新的方法,而且还不会让子类继承。
- 类扩展能添加属性和方法,而类别只能添加方法
定义:
//Person+NewFuntion.h文件
#import "Person.h"
@interface Person (NewFuntion)
//添加方法
-(void)eat;
@end
实现:
#import "Person+NewFuntion.h"
@implementation Person (NewFuntion)
//实现方法
-(void)eat{
NSLog(@"the person is eating!");
}
@end
使用:
#import <Foundation/Foundation.h>
#import "Person.h"
//一定要引入类别的接口文件,否则无法使用类别中添加的方法
#import "Person+NewFuntion.h"
int main(int argc, const char * argv[]) {
Person * person=[[Person alloc] init];
person.name=@"张三";
person.age=10;
[person run];
//调用类别中增加的eat方法
[person eat];
return 0;
}
- 协议:OC语言是单继承多协议的语言(类型于 java 中的接口)
- 协议没有父类(协议可以服从多个(>=0)协议(一般服从NSObject协议)
- 协议中不能定义变量(属性),只能定义方法。
声明一个协议:
@protocol ChildrenDelegate <NSObject>//协议声明
-(void)eat;
@end
声明一个符合此协议的对象属性
@interface Children : NSObject
@property(nonatomic,weak)id<ChildrenDelegate>delegete;//一个实现此协议的任意类型的对象属性
@end
真正实现此协议的类
@interface Nanny : NSObject<ChildrenDelegate>
@end
综合使用:
int main(int argc, const char * argv[]) {
Children * child=[[Children alloc] init];
Nanny * nanny=[[Nanny alloc] init];
child.delegete=nanny;
if ([child.delegete respondsToSelector:@selector(eat)]) {
[child.delegete eat];
}
return 0;
}
@selector(eat)返回 eat 方法的编号,它是个 SEL 类型
- oc 中的数组对象,键和值都必须是对象
- oc 中的数组,以如下形式初始化,必须以 nil 结束,代表数组的结尾。如:
NSArray * array1=[NSArray arrayWithObjects:@"0",@"1",@"2",@"3", nil];
- 在使用代码块的时候,对于全局变量,在块内是完全可操作的。但是对于局部变量来说,在块内只能使用不能更改。
如果试图在块内更改局部变量的值,程序会报错,解决的方案是在声明局部变量时添加_block关键字(注意是两个“”) - nil, NULL, Nil 的区别:
nil定义某一实例对象为空值,如NSObject* obj = nil;
Nil 定义某一类为空,如Class someClass = Nil;
NULL 定义基本数据对象指针为空,如int *pointerToInt = NULL; char *pointerToChar = NULL; struct TreeNode *rootNode = NULL;
延申阅读:
-
自动引用计数:
https://blog.devtang.com/2016/07/30/ios-memory-management/
https://juejin.im/post/5a360d2d518825455f2f5df6 -
结构体是什么:https://zh.wikipedia.org/wiki/%E7%BB%93%E6%9E%84%E4%BD%93_(C%E8%AF%AD%E8%A8%80)
-
OC 中的结构体及精彩评论:https://www.jianshu.com/p/f1b2085c4179
-
c 语言中的指针:https://zhuanlan.zhihu.com/p/28041871
声明一个指针类型的变量:
int *pInt = NULL
表示 pInt这个变量的值是数据或对象的指针地址的值,在这里是 NULL,代表空指针。
int 表示,pInt这个指针指向的数据或对对象是 int 类型的
使用的时候,*pInt 表示pInt这个指针变量指向的数据或对象的值。
使用的时候,@pInt 表示在内存中存储 pInt 这个值的内存地址是多少。在这里pInt 本身就是一个指针值,@pInt表示指向这个指针值的指针地址是多少。
网友评论