GXiOS

iOS开发--OC基础

2019-05-09  本文已影响2人  Caesar_62dd

对象方法的声明和实现

1.对象方法声明

xxffsm.png

2.对象方法实现

类方法的声明和实现

类方法声明

3.对象方法和类方法区别

new关键字

堆和栈的区别:

对象的存储细节

memory.png

isa指针

局部变量和全局变量以及成员变量的区别

@interface Person : NSObject{
    // 写在类声明的大括号中的变量, 我们称之为 成员变量(属性, 实例变量)
    // 成员变量只能通过对象来访问
    // 注意: 成员变量不能离开类, 离开类之后就不是成员变量 \
            成员变量不能在定义的同时进行初始化
    // 存储: 堆(当前对象对应的堆的存储空间中)
    // 存储在堆中的数据, 不会被自动释放, 只能程序员手动释放
    int age;
}
@end

@implementation Person{
}
@end
int a;
int b = 10;
// 写在函数和大括号外部的变量, 我们称之为全局变量
// 作用域: 从定义的那一行开始, 一直到文件末尾
// 全局变量可以先定义在初始化, 也可以定义的同时初始化
// 存储: 静态区
// 程序一启动就会分配存储空间, 直到程序结束才会释放

int main(int argc, const char * argv[]) {
    // 写在函数或者代码块中的变量, 我们称之为局部变量
    // 作用域: 从定义的那一行开始, 一直到遇到大括号或者return
    // 局部变量可以先定义再初始化, 也可以定义的同时初始化
    // 存储 : 栈
    // 存储在栈中的数据有一个特点, 系统会自动给我们释放
    int num = 10;
    {
        int value;
    }
    return 0;
}

函数与方法对比

常见错误

NSString 类介绍及用法

1.NSString常见方法

NSString *astring = @"This is a String!";
NSString *string = [NSString new];
string = @"GX";
[NSString stringWithFormat:@"哥%i岁了", 30];

2.NSString字符串长度计算

    NSString *str = @"gx";
    NSLog(@"length = %i", [str length]);
    输出结果:3
    NSString *str = @"高Caesar";
    NSLog(@"length = %i", [str length]);
    输出结果:4
    NSString *str = @"高雄";
    NSLog(@"length = %i", [str length]);
    输出结果:3
//NSUInteger 就是 unsigned long

        源码:
        typedef unsigned long NSUInteger;

结构体成员变量

typedef struct{
    int year;
    int month;
    int day;
} Sdate;


@interface GXStudent : NSObject
{
@public
    NSString *_name;
    Sdate _birthday;
}
- (void) sayMyNameWithBirthday;
@end
@implementation GXStudent
- (void) sayMyNameWithBirthday
{
    NSLog(@"My name is %@ , my birthday is %i.%i.%i", _name, _birthday.year, _birthday.month, _birthday.day );
}
@end

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        GXStudent *gx = [GXStudent new];
        //结构体只能在定义的时候初始化\
        系统并不清楚它是数组还是结构体
        gx->_name = @"Xiong";
//        1.先赋值给一个临时变量
//        Sdate gxdate = { 1991, 8, 11};
//        gx->_birthday = gxdate;
//        2.逐个赋值
//        gx->_birthday.year = 2014;
//        gx->_birthday.month = 05;
//        gx->_birthday.day = 12;
//        3.强制类型转换 == 方法一
        gx->_birthday = (Sdate){ 1991, 02, 11};
        [gx sayMyNameWithBirthday];
    }
    return 0;
}

修改模版

如何修改项目模板

修改类的头部信息

自定义代码段

自定义 Snippets

Snip20150529_27.png

导入Snippets

self关键字

self总结:

self注意

继承

继承的概念

jcj.png
@interface 子类名称 : 父类名称

@end

继承的相关特性

1.方法的重写

2.继承中方法调用的顺序

3.继承的注意事项

djc.png

4.继承的使用场合

super"关键字"

1.super基本概念

2.super的作用

多态

1.什么是多态?

2.多态的条件

3.多态的优点

4.如何实现多态

Animal *animal = nil;

//实例化猫的对象
animal = [Cat new];
[animal eat];

