------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-------
一、点语法
1、说明
点语法的本质是方法调用,注意不是访问成员变量。
2、举例说明
Person *p = [Person new];
p.age = 10; // [psetAge:10]; set方法
int a = p.age; // [p age]; get方法
3、注意
在对象方法内使用该对象方法的点语法会引发死循环。例如:
- (void)setAge:(int)age
{
//会引发死循环
/self.age= age; // [self setAge:age];
}
二、成员变量作用域
1、说明
成员变量的作用域规定了方法访问成员变量的一种权限,即方法可以在哪里访问成员变量。一共有四种成员变量作用域:
2、成员变量作用域分类:
@public : 在任何地方都能直接访问对象的成员变量。
@private : 只能在当前类的对象方法中直接访问(@implementation中默认是@private)(理解:只会包含.h文件)。
@protected : 可以在当前类及其子类的对象方法中直接访问 (@interface中默认就是@protected)。
@package : 只要处在同一个框架中,就能直接访问对象的成员变量。
3、注意
没有类的声明,只有类的实现也可以,类的实现中既可以有成员变量也可以有方法
子类不能访问父类私有的成员变量,但是其内有这个私有的成员变量,只是不能直接通过方法来访问而已。可以通过断点调试来查看。
@implementation中不能定义和@interface中同名的成员变量
子类不能访问父类私有的成员变量,但是其内有这个私有的成员变量,只是不能直接通过方法来访问而已。可以通过断点调试来查看。
@implementation中不能定义和@interface中同名的成员变量
三、@property和@synthesize
1、@property
@property作用:用在@interface中,@property可以自动生成某个成员变量的set方法和get的方法声明,如果没有改成员变量则会生成成员变量。
举例说明:@propertyint age;相当于-(void)setAge:(int)age;和- (int)age;并且生成_age的成员变量。
2、@synthesize的作用
@synthesize的作用:用在@plementation中,@synthesize自动生成setter和getter实现,并且会访问这个成员变量。
举例说明:@synthesize speed = _speed;会访问_speed这个成员变量,如果不存在,就会自动生成@private类型的_speed变量
3、使用细节
在类的声明中不写成员变量speed,如有@property或者@synthesize就会自动生成_speed的成员变量。
@synthesize age;默认访问age这个成员变量,不是_age成员变量。如果没有age就会自动生成private类型的age。如果已经有get或者set方法则会尊重手动的;
4、程序示例和运行结果
// Car.h
#import <Foundation/Foundation.h>
@interface Car : NSObject
{
//int _speed;
//int _wheels;
}
@property int speed;
@property int wheels;
//@property int speed, wheels;
- (void)test;
@end
// Car.h
#import <Foundation/Foundation.h>
@interface Car : NSObject
{
//int _speed;
//int _wheels;
}
@property int speed;
@property int wheels;
//@property int speed, wheels;
- (void)test;
@end
四、id
id是一种数据类型能指向\操作任何OC对象,相当于id= NSObject *。
例如:id d = [Person new];
五、构造方法
1、构造方法概念
构造方法是用来初始化对象的方法,是个对象方法,-开头。完整地创建一个可用的对象先调用+alloc分配存储空间(Person *p1 = [Person alloc];)然后调用-init进行初始化(Person *p2 = [p1 init];)。
重写构造方法的目的是为了让对象创建出来,成员变量就会有一些固定的值。
2、重写构造方法
重写-init方法过程
- (id)init
{
// 1.一定要调用回super的init方法。目的:初始化父类中声明的一些成员变量和其他属性
self =[super init]; // 返回当前对象 self
//2.如果对象初始化成功,才有必要进行接下来的初始化
if (self != nil)
{ // 初始化成
_age = 10;
}
//3.返回一个已经初始化完毕的对象
return self;
}
3、重写构造方法的注意点
先调用父类的构造方法([super init])
再进行子类内部成员变量的初始化
4、程序示例和运行结果
// main.m
// 自定义构造方法
//
// Created by 高德迎 on 14/11/24.
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
Student *stu = [[Student alloc] initWithNo:2 andAge:23 andName:@"gaodeying"];
int a = stu.no;
NSLog(@"%d",a);
return 0;
}
// Person.h
// 自定义构造方法
//
// Created by 高德迎 on 14/11/24.
// Copyright (c) 2014年 高德迎. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property int age;
@property NSString *name;
- (id)initWithAge:(int)age andName:(NSString *)name;
@end
// Person.m
// 自定义构造方法
//
// Created by 高德迎 on 14/11/24.
// Copyright (c) 2014年 高德迎. All rights reserved.
//
#import "Person.h"
@implementation Person
- (id)initWithAge:(int)age andName:(NSString *)name
{
if( self = [super init] )
{
_age = age;
_name = name;
}
return self;
}
@end
//
// Student.h
// 自定义构造方法
//
// Created by 高德迎 on 14/11/24.
// Copyright (c) 2014年 高德迎. All rights reserved.
//
#import "Person.h"
@interface Student : Person
@property int no;
-(id)initWithNo:(int)no andAge:(int)age andName:(NSString *)name;
@end
//
// Student.m
// 自定义构造方法
//
// Created by 高德迎 on 14/11/24.
// Copyright (c) 2014年 高德迎. All rights reserved.
//
#import "Student.h"
@implementation Student
-(id)initWithNo:(int)no andAge:(int)age andName:(NSString *)name
{
if(self = [super initWithAge:age andName:name])
{
_no = no;
}
return self;
}
@end
六、更改Xcode模板
更改命令行路径:mac源 ▸ 应用程序 ▸ Xcode.app ▸ Contents ▸ Developer ▸ Library ▸ Xcode ▸ Templates ▸ Project Templates ▸ Mac ▸ Application ▸ Command Line Tool.xctemplate
更改main路径:mac源 ▸ 应用程序 ▸ Xcode.app ▸ Contents ▸ Developer ▸ Library ▸ Xcode ▸ Templates ▸ File Templates ▸ Source ▸ Cocoa Class.xctemplate
更改xcode命令行后的效果,图3
如图
七、分类
1、分类的作用
在不改变原来类内容的基础上,可以为类增加一些方法
2、使用分类注意点
分类只能增加方法,不能增加成员变量
分类方法实现中可以访问原来类中声明的成员变量
分类可以重新实现原来类中的方法,但是会覆盖掉原来的方法,会导致原来的方法没法再使用
方法调用的优先级:分类(最后参与编译的分类优先) --> 原来类 --> 父类
3、分类的书写格式
分类的声明
@interface 类名 (分类名称)
// 方法声明
@end
分类的实现
@implementation 类名 (分类名称)
// 方法实现
@end
4、使用分类的好处
一个庞大的类可以分模块开发
一个庞大的类可以由多个人来编写,更有利于团队合作
5、示例程序及运行结果(给系统自带的类添加分类)
给NSString增加一个类方法:计算某个字符串中阿拉伯数字的个数
给NSString增加一个对象方法:计算当前字符串中阿拉伯数字的个数
// main.m
#import <Foundation/Foundation.h>
#import "NSString+Number.h"
int main()
// 类库:很多类的集合
{
// int count = [NSString numberCountOfString:@"54d43a43s43dasd"];
int count = [@"9fdsfds543543" numberCount];
NSLog(@"%d", count);
return 0;
}
//
// NSString+Number.h
// 05-分类的应用
#import <Foundation/Foundation.h>
@interface NSString (Number)
+ (int)numberCountOfString:(NSString *)str;
- (int)numberCount;
@end
// NSString+Number.m
#import "NSString+Number.h"
@implementation NSString (Number)
// @"abc434ab43"
+ (int)numberCountOfString:(NSString *)str
{
// 1.定义变量计算数字的个数
// int count = 0;
//
// for (int i = 0; i<str.length; i++)
// {
// unichar c = [str characterAtIndex:i];
//
// if ( c>='0' && c<='9')
// {
// count++;
// }
// }
// return count;
return [str numberCount];
}
- (int)numberCount
{
int count = 0;
for (int i = 0; i<self.length; i++)
{
// 取出i这个位置对应的字符
unichar c = [self characterAtIndex:i];
// 如果这个字符是阿拉伯数字
if ( c>='0' && c<='9' )
{
count++;
}
}
return count;
}
@end
运行结果:7。
八、类的本质
1、说明
其实类也是一个对象,是Class类型的对象,简称“类对象”
Class类型的定义
typedef struct objc_class *Class;
类名就代表着类对象,每个类只有一个类对象
2、类的运行过程
当程序启动时,就会加载项目中所有的类和分类,而且加载后会调用每个类和分类的+load方法。只会调用一次。
当第一次使用某个类时,就会调用当前类的+initialize方法
先加载父类,再加载子类(先调用父类的+load方法,再调用子类的+load方法)
先初始化父类,再初始化子类(先调用父类的+initialize方法,再调用子类的+initialize方法)
3、获取类对象的2种方式
Class c = [Person class]; // 类方法
或者
Person *p = [Person new];
Class c2 = [p class]; // 对象方法
4、类对象调用类方法
Class c = [Person class];
Person *p2 = [c new];
九、description
1、-description方法
使用NSLog和%@输出某个对象时,会调用对象的-description方法,并拿到返回值进行输出
2、+ description方法
使用NSLog和%@输出某个类对象时,会调用类对象+description方法,并拿到返回值进行输出
3、修改NSLog的默认输出
重写-description或者+description方法即可
4、死循环陷阱
如果在-description方法中使用NSLog打印self
十、NSLog
//输出输出行号
NSLog(@"%d", __LINE__);
// NSLog输出C语言字符串的时候,不能有中文
NSLog(@"%s", __FILE__);
// 输出源文件的名称
printf("%s\n", __FILE__);
//输出变量的地址
NSLog(@"%p", &p);
// 对象的地址
NSLog(@"%p", p);
// <类名:对象地址>
NSLog(@"%@", p);
十一、sel
1、说明
SEL其实是对方法的一种包装,将方法包装成一个SEL类型的数据,去找对应的方法地址。找到方法地址就可以调用方法。 其实消息就是SEL
2、sel运行过程
//[p test2];
// 1.把test2包装成SEL类型的数据
// 2.根据SEL数据找到对应的方法地址
// 3.根据方法地址调用对应的方法
3、方法的存储位置
每个类的方法列表都存储在类对象中
每个方法都有一个与之对应的SEL类型的对象
根据一个SEL对象就可以找到方法的地址,进而调用方法
SEL类型的定义
typedef struct objc_selector *SEL;
4、SEL对象的创建
SEL s = @selector(test);
SEL s2 = NSSelectorFromString(@"test");
5、SEL对象的其他用法
// 将SEL对象转为NSString对象
NSString*str = NSStringFromSelector(@selector(test));
Person *p= [Person new];
//调用对象p的test方法
[p performSelector:@selector(test)];
------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------