Objective C 学习笔记

来源:互联网 发布:mysql5.7 for mac下载 编辑:程序博客网 时间:2024/06/06 13:18

前 言

终于还是选择了”挨踢”的路,经过一段时间的培训,本着自己的认识、分析和理解程度上不去做技术上的高手,记下笔记提高自己。


目 录

  • 第一讲 语言简介、类和对象、NSObeject、基础语法
  • 第二讲 方法(封装)、继承、多态
  • 第三讲 属性(property)、语法新特性
  • 第四讲 OC数据类之字符串(NSString、NSMutableString)、集合类之数组(NSArray、NSMutableArray)
  • 第五讲 OC集合类之字典(NSDictionary、NSMutableDictionary)、集(NSSet、NSMutableSet)
  • 拓展 NSValue\Copy\MutableCopy\NSRang
  • 第六讲 NSNumber NSNumberForMatter NSValue NSDate NSDateForMatter NSTimer等
  • 第七讲 内存管理
  • 第八讲 类目、延展、协议
  • 第九讲 单例、通知、代理引用传值
  • 第十讲 Block应用、RunTime讲解

第一讲 语言简介、类和对象、NSObeject、基础语法

#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {    @autoreleasepool {        NSLog(@"Hello, World!");    }    return 0;}

import :(保证头文件只被包含一次)

1.检测重复,防止文件的重复拷贝

2.<> 导入系统头文件 “” 导入自定义头文件

3.Foundation是一个基本库,导入他才能使用NSLog();

4.导入Foundation的头文件( Foundation.h文件 )


@autoreleasepool//称之自动释放池

NSLog(@"Hello, World!");//类似于C语言的printf函数; 1.NSLog添加了时间戳 :2016-05-20 19:44:10.366 OC第一讲[1441:158586] Hello, World! 2.打印的时候多了一个@符号 3.自动换行
类(class):对一类事物抽象的描述(抽象)
对象(object):从以类食物中具体刻画出来的一个实例(具体);


第二讲 方法(封装)、继承、多态