//实例化狗的对象
animal = [Dog new];
[animal eat];

5.多态的原理

6.多态的注意点

假设 子类 Dog 有一个特有的方法bark
[dog bark];
Animal *an2 = [Dog new];
[(Dog*)an2 bark]; //把父类的指针,强制类型转换
Animal *an3 = [Animal new];
[(Dog*)an3 bark]; //错误的,不能强制转换

实例变量修饰符

1 .实例变量的作用域

slblxsf.png

2.变量修饰符在子类中的访问

3.实例变量作用域使用注意事项

description方法

1.description基本概念

2.description重写的方法

/**对象方法:当使用NSLog输出该类的实例对象的时候调用*/
-(NSString *) description
{
    return [NSString stringWithFormat:@"狗腿数:%d,狗眼数%d\n",_legNum,_eyeNum];
}
/**类方法:当使用NSLog输出该类的类对象的时候调用*/
+(NSString *) description
{
    return @"+开头的description方法";
}

3.description陷阱

- (NSString *)description {
    return [NSString stringWithFormat:@"%@", self];
}

OC中的私有方法

1.OC中的私有变量

@implementation Dog
{
    @public
    int _age;
}
@end

补充:私有变量的访问及修改方式

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Person+GX.h"
#import <objc/runtime.h>//runtime 头文件

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc] init];
        
            //访问私有方法
        SEL sel = @selector(hello);
        [p performSelector:sel];
        
            //kvc访问私有变量
        NSLog(@"-------%@--------%@",[p valueForKey:@"name"] ,[p valueForKey:@"age"]);
            //kvc修改私有变量
        [p setValue:@"猪八戒" forKey:@"name"];
        [p setValue:@"8888" forKey:@"age"];
        NSLog(@"-------%@--------%@",[p valueForKey:@"name"] ,[p valueForKey:@"age"]);
        
            //runtime 修改私有变量
            //记录变量的数量
        unsigned int count = 0;
        
            //获取变量所有属性变量
        Ivar *members = class_copyIvarList([Person class], &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = members[I];
                //取得属性名字并专程字符串类型
            const char *memberName =ivar_getName(ivar);
            NSLog(@"%s",memberName);
            Ivar name = members[0];
                //修改属性值
            object_setIvar(p, name, @"齐天大圣");
        }
        NSLog(@"%@", [p valueForKey:@"name"]);
        
    }
    return 0;
}


2.OC中的私有方法

@interface Dog : NSObject

@end
@implementation Dog
- (void)eat
{
    NSLog(@"啃骨头");
}
@end
int main(int argc, const char * argv[]) {
    Dog *d = [Dog new];
    SEL s1 = @selector(eat);
    [d performSelector:s1];
    return 0;
}

@property基本概念

@property基本使用

用@property int age;就可以代替下面的两行
- (int)age;   // getter
- (void)setAge:(int)age;  // setter
1.在@inteface和@end之间写上@property
2.在@property后面写上需要生成getter/setter方法声明的属性名称, 注意因为getter/setter方法名称中得属性不需要_, 所以@property后的属性也不需要_.并且@property和属性名称之间要用空格隔开
3.在@property和属性名字之间告诉需要生成的属性的数据类型, 注意两边都需要加上空格隔开

@property增强注意点

@interface Person : NSObject
{
    @public
    int _age;//可以省略
    int age;//可以省略
}
@property int age;

@end

int main(int argc, const char * argv[]) {

    Person *p = [Person new];
    [p setAge:30];
    NSLog(@"age = %i, _age = %i", p->age, p->_age);

    return 0;
}
Person *p = [Person new];
[p setAge:-10];
NSLog(@"age = %i", [p age]);

@property修饰符

@property修饰符

@property (readonly) int age;
@property (getter=isMarried)  BOOL  married;
说明,(程序员约定)通常BOOL类型的属性的getter方法要以is开头

id类型

1.静态类型和动态类型

Person *p = [Person new];
id obj = [Person new];

2.为什么要有动态类型?

//定义NSObject * 类型
 NSObject* obj = [Cat new];
 Cat *c = (Cat*)obj;
 [c eat];
/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};

