黑马程序员——0C语言——核心语法

———Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ———
一、点语法
本质是方法的调用,用在setter和getter的方法调用中。
Person *p = [Person new];
p.age = 10;  // [p setAge:10];
int a = p.age;  // [p age];

二、成员变量的作用域

@private 在当前类的对象方法中访问

@protected 可以在当前类及其子类的对象方法中访问(默认)

@public 在任何地方都能直接访问对象的成员变量

@package 只要处在同一个框架中,就能直接访问对象的成员变量


三、@property和@synthesize

1、property

可以自动生成某个成员变量的setter和getter方法(包括声明和实现)。

// 自动生成age的setter和getter方法,并自动生成@private类的_age变量

@property int age;

// - (void) setAge:(int)age;

// - (void)age;

使用注意:

1> 如果手动实现了setter方法,编译器就只会自动生成getter方法

2> 如果手动实现了getter方法,编译器就只会自动生成setter方法

3> 如果手动实现了setter和getter方法,编译器就不会自动生成不存在的成员变量

2、synthesize

可以自动生成某个成员变量的setter和getter方法的实现。

//生成age的setter和getter方法的实现,并访问_age这个成员变量

@synthesize age = _age;

- (void)setAge:age

{

_age = age;

}

- (int)age

{

return _age;

}

//默认会访问age这个变量,若没有则自动生成@private类的age变量

@synthesize age;


四、id

id,万能指针,能指向、操作任何的OC对象,只适用于OC对象。

本质:typedef NSObject * id; // id == NSObject *

id后面不用加*。

注意:id类型不能使用点语法。

Person *p = [Person new];

p.age = 20;

id d = [Person new];

[d setAge:10];


五、构造方法

构造方法:用来初始化对象的方法,是个对象方法,以 - 开头。

1、new方法

[Person new]等价于[[Person allot] init]

Person *p =[Person new];

// 调用+allot方法分配存储空间,返回分配好内存的对象

Person *p1 = [Person allot];

// 调用-init方法初始化,返回已经初始化的对象

Person *p2 = [p1 init];

// 合并

Person *p3 = [[Person allot] init];

2、重写构造方法

为了让对象创建出来,成员变量就会有一些固定的值

1> 先调用父类的构造方法[super init];

2> 再进行子类内部成员变量的初始化。

@implementation Person

- (id)init

{

// 调用父类init方法:初始化父类中的一些成员变量和其他属性

// 若对象初始化成功,则继续对成员变量初始化

if (self = [super init])

_age = 20;

// 返回初始化对象
return self;

}

3、自定义构造方法

1> 一定是对象方法,以 - 开头;

2> 返回值一般都是id类型;

3> 方法名一般以initwith开头。

#import <Foundation/Foundation.h>

// 父类

@interface Person : NSObject

@property NSString *name;

@property int age;

- (id)initWithName:(NSString *)name andAge:(int)age;

@end

@implementation Person

- (id)initWithName:(NSString *)name andAge:(int)age

{

if ( self = [super init] )

{

_name = name;

_age = age;

}

return self;

}

@end

// 子类

@interface Student : Person

@property int no;

- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no;

@end

@implementation Student

- (id)initWithName:(NSString *)name andAge:(int)age andNo:(int)no

{

// 父类的成员变量交给父类去初始化

if ( self = [super initWithName:name andAge:age] )

{

_no = no;

}

return self;

}

@end


六、分类Category

1、分类的格式

1> 分类的声明

@interface 类名 (分类名称)

方法声明

@end

2> 分类的实现

@implementation 类名 (分类名称)

方法实现

@end

2. 分类的使用注意:

1> 分类只能增加方法,不能增加成员变量;

2> 分类方法实现中,可以访问原来类中声明的成员变量;

3> 分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法;

4> 方法调用的优先级:分类(最后参与编译的分类优先) > 原来的类 > 父类;

5> 分类和继承都是在不改变原来模型的情况下,给类扩充一些方法。


#import <Foundation/Foundation.h>

// 给NSString添加分类

@interface NSString (NumberCount)

+ (int)numberCountOfSttring:(NSString *)str;

- (int)numberCount;

@end

@implementation NSString (NumberCount)

// 类方法,计算某个字符串中数字的个数