封装方法:封装可以隐藏实现细节,使得代码模块化
  封装:只要是对成员变量的封装,例如setget方法set方法的作用:提供一个方法给外界设置成员变量    命名规范:    1.方法必须set开头    2.set后面跟上成员变量的名称(去掉下划线,成员变量的首字母大写    3.返回值一定是void    4.一定要接收一个参数,而且参数和成员变量类型一致    5.形式参数的名称不能和成员变量一样get方法的作用:返回对象内部成员变量的值    命名规范:    1.方法名和去掉下划线的成员变量名一样    2.不能添加get关键字    3.肯定有返回值,而且返回值的类型和成员变量的类型一致    4.不接受任何参数
继承:可以扩展已存在的代码模块(类)
  1.抽取重复的代码  2.建立类与类之间的关系  3.子类阔以拥有父类的所有变量和方法
封装、继承的的目的都是为了——代码重用
多态:实现接口重用,为了类在继承和派生的时候,保证使用”家谱”中任意一类实例的某一属性时的正确调用

说明: DOG 继承于 Animal (Animal 拥有eat的属性、DOG 拥有run的属性)

#pragma mark --多态        Animal *animal = [[DOG alloc]init];        [animal eat];//调用方法会检测对象的真实形象         //1.父类的指针可以指向子类的对象,但是不能指向子类的对象        //2.父类类型的变量不能调用子类的方法/*多态: 不同对象对同一消息的不同反应*///强转        DOG *dog = (DOG *)animal;        [dog run];
//索引找到 继承父类的方法//如果父类定义的方法,在子类可以不用写,如在DOG类能调用Animal类中的run**************************************************************#import <Foundation/Foundation.h>@interface Animal : NSObject- (void) eat;@end*************************************************************#import "Animal.h"@interface DOG : Animal-(void)run;@end  *************************************************************@implementation DOG-(void)eat{    NSLog(@"dog love bone");}-(void)run{    NSLog(@"I can run");}@end
注意:子类需重新实现父类的方法,并覆盖父类以前的做法,需要重写Setter方法

1.父类方法必须声明

2.调用方法的时候,子类优先找当前类的方法,如果找不到则寻找父类的方法

3.缺点:耦合性太高

继承使用的场合:
当A类完全拥有或者部分拥有B类中的属性和方法,可以让B类继承

 -(void)sayHi{    [super sayHi];//直接调用父类中的某个方法    NSLog(@"I am a stduent,my name is %@",_name);}
    super作用:        1.直接调用父类的方法        2.super在对象方法中,那么就会调用父类中的对象方法,在父类中,会调用父类的方法        3.使用场合:子类重写父类的方法同时想保留父类的一些行为        [super 方法名]//调用父类方法     self的用法:        1.谁点用了当前方法,self就代表谁        2.self在对象方法中就代表当前对象        3.self在类方法中,代表当前类        [self 方法名] //调用对象方法
实例化方法和类方法(便利构造)

‘_’(减号开头)实例化方法

1.只能由对象调用2.对象方法中能访问当前对象的成员变量

‘+’(加号开头)类方法

1.只能由类调用2.类方法中不能访问成员变量

类方法的使用场合(注:类方法可以和实例方法同名)

1.不依赖对象,执行效率高2.当方法内部不许需要成员变量的时候,阔以使用类方法

第三讲 属性(property)、语法新特性

iOS 4.4之前,只会帮助setter和getter方法的声明
在头文件中声明 @property NSString *name;


属性:在iOS5之前写属性
1.先写出带下划线的成员变量
2.使用@property关键字匹配一个不带下划线的与成员变量同名的属性
3.使用@synthesize将成员变量和属性进行合并
//@synthesize name = _name;

@property (nonatomic, strong) <#NSString#> *<#NSString#>; 属性优点:      1.自动声明一个带下划线的成员变量    2.自动声明和实现成员变量对应的setter和getter方法第一类:内存管理相关    assign:缺省值,修饰基本数据类型和delegate    retain:对象类型 在MRC手动管理内存     copy:对象类型 (在遵守<NSCopying>情况下)第二类:线程相关     atomic:关心线程安全,通常用于多线程中    nonatomic:不用去关心线程安全,通常用于单线程第三类:    readwrite:读写    readonly:只读,只提供getter方法,不提供setter方法第四类:    nullable:表明这个属性的值可以为nil,对应swift中name?     nonull:不为nil,如果传一个nil的指针,将会收到编译器的警告     null_resettable:stter 可以为空     null_unspecified:是否为nil不确定//@property (nonatomic, strong, nullable) NSString *name;//nullable 只要属性加了这个关键字,以后相同类型的属性都需要加这个关键字 stter ,getter = 重新定义setter和getter的方法名。

第四讲 OC数据类之字符串(NSString、NSMutableString)、集合类之数组(NSArray、NSMutableArray)

  • pragma mark –NSString
        //字符串创建        /*         1.stringWithFormat         2.stringWithString         3.stringWithCharacter:lenth         */        NSString *string = [[NSString alloc] init];//不推荐使用        NSString *string1 = [[NSString alloc] initWithFormat:@"jack %@", string];        NSString *string2 = [NSString stringWithFormat:@"123%@",string1];        NSLog(@"%@",string2);        ===============================================================        //字符串的拼接        /*         1.stringByAppendingString         2.stringByAppendingFormat         */        NSString *string = @"123";        NSString *string2 = @"456";        NSString *string3 = [string stringByAppendingString:string2];        NSLog(@"%@", string3);        string3 = [string3 stringByAppendingFormat:@"%@", string3];        NSLog(@"%@", string3);        ===============================================================        //字符串的截取        /*         *subStringFromIndex; index为截取的开始位置的下标         *subStringToIndex;         *subStringWithRange;         */        NSString *string = @"abcde";        //练习:将“abcde”中的de去掉        //string = [string substringToIndex:3];        NSString *string2 = [string substringToIndex:2];        NSString *string3 = [string substringFromIndex:4];        string = [string2 stringByAppendingFormat:@"%@",string3];        NSLog(@"%@", string);        //练习:“hello word”的字符串通过截取变成“hd”        NSString *string4 = @"hello word";        string4 = [[string4 substringToIndex:1] stringByAppendingFormat:@"%@",[string4 substringFromIndex:string4.length - 1]];        NSLog(@"%@", string4);        ===============================================================        //字符串查询(查找字符串cd)        NSString *string = @"abcde";        NSRange range =[string rangeOfString:@"cd"];        if (range.location == NSNotFound && range.length ==0)        {             NSLog(@"Not Found!");        }else{            NSLog(@"Found the string!");        }        BOOL result = [string containsString:@"cd"];        if (result == YES) {              NSLog(@"Result=%hhd Found the string!",result);        }        ===============================================================        NSString *str = @"baidu.com";        // 查询前缀        if ([str hasPrefix:@"http://"]) {            NSLog(@"str has prefix 'http://'.");        }else {            NSLog(@"str has not prefix 'http://'.");        }        // 查询后缀        if ([str hasSuffix:@"com"]) {            NSLog(@"str has suffix 'com'.");        }else {            NSLog(@"str has not suffix 'com'.");        }       ===============================================================        //字符串替换(替换cd改成CD)        NSString *string = @"abcdecd";        NSString *stringResult = [string stringByReplacingCharactersInRange:NSMakeRange(2, 2) withString:@"CD"];//根据范围替换        NSLog(@"%@",stringResult);        NSString *stringResult1 = [string stringByReplacingOccurrencesOfString:@"cd" withString:@"CD"];//全部替换        NSLog(@"%@",stringResult1);        ===============================================================        // 字符串比较          /*         * 字符串比较:         * isEqualToString: 判断字符串是否相同         * compare:         字符串比较         * compare: option: 字符串比较(可定义比较模式)         */        NSString *string = [NSString stringWithFormat:@"1232"];        NSString *string1 = [NSString stringWithFormat:@"1234"];        // 法一:        BOOL resultString = [string isEqualToString:string1];        if (resultString == 1) {            NSLog(@"the same");        }        // 法二:       NSComparisonResult result = [string compare:string1 options:NSNumericSearch | NSCaseInsensitiveSearch];        if (result == NSOrderedAscending)//升序        {                NSLog(@"srtring1 is bigger than string!!");        }else if (result == NSOrderedDescending)//降序        {                NSLog(@"srtring is bigger than string1!!");        }else//相等        {                NSLog(@"the same!!");        }         ===============================================================         // NSComparisonResult:比较结果枚举类型,NSStringCompareOptions比较策略枚举类型         // NSNumericSearch   :比较字符串长度         // NSCaseInsensitiveSearch: 大小写不敏感比较         // NSLiteralSearch        : 完全比较,比较大小写            string1 = [NSString stringWithFormat:@"1234"];         string2 = [NSString stringWithFormat:@"123"];         NSComparisonResult result = [string1 compare:string2 options:NSNumericSearch | NSCaseInsensitiveSearch];         if (result == NSOrderedSame) {             NSLog(@"the strigns are same.");         }else if (result == NSOrderedAscending) {             NSLog(@"string1 is less than string2.");         }else if (result == NSOrderedDescending) {             NSLog(@"string1 is bigger than string2.");         }        ===============================================================        /*         1.length:获取长度         2.integerValue,floatValue,doubleValue:简单数据类型的转换         3.uppercaseString,lowercaseString,capitalzedString:字符串大小写转换         */        ===============================================================        //数值转换        int a =234;        NSString *numberString = [NSString stringWithFormat:@"%d",a];        int number = [numberString intValue];        NSInteger number2 = [numberString integerValue];        float number3 = [numberString floatValue];        double number4 = [numberString doubleValue];        ===============================================================        // 大小写转换        NSString *string = @"hello word";        NSLog(@" string = %@",string);        NSString *string1 = [string uppercaseString];        NSLog(@"string1 = %@",string1);        NSString *string2 = [string1 lowercaseString];        NSLog(@"string2 = %@",string2);        NSString *string3 =[string capitalizedString];//单词首字母大写        NSLog(@"string3 = %@",string3);
  • pragma mark –NSMutableString可变字符串
      //增、删、改、插        NSMutableString *string = [NSMutableString stringWithFormat:@"123"];        [string appendFormat:@"456"];//拼接        NSLog(@"%@",string);        [string appendString:string];        NSLog(@"%@",string);//123456123456        [string insertString:@"a" atIndex:3];//在某个下标位置插入字符        NSLog(@"%@",string);        [string deleteCharactersInRange:NSMakeRange(4, 3)];//删除        NSLog(@"%@",string);        [string replaceCharactersInRange:NSMakeRange(0, 3) withString:@"ABC"];//更改        NSLog(@"%@",string);
  • pragma mark –NSArray
//C语言//int a[5] = {1,2,3,4,5};//相同类型集合        //oc语言数组        //数组初始化        //一般初始化方式        NSArray *array = [[NSArray alloc]initWithObjects:@"123",@(34),@"567", nil];        //便利初始化        NSArray *array1 = [NSArray arrayWithObject:@"jack"];//一个对象自动添加nil        NSArray *array2 = [NSArray arrayWithObjects:@"tom",@(123) ,nil];        //快速初始化(ios5以上)        NSArray *array3 = @[@"2",@"5",@"nice"];//对象自动添加nil
         数组取值:         //objectAtIndex:  //取出某一下标对应的元素         //lastObject:    //取出最后一个元素         //firstObject:  //取出第一个元素
        NSArray *array = [NSArray arrayWithObjects:@"1",[NSString stringWithFormat:@"2"],[NSNumber numberWithInt:3], nil];        NSLog(@"%@",array);//数组外层有小括号        id object = [array objectAtIndex:1];//NSString *string = [array objectAtIndex:1]        id firstObject = [array firstObject];        NSLog(@"firstObject:%@",firstObject);        id lastObject = [array lastObject];        NSLog(@"lastObject:%@",lastObject);        NSLog(@"object:%@",object);        NSArray<NSString *> *strings = @[@"1",@"2",@"3"];        NSLog(@"%@",strings);        NSLog(@"%ld",strings.firstObject.length);        NSDictionary<NSString *,NSNumber *> *dict =@{@"a":@(1),@"b":@(2),@"c":@(3)};        NSLog(@"%@",dict);
  • pragma mark –NSMutableArray
        NSMutableArray ->数组运算: *增   *删  *改  *查  *排序         ===============================================================         NSMutableArray *mutableArray = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",@"4", nil];        //增加:addObject:(一定不能添加一个空对象)        [mutableArray addObject:@"5"];        //删除        [mutableArray removeObject:@"4"];//删除4这个对象        [mutableArray removeObjectAtIndex:2];//删除下标对象        //查        NSInteger index = [mutableArray indexOfObject:@"2"];        //修改        [mutableArray replaceObjectAtIndex:2 withObject:@"30"];        //排序        [mutableArray sortedArrayUsingSelector:@selector(compare:)];         ===============================================================        NSArray *array = [NSArray arrayWithObjects:@"1",@"13",@"4",@"56", nil];        NSLog(@"%@",array);        //增加元素        NSArray *newArray = [array arrayByAddingObject:@"23"];        NSLog(@"%@",newArray);        //查找某一个元素坐在的下标        NSInteger index = [array indexOfObject:@"56"];        NSLog(@"%d",(int)index);        //排序 sortedArrayUsingSelector        //方法选择器+方法 :@selector(compare:)        NSArray *sorteArray = [array sortedArrayUsingSelector:@selector(compare:)];        NSLog(@"%@",sorteArray)         ===============================================================        //3种便利数组元素方式        //getter和点语法都阔以        //循环便利        for (int i = 0 ; i<array.count; i++) {            NSLog(@"循环便利:%@",[sorteArray objectAtIndex:i]);        }        //快速枚举 for-in 适用于不需要知道元素下标        for (NSString *string in sorteArray) {            NSLog(@"快速枚举:%@",string);        }        //block enumerateObjectsUsingBlock 两次回车符   可以将一串代码作为值        [sorteArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {            //obj:返回的下标对应的参数            //idx:下标位置            NSLog(@"block:%@ index:%lu",obj,idx);            if (idx == 2)//下标等于2中断循环            {                *stop = YES;            }        }];        ===============================================================        //Array数组元素排序(排序条件)        //声明数组有年龄和姓名        // 1. (排序条件)        NSSortDescriptor *sortDescriptor1 = [NSSortDescriptor sortDescriptorWithKey:@"_age" ascending:YES];//按年龄排        NSSortDescriptor *sortDescriptor2 = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];//按名字排        // 2. 先按年龄排,再按名字排        [Array sortUsingDescriptors:@[sortDescriptor1,sortDescriptor2]];
    //练习:        NSArray *array1 = [NSArray arrayWithObjects:@"123",@"234",@"78",nil];        NSLog(@"array1 = %@",array1);        NSArray *array2 = [NSArray arrayWithObject:array1];        NSLog(@"array2 = %@",array2);        NSArray *array3 = [NSArray arrayWithObjects:@"789",array2, nil];        NSLog(@"array3 = %@",array3);        NSLog(@"%@",array3[0]);        NSLog(@"%@",array3[1][0][2]);//从array3种取出array1的第2个元素        array3 = ( 789, ((123,234,78)))        ===============================================================     //练习:举例 @[@"1",@"2",@"3",@"4",@"5"] 移除数组中大于3的元素        NSArray *array = @[@"1",@"2",@"3",@"4",@"5"];        NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:array];        NSMutableArray *removeArray = [[NSMutableArray alloc]init];//用来记录要被删的元素       // 在遍历集合的时候不能对集合的对象元素进行改变        for (NSString *string in array) {            if ([string integerValue] > 3) {                [removeArray addObject:string];            }        }        [mutableArray removeObjectsInArray:removeArray];        NSLog(@"%@",mutableArray);        ===============================================================    //练习:           NSString *string = @"123-456-789-000";        NSArray *array =[string componentsSeparatedByString:@"-"];        NSLog(@"%@",array);        //(123,456,789,000)        string =[array componentsJoinedByString:@"+"];        NSLog(@"%@",string);        //123+456+789+000      ===============================================================    //练习: 对一个已知的NSMutableArray数组进行冒泡排序        NSMutableArray *array = [NSMutableArray arrayWithObjects:@"7",@"3",@"5",@"2",@"4",@"6",@"1", nil];        for (int i = 0; i<array.count-1; i++)        {            for (int j = 0; j <array.count-1-i; j++)            {                if ([array[j] integerValue] > [array[j+1] integerValue]  )                {                    [array exchangeObjectAtIndex:j withObjectAtIndex:j+1];                      NSInteger num = [array[j] integerValue];                      NSInteger num1 = [array[j+1] integerValue];                      if (num >num1)                       {                          [array exchangeObjectAtIndex:j withObjectAtIndex:j+1];                         }            }        }NSLog(@"%@",array);

第五讲 OC集合类之字典(NSDictionary、NSMutableDictionary)、集(NSSet、NSMutableSet

  • pragma mark –NSDictionary
        /*         字典以键值对的方式进行存储,无序 例如:key ->value         初始化方式:         */         //一般初始化:alloc + initWithObjectsandKeys        NSDictionary *dictionary = [[NSDictionary alloc]initWithObjectsAndKeys:@"first",@(1),@(2),@"second",@(4),@"four",nil];        NSLog(@"%@",dictionary);        //便利初始化:dictionaryWithObjectAndKeys        //便利构造(ios5)----快速构造方式,成对出现:前键 后值 返回的是不可变字典        NSDictionary *newdictionary = @{@"fist":@(1),@"second":@(2)};        NSLog(@"%@",newdictionary);        /*         字典的常规方法         1.查询某个对象:ObjectForKey:         2.取出所有键值:allkeys         3.取出所有value:allValues数组        */        //1.查        NSString *string = [dictionary  objectForKey:@"first"];//取出key做对应的对象        NSLog(@"%@",string);        //2.字典里面所有键的集合        NSArray *keys = [newdictionary allKeys];        NSLog(@"%@",keys);        //3.取出所有的值        NSArray *value = [newdictionary allValues];        NSLog(@"%@",value);         ===============================================================            字典的遍历练习         ===============================================================         NSDictionary *dictionary = @{@"name":@"jack",@"age":@(18),@"height":@"188",@"code":@"1555",@"sex":@"男"};        //for循环 取出所有的KEY值        NSArray *key = [dictionary allKeys];        for (int i = 0; i < key.count; i++) {            //1.取出键值            NSString *keyString = key[i];            NSString *value = [dictionary objectForKey:keyString];            //NSString *value = dictionary[keyString];        }        NSLog(@"key1:%@",key);        //for-in遍历        for(NSString *key in dictionary){            NSLog(@"key2:%@",[dictionary objectForKey:key]);        }       // key position -- value @{@"1":@"北京",@"2":@"重庆",@"3":@"成都"}       // dictionary[@"position"][@"3"];
  • pragma mark –NSMutableDictionary
        /*         *增:setObject:forkey         *删:removeObjectforKey         *查:objectForKey         *改:setObject:forkey 覆盖指定key对应的值         */        NSMutableDictionary *mutableDict = [[NSMutableDictionary alloc]init];        //增:        [mutableDict setObject:@"jack" forKey:@"name"];        [mutableDict setObject:@"56" forKey:@"age"];        [mutableDict setObject:@"188" forKey:@"height"];        //删        [mutableDict removeAllObjects];//删除所有        [mutableDict removeObjectForKey:1];//删除KEY值对应的value key值也就不存在了        //查找        NSString *string = [mutableDict objectForKey:@"age"];        //改:        [mutableDict setObject:@"45" forKey:@"age"];
  • pragma mark –NSSet

  • NSSet简介

    • NSSet对象中不能存放重复对象,如果出现重复,最终只会保留一个,NSSet也常用来清除其他集合中的重复对象。

    • 集,类似数组,但区别于数组,其特点是:无序不重复;

    • 集分为可变集 NSSet 与不可变集 NSMutableSet;


  • 初始化

 // 1、alloc + init        - (instancetype)initWithObjects:(ObjectType)firstObj, ... ;// 2、遍历构造        + (instancetype)setWithObjects:(ObjectType)firstObj, ...; ``` * 常用方法 ```1、获取元素个数- (NSUInteger)count;2、获取任意元素- (nullable ObjectType)anyObject;3、获取所有元素@property (readonly, copy) NSArray<ObjectType> *allObjects;4、查询是否包含某一元素- (BOOL)containsObject:(ObjectType)anObject;  ``` * ___pragma mark --NSMutableSet___ * 常用方法

// 1、添加元素
- (void)addObject:(ObjectType)object;

// 2、删除元素
- (void)removeObject:(ObjectType)object;

拓展 NSValue\Copy\MutableCopy\NSRang

  • pragma mark –NSValue

    • 数值对象,用于复杂数据类型的对象化封装,如结构体;

    • NSValue 对自定义结构体类型的初始化

 // 1、结构体类型声明        typedef struct {             char name[81];             int  age;          }Person;// 2、声明结构体变量并初始化        Person person = {"Charles", 21};// 3、封装        NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];// 4、解封装        Person newPerson;        [value getValue:&newPerson];        NSLog(@"<%p 姓名:%s 年龄:%d>", &newPerson, newPerson.name, newPerson.age); ```
  简单结构体类型转换为对象类型    //便利结构初始化    NSValue *Value = [NSValue valueWithPoint:NSMakePoint(4, 5)];    NSLog(@"%@",Value);    //打印:NSPoint: {4, 5}    NSValue *sizeValue = [NSValue valueWithSize:NSMakeSize(34, 568)];    NSLog(@"%@",sizeValue);    //打印:NSSize: {34, 568}    NSValue *rectValue = [NSValue valueWithRect:NSMakeRect(3, 5, 6, 678)];    NSLog(@"%@",rectValue);    //打印:NSRect: {{3, 5}, {6, 678}}    //便利解封装    NSPoint point = [Value pointValue ];    NSString *str1 = NSStringFromPoint(point);    NSLog(@"point is %@",str1);    NSSize size = [sizeValue sizeValue];    NSString *str2 = NSStringFromSize(size);    NSLog(@"point is %@",str2);    NSRect rect = [rectValue rectValue];    NSString *str3 = NSStringFromRect(rect);    NSLog(@"point is %@",str3);
  • pragma mark –Copy
        NSArray *array = [NSArray arrayWithObjects:@"1",@"2",@"3", nil];        NSArray *newArray = [array copy];        NSLog(@"%p %p",array,newArray);        //结论:copy对于不可变对象,是指针复制,也成为浅复制        NSMutableString *mutableString = [NSMutableString stringWithFormat:@"34"];        NSMutableString *newMutableStr =[mutableString copy];        NSLog(@"%p %p",mutableString,newMutableStr);        //结论:copy作为可变对象,是内容复制,也成为深复制。但是复制之后的字符串变成了一个不可变的字符串;
  • pragma mark –MutableCopy
        NSMutableArray *mutableArray = [@[@"123",@"456"] mutableCopy];        [mutableArray addObject:@"789"];        //NSLog(@"%@",mutableArray);        NSString *string = [NSString stringWithFormat:@"AAA"];        //NSString *newStr = [string mutableCopy];        NSMutableString *newStr = [string mutableCopy];        [newStr appendFormat:@"BBB"];        NSLog(@"%p %p",string,newStr);        NSMutableString *newStr2 = [newStr copy];// mutableCopy:对于可变或者不可变对象mutableCopy都是深复制(开辟新的内存,内容复制),且开辟的新内容都是可变的        NSMutableString *str = [@"123" mutableCopy];
  • pragma mark –NSRange
    • C 语言使用结构体、指针和数组来构造复杂的数据类型,而结构体和指针在iOS编程中至关重要,Cococa为我们准备了与字符串操作有关的结构体NSRange:
// NSRange:用来表示相关事物的范围 typedef struct _NSRange {     unsigned int location;     //location表示起始位置    unsigned int length;       //length表示长度 } ```* NSRange有三种创建方式:
比如要得到字符串@“helloRIMIOnline”中@“Online”字符串,需要一个起始位置为9,6个长度的范围,它可以有三种方式创建:

它可以有三种方式创建:

  • 第一种调用函数可以这么写:
    NSRange range = NSMakeRange (9,6);

  • 第二种直接给成员赋值:
    NSRange range;
    range.location = 9;
    range.length = 6;

  • 第三种应用C语言的聚合结构赋值机制:
    NSRange range = {9,6};

第六讲 NSNumber NSNumberForMatter NSValue NSDate NSDateForMatter NSTimer等

  • pragma mark –NSNumber

  • 数值对象,用于简单数据类型的对象化封装,继承与 NSValue;

  • NSNumber的初始化

        NSNumber *number1 = [NSNumber numberWithInt:5];        NSNumber *number2 = [NSNumber numberWithFloat:5];        NSNumber *number3 = [NSNumber numberWithDouble:5.0f];
  • NSNumber 比较
    NSNumber *number = @(10);    NSNumber *antherNumber = @(10);// 1、判断是否相等    BOOL isEqual = [number isEqualToNumber:antherNumber];// 2、比较大小    NSComparisonResult result = [number compare:antherNumber];    // NSOrderedAscending(-1):升序    // NSOrderedSame(0)      :相等    // NSOrderedDescending(1):降序    if (result == NSOrderedAscending) {        NSLog(@"number < antherNumber");    }else if (result == 0) {        NSLog(@"number = antherNumber");    }else {        NSLog(@"number > antherNumber");    }
        NSNumber *number = [NSNumber numberWithInt:4];        NSLog(@"%@",number);//4        //便利写法        NSNumber *floatNumber = @(4.6);        NSLog(@"%@",floatNumber);//保留有效位数 4.6        CGFloat num = floatNumber.floatValue;        NSLog(@"%f",num); //4.6        NSNumber *number1 = [NSNumber numberWithFloat:3.05];        NSLog(@"%@",number1);//3.05
  • pragma mark –NSNumberFormatter

  • 使用 NSNumberFormatter 对 NSNumber 与 NSString 相互转化

  • NSNumberFormatterStyle

    1、NSNumberFormatterScientificStyle: 1.23456E5    2、NSNumberFormatterPercentStyle: 12,345,600%    3、NSNumberFormatterCurrencyStyle: ¥ 123,456.00    4、NSNumberFormatterDecimalStyle: 123,456    5、NSNumberFormatterNoStyle: 123456    ===========================================================#import <Foundation/Foundation.h>int main(int argc, const char * argv[]) {    @autoreleasepool {        NSNumber *number = @(12345);        NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];        // 设置样式             [formatter setNumberStyle:NSNumberFormatterCurrencyStyle];        // 据样式将 number 转换成字符串        NSString *numberString = [formatter stringFromNumber:number];        NSLog(@"number string = %@", numberString); // 输出 number string = ¥ 123,45.00    }    return 0;}
        NSNumber *number = @(123456);//将数字转换成文字        NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];        formatter.numberStyle = kCFNumberFormatterSpellOutStyle;        NSString *string = [formatter stringFromNumber:number];        NSLog(@"%@",string);//十二万三千四百五十六
  • pragma mark –NSValue

  • 数值对象,用于复杂数据类型的对象化封装,如结构体;

// 1、结构体类型声明    typedef struct {        char name[81];         int  age;      }Person;// 2、声明结构体变量并初始化    Person person = {"Charles", 21};// 3、封装    NSValue *value = [NSValue valueWithBytes:&person objCType:@encode(Person)];// 4、解封装    Person newPerson;    [value getValue:&newPerson];    NSLog(@"<%p 姓名:%s 年龄:%d>", &newPerson, newPerson.name, newPerson.age);
  • pragma mark –NSdDate
//区别:NSData         /*         * NSDate 的初始化         * date 获取当前系统时间,默认为格林威治时间,比北京时间早8小时         * dateWithTimeInterval:3600 sinceDate: 使用一个传入的时间作为参照,加上偏移时间间隔(秒)         * dateWithTimeIntervalSince1970: 使用1970-01-01的时间作为参照,加上偏移时间间隔(秒)         * dateWithTimeIntervalSinceNow: 使用当前的时间作为参照,加上偏移的时间间隔(秒)         * dateWithTimeIntervalSinceReferenceDate: 使用2001-01-01的时间作为参照,加上偏移的时间间隔(秒)         */        //NSDate的初始化        NSDate *date = [NSDate date];        NSLog(@"date=%@",date);//date=2016-05-21 09:40:55 +0000          //传入的日期加上偏移量(时区+8)        NSDate *date1 = [NSDate dateWithTimeInterval:3600*8 sinceDate:date];        NSLog(@"date1=%@",date1);//date1=2016-05-21 17:40:55 +0000        //以2001-1-1时间作为参照,在加上偏移量        date1 = [NSDate dateWithTimeIntervalSinceReferenceDate:7200];        NSLog(@"date1=%@",date1);//date1=2001-01-01 02:00:00 +0000          //使用date获取时间间隔        NSTimeInterval time = [date timeIntervalSinceDate:date1];        NSLog(@"time=%lf",time);        time = [date timeIntervalSince1970];        time = [date timeIntervalSinceReferenceDate];        time = [date timeIntervalSinceNow];        //NSDate的的比较        NSComparisonResult result = [date compare:date1];        NSLog(@"%ld",(long)result);        BOOL result1 = [date isEqual:date1];        NSLog(@"%d",result1);        //比较2个日期,返回较小的那个        NSDate *earlierDate = [date earlierDate:date1];        NSLog(@"%ld",(long)earlierDate);       //比较2个日期,返回较小那个        NSDate *laterDate = [date laterDate:date];        NSLog(@"%ld",(long)laterDate);
  • pragma mark –NSDateFormatter
        NSDate *date = [NSDate date];        NSLog(@"初始化:%@",date);        NSDateFormatter *formatter = [[NSDateFormatter alloc]init];//创建一个格式转换器对象        [formatter setDateFormat:@"yyyy年mm月dd日 hh:mm:ss"];//设置自定义格式        [formatter setDateStyle:NSDateFormatterMediumStyle];//系统定义日期样式        [formatter setTimeStyle:NSDateFormatterMediumStyle];//系统定义时间样式        NSString *dateString = [formatter stringFromDate:date];//自定义        NSLog(@"dateString1 : %@",dateString);        //类方法 获取当地时间字符串        dateString = [NSDateFormatter localizedStringFromDate:date                                                    dateStyle:NSDateFormatterMediumStyle                                                    timeStyle:NSDateFormatterMediumStyle];          NSLog(@"dateString2 : %@",dateString);        //获取当前时区        NSTimeZone *zone = [NSTimeZone systemTimeZone];        NSInteger interval =[zone secondsFromGMTForDate:date];        date = [date dateByAddingTimeInterval:interval];        NSLog(@"当前时区:%@",date);=============================打印输出结果==================================2016-05-21 17:51:08.623 3.24练习[7214:232131] 初始化:2016-05-21 09:51:08 +00002016-05-21 17:51:08.624 3.24练习[7214:232131] dateString1 : 2016521日 下午5:51:082016-05-21 17:51:08.624 3.24练习[7214:232131] dateString2 : 2016521日 下午5:51:082016-05-21 17:51:08.624 3.24练习[7214:232131] 当前时区:2016-05-21 17:51:08 +0000
  • 通过NSCalendar类来创建日期
    NSDateComponents * comp = [[NSDateComponents alloc]init];    [comp setYear:1993]; // 设置年    [comp setMonth:7];  // 设置月    [comp setDay:16]; // 设置日    [comp setHour:9]; // 设置时    [comp setMinute:14]; // 设置分    [comp setSecond:0];// 设置秒    NSCalendar * myCal = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];    NSDate * myDate = [myCal dateFromComponents:comp];    NSLog(@"%@", myDate);

第七讲 内存管理

  • pragma mark –普通情况下的内存管理
        Person *person = [[Person alloc]init];        NSLog(@"%ld",[person retainCount]);//1        // retainCount 用来记录对象的引用计数,所以不会对对象的引用计数产生影响        [person retain];//2        NSLog(@"%ld",[person retainCount]);        [person release];//1        NSLog(@"%ld",[person retainCount]);        [person release];// 0 延时调用        NSLog(@"%ld",[person retainCount]);//1?        [person release];
  • pragma mark –自定义初始化中的内存管理
        //内存管理原则        //1.谁alloc 谁release;        //2.每一个alloc 对应一个release;        NSString *name = [[NSString alloc]initWithFormat:@"rimi"];        Person *person = [[Person alloc]initWithName:name code:@"234" age:34];        [name release];        [person release];        NSLog(@"%ld",[name retainCount]);        NSLog(@"%ld",[person retainCount]);
  • pragma mark –set方法中的内存管理
         BOOK *book1 = [[BOOK alloc]init];//1        Person *person = [[Person alloc]init];        [person setBook:book1];//2        [person setBook:book1];//3        BOOK *book2 = [[BOOK alloc]init];        [person setBook:book2];        [book1 release];//1        NSLog(@"book1=%ld",[book1 retainCount]);        [person release];//0        NSLog(@"book2=%ld",[book2 retainCount]);        NSLog(@"person=%ld",[person retainCount]);        NSMutableString *mutable = [[NSMutableString alloc]initWithFormat:@"123"];        //NSString *string = [mutable retain]; //retain关键字赋值指针 内容不变        NSString *string = [mutable copy];//copy关键字赋值内容        [mutable appendFormat:@"456"];        NSLog(@"%@ %@",mutable,string);
  • pragma mark –便利构造中的内存管理
        NSString *name = [NSString stringWithFormat:@"123"];        Person *person = [Person personWithName:name code:@"123" age:34];        //[person release];//错误 便利构造方法初始化对象 应减少一次release 因为在内方法中alloc已经对应一个autorelease        //[name release];//错误        NSArray *array = [NSArray arrayWithObjects:@"1",@"2",nil];//便利构造方法不需要释放    //Autorelease 的基本方法        //1.会将对象放在自动释放池中        //2.当自动释放池被销毁的时候,会对池中所有的对象进行一次release        //3.刚调用Autorelease的时候,引用计数是不会发生改变的        //4.Autorelease好处 不用关心对象被销毁的时间        //5.Autorelease一般用在内存较小的时候        //特别注意:便利构造方法初始化对象 应减少一次release 因为在内方法中alloc已经对应一个autorelease
  • pragma mark –集合类中的内存管理
     //一个对象加入到数组中 retaincount+1 不影响集合类的retaincount        Person *person1 = [[Person alloc]init];        NSArray *array = [NSArray arrayWithObjects:person1, nil];        NSLog(@"person1 retainCount = %ld",[person1 retainCount]);        NSLog(@"array retainCount = %ld",[array retainCount]);        [array retain];        NSLog(@"array retainCount = %ld",[array retainCount]);    //数组中的retaincount+1 不影响数组中的元素        [array release];        NSLog(@"array retainCount = %ld",[array retainCount]);        =====================================================================        //当集合对象的呗销毁的时候,集合类的元素会进行一次release操作:releasecount-1        Person *person1 = [[Person alloc]init];        NSArray *array = [[NSArray alloc]initWithObjects:person1, nil];        [array retain];        [array release];         //[person1 release];        NSLog(@"array retainCount = %ld",[array retainCount]);        NSLog(@"person1 retainCount = %ld",[person1 retainCount]);
  • pragma mark –循环引用(dog类)
        /*         1.循环引用解决方案         使用@class 关键字导入类,如果需要导入类的属性或者方法,在实现的。m文件里导入该类的头文件;         2.将其中的一个对象改为弱引用,dealloc方法不在释放该对象         */        Person *per1 = [[Person alloc]init];//1        Dog *dog1 = [[Dog alloc]init];//1        per1.dog = dog1;//2        dog1.person = per1;//2        [per1 release]; //per1=1 dog1=2        NSLog(@"per1 = %ld dog1 = %ld",[per1 retainCount],[dog1 retainCount]);        [dog1 release];        NSLog(@"per1 = %ld dog1 =%ld",[per1 retainCount],[dog1 retainCount]);
  • pragma mark –异常情况
        //1.混乱释放        Person *person1 = [[Person alloc]init];        Person *person2 = person1;        //[person2 release];//错误 不遵守内存管理原则        [person1 release]; //谁创建 谁release  =====================================================================        //2.内存泄露        Person *per1 = [[Person alloc]init];        Person *per2 = [[[Person alloc]init]autorelease];        per2 = per1;        [per1 release];        //[per2 release];//错误 造成过度释放  解决办法:增加自动释放  ===================================================================        //3.过度释放        Person *person = [Person personWithName:@"rimi" code:@"1001" age:23];        //[person release]; 错误  便利构造的对象不需要多余的release  =====================================================================        //4. nil 对象的引用计数为0        Person *pernson = nil;        NSLog(@"%ld",[pernson retainCount]);  =====================================================================        //5.常量对象的引用计数为无穷        NSString *string = @"123";        NSString *string1 = [NSString stringWithString:string];        NSLog(@"%ld",[string1 retainCount]);

第八讲 类目、延展、协议

暂无

第九讲 单例、通知、代理引用传值

  • 单例
        //单例在程序的运行中只会被分配一次        //可以在程序的任何一个地方都可以访问和修改它        //单例的生命周期和程序的生命周期一样的        //单例是用类方法创建         NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];        [userDefaults setObject:@"no" forKey:@"取消"];//存储         NSString *string = [userDefaults objectForKey:@"取消"];        NSLog(@"---%@",string);        if ([string isEqualToString:@"yes"])        {            [userDefaults setObject:@"no" forKey:@"取消"];        }        else        {            [userDefaults setObject:@"yes" forKey:@"登录"];        }        NSLog(@"%@",[userDefaults objectForKey:@"登录"]);        [userDefaults synchronize];//数据持久化        //单例可以在程序的任何一个地方都可以访问和修改它        [[NSUserDefaults standardUserDefaults]setObject:@"tom" forKey:@"name"];//存储        [[NSUserDefaults standardUserDefaults]removeObjectForKey:@"name"];//删除        [userDefaults synchronize];//数据持久化        // NSUserDefaults 不能存储自定义对象 
  • 单例的实现举例
        // 简单单例的实现举例,创建一个Teacher单例         // 单例必须类方法创建         Teacher *teacher = [Teacher defaultTeacher];        第一步:在Teacher.h文件声明        @interface Teacher : NSObject<NSCopying>//单例完整        +(Teacher *)defaultTeacher;        @end        第二步:在Teacher.m文件实现        //简单单例的实现 (保证对象的唯一性)        //~~~~~~~~~~~~ 方法① ~~~~~~~~~~~~~~~~~~~~~~~~~~~        static Teacher *teacher = nil;        +(Teacher *)defaultTeacher        {          if (!teacher)            {                teacher = [[Teacher alloc]init];                //(保证对象只被初始化一次)            }            return teacher;        }        //~~~~~~~~~~~~ 方法② ~~~~~~~~~~~~~~~~~~~~~~~~~~~        static dispatch_once_t onceToken;        static Teacher *teacher;        +(Teacher *)defaultTeacher        {        _dispatch_once(&onceToken, ^{            teacher = [[Teacher alloc]init];        });        return teacher;        }        //~~~~~~~~~~~~ 方法③ ~~~~~~~~~~~~~~~~~~~~~~~~~~~        static bool token = NO;        static Teacher *teacher;        +(Teacher *)defaultTeacher        {         if (!token) {             token = YES;                teacher = [[Teacher alloc]init];            }         return teacher;        }        //~~~~~~~~~~~~ 方法④   完成单例的实现 ~~~~~~~~~~~~~~~        /*        自定义单例创建完整方法:        1.遵守<NSCopying>协议        2.覆写copyWithZone:(NSZone *)zone/retain/release/autorelease/retainCount方法        */        static Teacher *teacher;        +(instancetype)allocWithZone:(struct _NSZone *)zone{         @synchronized(self) {                if (!teacher) {                     teacher = [super allocWithZone:zone];                    return teacher;                }                return nil;            }        }        -(id)copyWithZone:(NSZone *)zone        {             return self;        }        -(instancetype)retain        {             return self;        }        -(instancetype)autorelease;        {            return self;        }        - (oneway void)release        {        }        -(NSUInteger)retainCount        {             return NSUIntegerMax;        }
  • 通知
发送通知第一步:通知声明 声明两个字符串(示例)        extern NSString *const TeacherAskQuestionNotification;        extern NSString *const TeacherAskQuestionUserInfokey;第二步:通知赋值        NSString *const TeacherAskQuestionNotification = @"TeacherAskQuestionNotification";        NSString *const TeacherAskQuestionUserInfoKey = @"TeacherAskQuestionUserInfoKey";第三步:发送通知    //postNotificationName:通知的名称    //object:通知的发送者    //userInfo:发送的信息,是以字典的方式发送    [[NSNotificationCenter defaultCenter]postNotificationName:TeacherAskQuestionNotification//发送通知的名称(声明)                                                       object:self//发送通知的对象                                                     userInfo:@{TeacherAskQuestionUserInfoKey:question}];                                                 ===============================================================================接收通知:第一步:注册观察者,接收通知        - (instancetype)initWithName:(NSString *)name        {             self = [super init];                if (self) {                _name =[name copy];                //addObserver:观察者                //selector:接受到通知之后 回调的方法(需要执行的方法)                //name:通知的名称                //object:设置为空                [[NSNotificationCenter defaultCenter]addObserver:self                                                selector:@selector(studentHasReceiveQuestion:)                                                    name:TeacherAskQuestionNotification                                                  object:nil];    }    return self;}第二步:接收到通知之后,回调的方法        -(void)studentHasReceiveQuestion:(NSNotification *)notification{            //获取老师发送的问题 通知发送的内容             NSString *question = [notification.userInfo objectForKey:TeacherAskQuestionUserInfokey];            NSLog(@"student name '%@' receive this question %@",_name,question);            //回答老师的问题            if (self.delegate && [self.delegate respondsToSelector:@selector(student:didFinishAnswerWithQuestionWithResult:)]) {            [self.delegate student:self didFinishAnswerWithQuestionWithResult:_name];            }        }第三步://移除通知        - (void)dealloc        {            // ARC MRC都需要移除通知            [[NSNotificationCenter defaultCenter]removeObserver:self];            [_name release];            [super dealloc];        }
  • 代理、协议
 第一步:在.h文件定义协议的名字和方法(示例)        @class DetailViewController;        // 定义协议头        @protocol DetailViewControllerDelegate <NSObject>        // 协议方法(必须执行)        @optional        - (void)detailViewController:(DetailViewController *)Vc didClickButtonWithColor:(UIColor *)color;        @end 第二步:在.h文件定义协议代理的属性(用于关联代理)定义一个遵守协议的属性,称之为代理        @property (nonatomic, weak) id<DetailViewControllerDelegate> btnDelegate; 第三步:在.m文件实现给协议代理发送消息        - (void)clickBtn:(UIButton *)btn {            NSLog(@"%@",btn.backgroundColor);        // 先要判断代理是否实现了协议方法        if ([self.btnDelegate respondsToSelector:@selector(detailViewController:didClickButtonWithColor:)]) {        // 有实现才正式发送消息给代理        [self.btnDelegate detailViewController:self didClickButtonWithColor:btn.backgroundColor];    }        // 返回        [self dismissViewControllerAnimated:YES completion:nil];}        ===============================================================================代理的第一步:遵守协议            @interface ViewController ()<DetailViewControllerDelegate>代理的第二步:获得委托方(将自己作为委托方的代理)        - (void)clickedNextBtn {            NSLog(@"跳转到下一页");            // 初始化控制器            DetailViewController *detailVc = [[DetailViewController alloc] init];            // 设置当前控制器为代理            detailVc.btnDelegate = self;            // 设置模态跳转动画模式            detailVc.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;            // 显示活动指示器            [self.activityView startAnimating];            // 模拟延时            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{            // 模态跳转             [self presentViewController:detailVc animated:YES completion:nil];            // 跳转后关掉活动指示器            [self.activityView stopAnimating];            });        }代理的第三步:实现代理方法,获得参数         - (void)detailViewController:(DetailViewController *)Vc didClickButtonWithColor:(UIColor *)color {         // 使用传回的颜色设置当前控制器视图的背景色         self.view.backgroundColor = color;        }

第十讲 Block应用、RunTime讲解

*___Block应用_

        ---------------------------------------------        返回值类型   函数名    参数类型      调用         void     (^print)    ()    =   ^(){}        ---------------------------------------------         --------------------------------------------         //无返回值 无参数类型         void (^print)()=^(){            NSLog(@"I am student!");        };        print();//调用Block        //打印:I am student!        --------------------------------------------       //定义一个block变量        void (^printLines)(int number)=^(int number)        {            for (int i = 0; i<number; i++)            {                NSLog(@"----------------");            }        };         printLines(5);       //打印:五条线       --------------------------------------------       //练习:block计算2个数的和        int (^sum1)(int,int)= ^(int a,int b)        {            return a+b;        };        NSLog(@"sum = %d",sum1(5,6));      //打印:sum = 11      --------------------------------------------      //练习:指向函数的指针 (对比block) 注意此处sum的调用        int (*p)(int,int) = sum;        int number = p(4,5);        NSLog(@"number: %d",number);
  • block访问外部变量
        //1.对于基本数据类型,调用的时候是拷贝的,可以访问外部变量,但是不能修改局部变量        //2.若需要修改局部变量 应该加一个 __block关键字        __block int number = 12; //__block关键字 表示同一个地址内存         //int number = 12;      // 两个number的地址不一样        //定义一个变量        void (^block)();// =12;        block = ^(){            number = 15;            NSLog(@"number = %d",number);        };// =15        NSLog(@"block调用之前 number= %d",number);//=12        number = 18;        NSLog(@"18 => %d",number);//=18        //调用block        block();        NSLog(@"block调用之后 number= %d",number);//15        number = 28;        NSLog(@" number= %d",number);        
  • block对于对象类型
        //相当于指针复制,指向同一块内部        NSMutableArray *array = [NSMutableArray arrayWithObjects:@"1",@"2",@"3",nil];        void (^myBlock)()=^(){            [array addObject:@"4"];            NSLog(@"myBlock 里面的%@",array);        };        //先为array增接一个元素        [array addObject:@"6"];        NSLog(@"%@",array);        myBlock();        NSLog(@"myBlock 调用后之后的值%@",array);
  • 引用Block传值
参考BlockDemo\OC阶段最后一讲
  • RunTime

    相关练习参考OC阶段第十讲课

    RunTime简称运行时,就是系统在运行的时候的一些机制,是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API。 在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者 比如说,下面一个创建对象的方法中, 举例: OC : [[MJPerson alloc] init] runtime : objc_msgSend(objc_msgSend(“MJPerson” , “alloc”), “init”)
    在程序运行过程中, 可以动态创建一个类(比如KVO的底层实现),可以动态地为某个类添加属性\方法, 修改属性值\方法,可以遍历一个类的所有成员变量(属性)\所有方法


1 0
原创粉丝点击