/// A pointer to an instance of a class.
typedef struct objc_object *id;
 id obj = [C at new];
 [obj eat]; // 不用强制类型转换

 [obj test]; //可以调用私有方法

3.id数据类型与静态类型

    Person *p = [Person new];
    Student *stu = [Student new];

    BOOL res = [p isKindOfClass:[Person class]];
    NSLog(@"res = %i", res); // YES
    res = [stu isKindOfClass:[Person class]];
    NSLog(@"res = %i", res); // YES
- (BOOL) isMemberOfClass: classObj 判断是否是这个类的实例
    Person *p = [Person new];
    Student *stu = [Student new];

    BOOL res = [p isMemberOfClass:[Person class]];
    NSLog(@"res = %i", res); // YES
    res = [stu isMemberOfClass:[Person class]];
    NSLog(@"res = %i", res); // NO
+ (BOOL) isSubclassOfClass:classObj 判断类是否是指定类的子类
    BOOL res = [Person isSubclassOfClass:[Student class]];
    NSLog(@"res = %i", res); // NO

    res = [Student isSubclassOfClass:[Person class]];
    NSLog(@"res = %i", res); // YES

new方法实现原理

1.new方法实现原理

This method is a combination of alloc and init. Like alloc, it initializes the isa instance variable of the new object so it points to the class data structure. It then invokes the init method to complete the initialization process.

构造方法

1.重写init方法

- (id)init {
    self = [super init];
    if (self) {
        // Initialize self.
    }
    return self;
}
+ [super init]的作用:

面向对象的体现,先利用父类的init方法为子类实例的父类部分属性初始化。

+ self 为什么要赋值为[super init]:

简单来说是为了防止父类的初始化方法release掉了self指向的空间并重新alloc了一块空间。还有[super init]可能alloc失败,这时就不再执行if中的语句。

- (id)init {
    if (self = [super init]) {
        // Initialize self.
    }
    return self;
}

2.构造方法使用注意

3.instancetype的作用

// init此时返回值是id
NSString *str = [[Person alloc] init];
// Person并没有length方法, 但是id是动态类型, 所以编译时不会报错
NSLog(@"length = %i", str.length);
// init此时返回值是instancetype
// 由于instancetype它会进行类型检查, 所以会报警告
NSString *str = [[Person alloc] init];
NSLog(@"length = %i", str.length);
instancetype *p = [[person alloc] init];
// 错误写法instancetype只能作为返回值

自定义构造方法

1.自定义构造方法

@interface Person : NSObject

@property int age;

@property NSString *name;

// 当想让对象一创建就拥有一些指定的值,就可以使用自定义构造方法
- (id)initWithAge:(int)age;

- (id)initWithName:(NSString *)name;

- (id)initWithAge:(int)age andName:(NSString *)name;

@end

继承中的自定义构造方法

1.继承中的自定义构造方法

initsuper.png

2.自定义构造方法的使用注意

自定义类工厂方法

1.自定义工厂方法

+ (id)person;
+ (id)person
{
    return  [[Person alloc]init];
}