+ (int)numberCountOfSttring:(NSString *)str

{

int count = 0;

// 遍历

for (int i = 0; i < str.length; i++)

{

//characterAtIndex:i 返回下标是i的字符

unichar c = [str characterAtIndex:i]

if ( c >= '0' && c <= '9' )

count++;

}

return count;

}

// 对象方法,计算这个字符串中数字的个数

- (int)numberCount

{

int count = 0;

for (int i = 0; i < self.length; i++)

{

unichar c = [self characterAtIndex:i]

if ( c >= '0' && c <= '9' )

count++;

}

return count;

}

@end


七、类的本质

1、类对象

类也是一个对象,是Class类型的对象,简称“类对象”。

类对象的本质:typedef struct objc_class *Class;

类名就代表类对象,一个类只能有一个类对象。

Person *p = [[Person allot] init];

Class c = [p class];

// [Person test]

[c test];

获取类对象的2种方式

类方法:

Class c = [Person class];

对象方法:

Class c2 = [p class];

类对象调用方法

Class c = [Person class];

Person *p2 = [c new];


2、+load和+initialize

+ load

在程序启动时会加载所有的类和分类,并调用每个类和分类的+load方法。

加载顺序:先加载父类,在加载子类,最后加载分类。

不管程序有没有用到这个类,都会调用+load这个方法把类加载进来。

+ initialize

当第一次使用某个类时,就会调用当前类的+initialize方法,只会调用一次。

调用顺序:先调用(初始化)父类的,再调用(初始化)子类。

#import <Foundation/Foundation.h>   
@interface Person : NSObject  
@property int age;   
+ (void)test;  
@end  
  
@implementation Person  
+ (void)test  
{  
SLog(@"调用了test类方法");  
}  
  
// 当程序启动的时候,就会加载一次项目中所有的类,类加载完毕后就会调用+load方法  
// 先加载父类,再加载子类  

+ (void)load  
{  
    NSLog(@"Person load");  
}  
    N
  
// 当第一次使用这个类的时候,就会调用一次initialize方法  
+ (void)initialize  
{  
    // 监听  
    NSLog(@"Person initialize");  
}  

@end  

3、description方法

1> - description方法

使用NSLog和%@输出某个对象时,会调用对象的-description方法,

并拿到返回值进行输出(类名:内存地址)

2> + description方法

使用NSLog和%@输出某个类对象时,会调用类对象+description方法,

并拿到返回值进行输出(类名)

3> 修改NSLog的默认输出
重写-description或者+description方法即可
4> 死循环陷阱
如果在-description方法中使用NSLog打印self
// 决定了实例对象的输出结果 
- (NSString *)description  
{  
    // NSLog(@"%@", self);// 死循环  
      
    return [NSString stringWithFormat:@"age=%d, name=%@", _age, _name];  
}  
  
// 决定类对象的输出结果 
+ (NSString *)description  
{  
    return NSStringFromClass([self class]);  

}  

4、SEL

每个类的方法列表都封装在类对象中,

每个方法都有一个与之对应的SEL类型的对象,

根据这个SEL对象就能找到方法的地址,然后调用方法。

SEL类型的本质:typedef struct objc_selector *SEL;

1> SEL对象的创建

SEL s1 = @selector(方法名);  

// NSString对象转换为SEL对象

SEL s2 = NSSelectorFromString(@"方法名");


2> SEL对象的使用

// 将SEL对象转换为NSString对象  

NSString *str = NSStringFromSelector(@selector(方法名));  

// 调用对象p的test方法:  

Person *p = [[Person alloc] init];  

[p performSelector:@selector(test)];  

3> _cmd

_cmd 代表当前方法的SEL,每个方法内部都有这么一个变量。

- (void)test2  

{  

   // 死循环  

    // [self performSelector:_cmd];  

    NSString *str = NSStringFromSelector(_cmd);

    NSLog(@"test2.., _cmd=%@", str);  

5、NSLog输出增强

NSLog(@"%d", __LINE__);// 代码当前行号
// NSLog输出C语言字符串的时候,不能有中文  
// NSLog(@"%s", __FILE__);// 输出不成功!(可以先做转换)  
printf("%s\n", __FILE__);// 当前文件路径  

NSLog(@"%s", __func__);// 当前函数名 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值