+ (id)personWithAge:(int)age;
+ (id)personWithAge:(int)age
{
    Person *p = [[self alloc] init];
    [p setAge:age];
    return p;
}
其实苹果在书写工厂方法时也是按照这样的规划书写
    [NSArray array];
    [NSArray arrayWithArray:<#(NSArray *)#>];
    [NSDictionary dictionary];
    [NSDictionary dictionaryWithObject:<#(id)#> forKey:<#(id<NSCopying>)#>];
    [NSSet set];
    [NSSet setWithObject:<#(id)#>];

2.子父类中的类工厂方法

@interface Person : NSObject
+ (id)person;
@end

@implementation Person
+ (id)person
{
//   return  [[Person alloc]init];
//     谁调用这个方法,self就代表谁
//    注意:以后写类方法创建初始化对象,写self不要直接写类名
    return  [[self alloc]init];
}
@end

@interface Student : Person
@property NSString *name;
@end

@implementation Student
@end

int main(int argc, const char * argv[])
{
    Student *stu = [Student person];// [[Student alloc] init]
    [stu setName:@"gx"];
}

类的本质

1.类的本质

2.如何获取类对象

格式:[实例对象   class ];
如:   [dog class];
格式:[类名 class];
如:[Dog class]

3.类对象的用法

[Dog test];

Class c = [Dog class];
[c test];
Dog *g = [Dog new];

Class c = [Dog class];
Dog *g1 = [c new];

4.类对象的存储

ldxcc.png

5.OC实例对象 类对象 元对象之间关系

NSObject.h
@interface NSObject <NSObject> {
    Class isa  OBJC_ISA_AVAILABILITY;
}
objc.h
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

/// Represents an instance of a class.
struct objc_object {
    Class isa  OBJC_ISA_AVAILABILITY;
};
runtime.h
struct objc_class {
    Class isa  OBJC_ISA_AVAILABILITY;

#if !__OBJC2__
    Class super_class                                        OBJC2_UNAVAILABLE;
    const char *name                                         OBJC2_UNAVAILABLE;
    long version                                             OBJC2_UNAVAILABLE;
    long info                                                OBJC2_UNAVAILABLE;
    long instance_size                                       OBJC2_UNAVAILABLE;
    struct objc_ivar_list *ivars                             OBJC2_UNAVAILABLE;
    struct objc_method_list **methodLists                    OBJC2_UNAVAILABLE;
    struct objc_cache *cache                                 OBJC2_UNAVAILABLE;
    struct objc_protocol_list *protocols                     OBJC2_UNAVAILABLE;
#endif

} OBJC2_UNAVAILABLE;

类的启动过程

1.+load方法

@implementation Person

+ (void)load
{
    NSLog(@"%s", __func__);
}
@end

@implementation Student : Person

+ (void)load
{
    NSLog(@"%s", __func__);
}
@end

输出结果:
+[Person load]
+[Student load]

2.+initialize

@implementation Person
+ (void)initialize
{
    NSLog(@"%s", __func__);
}
@end

@implementation Student : Person
+ (void)initialize
{
    NSLog(@"%s", __func__);
}
@end
int main(int argc, const char * argv[]) {
    Student *stu = [Student new];
    return 0;
}
输出结果:
+[Person initialize]
+[Student initialize]

SEL类型

1.什么是SEL类型

Dog *dog=[[Dog alloc] init];
[dog eat];
sel.png

2.SEL使用

    BOOL flag;
    // [类 respondsToSelector]用于判断是否包含某个类方法
    flag = [Person respondsToSelector:@selector(objectFun)]; //NO
    flag = [Person respondsToSelector:@selector(classFun)]; //YES

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

    // [对象 respondsToSelector]用于判断是否包含某个对象方法
    flag = [obj respondsToSelector:@selector(objectFun)]; //YES
    flag = [obj respondsToSelector:@selector(classFun)]; //NO

    // [类名 instancesRespondToSel ector]用于判断是否包含某个对象方法
    // instancesRespondToSelectorr只能写在类名后面, 等价于 [对象 respondsToSelector]
    flag = [Person instancesRespondToSelector:@selector(objectFun)]; //YES
    flag = [Person instancesRespondToSelector:@selector(classFun)]; //NO
    Person *p = [Person new];
    SEL s1 = @selector(objectFun);
    [p performSelector:s1];

    SEL s2 = @selector(objectFun:);
    [p performSelector:s2 withObject:@"gx"];

    SEL s3 = @selector(objectFun:value2:);
    [p performSelector:s3 withObject:@"gx" withObject:@"璐璐"];

    SEL s4 = @selector(classFun);
    [Person performSelector:s4];

    SEL s5 = @selector(classFun:);
    [Person performSelector:s5 withObject:@"gx"];

    SEL s6 = @selector(classFun:value2:);
    [Person performSelector:s6 withObject:@"gx" withObject:@"璐璐
"];
@implementation Person

- (void)makeObject:(id) obj performSelector:(SEL) selector
{
    [obj performSelector:selector];
}
@end

int main(int argc, const char * argv[]) {

    Person *p = [Person new];
    SEL s1 = @selector(eat);
    Dog *d = [Dog new];
    [p makeObject:d performSelector:s1];

    return 0;
}

3.OC方法查找顺序

sldxldxydx.png
上一篇下一篇

猜你喜欢

热点阅读