import 指令(将文件的内容在预编译的时候拷贝到写指令的地方)

import <Foundation/Foundation.h>

Foundation 框架

NSLog 函数 NSLog(@"Hello, World!");

NSString

语法: NSString *str = @"jack";
字符串占位符: %@

数据类型

C 语言支持的数据类型

基本数据类型

int double float char

构造类型

数组 结构体 枚举

指针类型

int *p1

空类型

void

typedef 自定义类型

BOOl 类型 YES/NO

Boolean 类型 true/false

class 类

id 类型 万能指针

nil 与 NULL 差不多

SEL 方法选择器

block 代码段

类的定义

语法
    声明:
    @inteface 类名 : NSObject
    {

    }
    @inteface Person : NSObject
    {
        NSString *_name;
        int _age;
        float _height;
    }
    - (void)run;
    - (void)run : (参数类型)形参名称;
    - (void)run : (参数类型1)形参名称1 : (参数类型2)形参名称2;
    - (void)eat : (NSString *)foodName;
    - (void)sum : (int)num1 : (int)num2;
    @end
    实现:
    @implementation 类名
    @end
    实现:
    @implementation Person
    - (void)run
    {
      NSLog(@"这是一个方法");
    }

    - (void)eat: (NSString *)foodName
    {
      NSLog(@"这是一个方法的参数%@", foodName);
    }

    - (int)sum : (int)num1 : (int)num2 {
      int sum = num1 + num2;
      NSLog(@"num1和num2的和是%d", sum);
      return sum;
    }
    @end

实例化

Person *p1 = [Person new];

调用实例方法

[p1 run];
[p1 eat : @"红烧排骨"];
[p1 eat: 1: 2];

方法中访问属性

NULL和nil的区别

NULL一般用于指针不指向内存内存中的任何一块空间
nil一般用于类指针不指向任何对象

类的封装

setter
getter

对象和对象之间的关系(组合/依赖/关联/继承)

static关键字

C语言中的static关键字

a.修饰局部变量
b.修饰全局变量
c.修饰函数

OC中的static关键字

a. static不能修饰属性, 也不能修饰方法
b. static可以修饰方法中的局部变量

如果方法的返回值是当前类的对象, 那么这个方法的返回值写instancetype

self关键字

获取类在代码段中的地址的方式

a. 调试查看对象的isa指针的值
b. 在类方法中查看self的值
c. 调用对象的对象方法class, 就会返回这个对象所属的类在代码中的地址 [person1 class]
d. 调用类的class方法 [Person class]

类的继承

语法(继承所有属性和方法, 包括静态方法和静态属性和类方法):
    @inteface Chinese : Person {

    }
    @end

    @implementation Chinese {

    }
    @end

super关键字

访问修饰符(默认是protected)

@private(只能在对象方法中访问, 子类对象方法无法访问, 无法通过对象访问)
示例
    @inteface Chinese : NSObject {
        @private
        NSString *_name = "Felix";
    }
    @end

    @implementation Chinese {

    }
    @end

@protected(只能在本类和子类的对象方法中访问, 无法通过对象访问)
@package(只能在当前框架中访问, 了解)
@publick(可以在任何地方访问)

修饰符只能修饰属性, 不能修饰方法;

私有属性

将属性写在implementation中

私有方法

只写实现, 不写声明

子类方式的重写

子类在实现的时候重写即可

description方法(每个类都有一个=description方法, 该方法打印的是对象的地址, 可以重写它来适应自己的需求)

sel对象

点语法(就是调用调用对象的setter或者getter方法)

@property

自动生成setter、getter方法的声明(定义还是要自己写);
@inteface Person : NSObject {
    NSString *_name;
    int _age;
}

- (void) setName: (NSString *) name;
- (NSString *) name;

@property int age;
// 生成age的setter和getter的声明
// 也就是 - (void) setName: (NSString *) name;
// - (NSString *) name;
@end

@synthesize

自动生成getter/setter方法的实现
语法
    @synthesize @property名称;
    示例:
        @inteface Person : NSObject {
            NSString *_name;
            int _age;
        }

        @property int age;
        @end

        @implementation Person
        @synthesize
        @end

@property 增强

@inteface Person : NSObject
@property NSString *name;
@end

1) 生成一个私有属性, 类型为NSString, 属性名为_name
2) 生成getter/setter声明
3) 生成getter/setter实现

静态类型和动态类型

静态类型: 一个指针指向的对象是一个本类对象;
动态类型: 一个指针指向的对象不是一个本类对象;

id指针 --> 万能指针类型, 可以指向任意OC对象

id id1 = [Person new];

instancetype 代表方法的返回值是当前这个类的对象

语法
    + (instancetype)person {
        return [self person];
    }

动态类型检测

intanceResonseToSelector 判断一个类中是否有某个方法

resonseToSelector 判断一个对象中是否有某个方法

Person *p1 = [Person new];
BOOL res = [p1 resonseToSelector:@selector(sayHi)];

isKindOfClass方法(对象方法) 判断指定对象是否为指定类的对象或者子类对象

[s1 isKindOfClass: [Person class]]

isMemberOfClass方法(对象方法) 判断指定对象是否为指定类的对象, 不包括子类

[s1 isMemberOfClass: [Person class]]

isSubClassOfClass方法(类范发给) 判断指定对象是否为指定类的子类的对象

构造方法

重写init方法的规范

1) 必须要先调用父类的init方法, 然后将方法的返回值赋值给slef
2) 调用init方法初始化对象有可能失败, 如果初始化失败, 返回的就是nil
3) 判断父类是否初始化成功, 如果初始化成功, 就初始化当前对象的属性
4) 最后, 返回self的值

@implementation Person
- (instancetype)init {
    self = [super init];
    if (self != nil) {

    }
    return slef;
}
@end

带参数的init方法

1) init规范
2) 必须以initWith开头
3) 返回值必须是instancetype

声明
    @inteface Person
    - (instancetype)initWithName:(NSString *)name andAge:(int)age;
    @end
实现
    @implementation Person
    - (instancetype)initWithName:(NSString *)name andAge:(int)age {
        self = [super init];
        if (self != nil) {
           self.name = name;
            self.age = age;
        }
        return slef;
    }
    @end
调用
    Person *felix = [[Person alloc] initWithName: @"小花" andAge : 18]

内存管理

栈区: 局部变量, 当局部变量的作用域被执行完毕之后, 这个局部变量就会被系统立即回收
堆区:OC对象, C函数申请的动态空间
BSS段: 未初始化的全局变量, 静态变量, 一旦初始化以后就会被回收, 并转存到数据段之中
数据段: 已经初始化的全局变量, 静态变量, 直到程序结束的时候才会被回收
代码段: 代码, 程序结束的时候系统会被自动回收存储在代码段中的数据

引用计数器

1) 每一个对象都有一个属性: retainCount, 叫做引用计数器, 类型是unsigned long, 占据8个字节;
引用计数器的作用, 用来记录当前这个对象有多少个人在用

内存管理的分类

MRC: Manual Reference Counting 手动引用计数, 手动没存管理
ARC: Automatic Reference Counting 自动引用计数, 自动内存管理

重写dealloc的规范

必要要调用父类的dealloc方法, 并且调用父类dealloc的方法必须放在dealloc方法的最后;

@property参数

@property的四组参数(参数顺序可以随意, 但是一般按照如下顺序写)
a. 与多线程相关的两个参数
    atomic(多线程安全锁: 安全、效率低下)
    nonatomic(不加多线程安全锁: 不安全、效率高)
b. 与生成的setter方法的实现相关的参数
    assign: 默认值, 生成的setter方法直接赋值
    retain: 生成的setter方法就是标准的MRC的内存管理, 也就是先判断是否为同一个对象, 如果是release旧的, retain新的
    当属性类型是OC对象类型的时候, 那么就用retain, 否则用assign
    注意: 要手动写重写dealloc方法
c. 与生成只读、读写相关的参数
    readonly: 只读, 只会生成getter, 不会生成setter
    readwrite: 默认值, 同时生成getter和setter
d. 与生成的getter setter方法名字相关的参数
    getter、setter
    @property(nonatomic, assign, getter = methodName) age;
    @property(nonatomic, assign, setter = methodName:) age;
e. stong、weak 代表指针类型为强类型还是弱类型(默认是强类型)

# 自动释放池

创建自动释放池
@autoreleasepool
{
    Person *p1 = [[[Person alloc] init] autorelease];
}

分类

注意事项:
1) 分类中只能写方法, 不能写属性;
2) 在分类中使用@property, 只会自动生成声明, 不能自动生成实现, 也不会自动生成私有属性;
3) 在分类中不能直接访问真私有属性(定义在implementation之中), 但是可以通过getter和setter访问
4) 当分类中有和本类同名的方法的时候, 优先调用分类的方法, 哪怕没有引入分类头文件, 如果多个分类中有相同的方法, 优先调用最后编译的分类的;

延展

1) 延展是一个特殊的分类
2) 延展这个分类没有名字
3) 只有声明, 没有实现, 和本类共享一个实现
4) 分类中只能新增方法, 延展中任意成员都可以写
5) 分类中写@property, 只会生成getter setter的声明
    延展中写@property, 会自动生成私有属性, 也会自动生成getter和setter的声明和实现
语法:
    @inteface 本类名 ()
    - (void)run;
    - (void)sleep;
    @end
    没有实现, 在本类中实现
应用:
    为类生成一个私有的@property
    延展一般情况下不会独占一个文件, 都是将延展直接写在本类的实现文件中?

OC在C的基础之上新增了一些数据类型

BOOL
Boolean
class
nil
SEL
id(万能指针)
block

block变量

声明:
    必须要指定block变量存储的代码是否有参数, 是否有返回值
示例:
    返回值类型 (^block变量的名称)(参数列表);
    void (^myBlock1)(); 表示声明了一个block类型的变量叫做myBlock1 这个变量只能储存没有返回值没有参数的代码段
    int (^myBlock2)(int num1, int num2);
初始化:
    代码段的书写格式:
    ^返回值列表(参数列表) {
        代码段;
    }
    ^void () {
        NSLog(@"its a");
        NSLog(@"its b");
    }
    myBlock1 = ^void () {
        NSLog(@"its a");
        NSLog(@"its b");
    }
执行:
    myBlock1();

使用typedef将复杂的block定义简化

typedef void (^NewType)();
NewType block1;
NewType block2;

typedef int (^NewType)(int num1, int num2);

block访问外部变量

1)在block代码块的内部可以取定义在外部的变量的值, 定义在外部的局部变量和外部变量
2) 在block代码块的内部可以修改全局变量的值, 但是不能修改定义在外部的局部变量的值
3) 如果想要修改定义在block外部的局部变量的值, 需要在局部变量前面加上__block修饰符, 例如__block int num = 300;

protocol协议(声明一大堆方法, 然后类去遵守)

语法: @inteface Person : NSObject <协议1, 协议二>

@required(默认值)、@optional(不实现, 都不会报错, required会报警告⚠️, 但是@optional不会)

协议之间的继承

语法:
    @protocol 协议名称 <父协议名称>
    @end

限制协议

1) NSObject <StudentProtocol> *指针名 = [Student new];
    id <StudentProtocol> id = [Student new];
    如果Student队形没有遵守StudentProtocol协议就会报警告
2) 声明一个指针变量, 要求这个指针指向的对象必须遵守多个协议
    NSObject <StudentProtocol, SBPtotocol> *stu;
3) 声明一个指定类型的遵守了协议的学生对象
    Student <StudentProtocol> *stu;

Foundation框架

字符串常用方法

a. stringWithFormat 字符串拼接
    [NSString stringWithFormat: "@大家好, 我叫%@, 我今年%d岁", str, age]
b. lenth 方法, 字符串长度
    NSUInteger len = str.length;
c. characterAtIndex
    Unichar ch = [str characterAtIndex: 2];
d. isEqualToString 判断两个字符是否相同
e. rangeOfString 搜索某个字符第一次出现的下标(indexOf)
    NSRange range = [str rangeOfString];
    NSRange是一个NSRange类型的结构体变量
    typedef struct _NSRange {
        NSUInteger location;    代表子串字主串出现的下标(没有就是unsigned long的最大值)
        NSUInteger length;      代表子串创在主创中匹配的长度(没有就是0)
    } NSRange;
f. subStringFromIndex 字符创截取
    [str subStringFromIndex: 3];    // 从第三个开始截取, 截取到最后
    [str subStringToIndex: 3];    // 从第0个开始截取, 截取指定个数
    [str subStringWithRange: NSMakeRange(2, 3)];    // 从指定位置开始截取, 截取指定个数
g. stringByReplacingOccurrencesOfString 字符串的替换(相当于replace方法)
    NSString *email = @"wasd#qq.com";   // 替换“#”号
    email = [email stringByReplacingOccurrencesOfString: @"#", @"@"];
h. NSString *str = @"1" 字符串转其他类型
    int num = str.intValue;
    int num = str.intValue;
    NSInteger num = str.integerValue;
    double num = str.doubleValue;
    float num = str.floatValue;
    long long num = str.longLongValue;
    bool num = str.boolValue;
i. stringByTrimmingCharactersInSet 去掉字符串前后空格
    [str stringByTrimmingCharactersInSet: [NSCharacterSet whitespaceCharacterSet]];
j. uppercaseString 字符串转大写
   [str uppercaseString];
k. lowercaseString 字符串转小写
   [str lowercaseString];

创建NSRange变量的方法

1. NSRange range;
    range.location = 3;
    range.length = 4;
2. NSRange range = { 3, 7 };
3. NSRange range = { .location = 3, .length = 7 };
4. NSRange range = NSMakeRange(3, 7);

NSMutableString

NSMutableString *str = [NSMutableString string];
[str appendString:@"jack"];
[str appendString:@"rose"]; // 追加
[str appendFormat:@"我今年%ds岁了", age]; // 以拼接的方式追加

NSArray

特点:
    a. 只能存储OC对象, 任意的OC对象
    b. 长度固定, 一旦NSArray数组创建完毕之后, 元素的长度固定, 无法新增, 也无法删除
    c. 每个元素都是紧密相连的, 每一个元素仍然有自己的下标
    d. 元素的类型是id类型(万能指针)
创建方式:
    NSArray *arr = [NSArray arrayWithObejcts: @"rose", @"jack", @"lilei", @"hanmeimei", nil];
简写方式:
    NSArray *arr = @[@"rose", @"jack", @"lilei", @"hanmeimei", ]

NSArray常用属性和方法;

NSArray *arr = @[@"jack", @"rose", @"lilei"];
1. 获取数组长度:
    NSInteger count = arr.count;
2. 获取指定下标的元素
    [arr objectAtIndex: 3];
3. 判断是否包含指定的元素
    [arr containsObject: @"lili"];
4. 获取首个, 结尾的元素
    arr.firstObject;
    arr.lastObject;
5. 查找元素在数组中第一次出现的下标(没有找到就返回NSUInteger的最大值)
    NSUInteger index = [arr indexOfObject: @"rose"];

for-in 循环遍历元素语法

for(NSString *str in arr) {
    NSLog(@"%@", str);
}

使用block遍历 enumerateObjectsUsingBlock

数组转NSString(js的join方法)

NSArray *arr = @[@"jack", @"rose", @"jim"];
NSString *str = [arr componentsJoinedByString: @"-"];

NSString转数组

NSString = @"柳州市, 城中区, 地王财富中心";
NSArray *arr = [str componentsSeparatedByString: @","];

NSMutableArray(支持动态新增删除功能)

创建:
    1. NSMutableArray *arr4 = [NSMutableArray new];
    2. NSMutableArray *arr4 = [[NSMutableArray alloc] init];
    3. NSMutableArray *arr4 = [NSMutableArray array];
    4.NSMutableArray *arr4 = [NSmutableArray arrayWithObjects: @"jack", @"rose", @"lili", nul];
1.新增元素:
    NSMutableArray *arr4 = [NSMutableArray new];
    [arr4 addObject: @"jack"];
2.新增数组:
    NSObject arr = @[@“jack”, @"rose", @"lucy", @"tom"];
    NSMutableArray *arr = [NSMutableArray new];
    [arr addObjectFromArray: arr];
3.指定下标处插入元素;
    NSMutableArray *arr = [NSmutableArray arrayWithObjects: @"jack", @"rose", @"lili", nul];
    [arr insertObject: @"lilei" atIndex: 1];
4.删除指定下标的元素:
    [arr removeObjectAtIndex: 1];
5.删除所有指定的元素:
    [arr removeObject: @"lili"];
6.删除最后一个元素:
    [arr removeLastObject];
7.删除所有元素:
    [arr removeAllObjects];
    

NSNumber

NSNumber *number1 = [NSNumber numberWithInt: 10];
NSNumber *number2 = [NSNumber numberWithInt: 20];
NSNumber *number3 = [NSNumber numberWithInt: 30];
NSNumber *number4 = [NSNumber numberWithInt: 40];

NSArray *arr = @[number1, number2, number3, number4]

遍历:
    for (NSNumber *num in arr) {
        NSLog(@"%D", num.intValue);
    }

简写:
    NSNumber *number1 = @10;
    int num = 10;
    NSNumber *n1 = @(num);

NSDictionary

创建方式:
    NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndkeys:@"jack", @"name", @"18", @"age", nil];
简写:
    NSDictionary *dict = @{@"name": @"rose", @"age": @"18"};
打印:
    NSLog(@"%@", dict);
取值:
    dict[name];
    dict.count;
    [dict obejctForKeys: @"age"];
遍历:
    for (id key in dict) {
        NSLog(@"%@ = %@", key, dict[key]);
    }

使用block遍历 enumerateKeysAndObjectsUsingBlock

NSMutableDictionary

新增key:
    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithObjectsAndkeys: @"jack", @"name", @"18",@"age", nil];
    [dict setObject:@"广州市xx街道", forKey: @"address"];

删除所有的键值对

removeAllObjects

删除指定的键值对

removeObjectForKey
[dict removeObjectForKey: @"age"];

NSFileManager

创建
    NSFileManager *manager = [NSFileManager defaultManage];
1. fileExistsAtPath 判断指定路径下的文件是否存在
    NSString *path = @"/Users/Apple/deastop/cc.mp3";
    BOOL res = [manager fileExistsAtPath: path]

暂停程序sleep

[NSThread sleepForTimeInterval: 10];

CGPoint

声明:
    1. CGPoint p1;
    p1.x = 20;
    p1.y = 30;
    2. CGPoint p1 = {20, 30};
    3. CGPoint p1 = {.x = 20, .y = 30};
    4. CGPiont p1 = CGPointMaker(20, 30);

CGSize

声明:
    1. CGSize size;
    size.x = 20;
    size.y = 30;
    2. CGSize size = {20, 30};
    3. CGSize size = {.x = 20, .y = 30};
    4. CGPiont size = CGSizeMaker(20, 30);

CGRect

CGRect rect;
rect.origin.x = 20;
rect.origin.y = 30;
rect.size.width = 100;
rect.size.height = 200;

NSValue

用来包装结构体, 类似于NSNumber;

字符串和时间相互转换

1. 获取当前系统时间
    NSDate *date = [NSDate new];
    NSLog(@"%@", date);
2. 时间转字符串
    NSDateForMatter *formatter = [NSDateFormatter new];
    formatter.dateFormatter = @"yyyy-MM-DD HH:mm:ss";
    NSString *str = [formatter stringFromDate: date];
3. 字符串转NSDate对象
    NSString *strDate = @“2021年12月12号 12点12分12秒”;
    NSDateForMatter *formatter = [NSDateFormatter new];
    formatter.dateFormatter = @"yyyy年MM月DD号 HH点mm分ss秒";
    NSDate *date = [formatter dateFromString: strDate];

时间计算

NSCalendar获取时间对象的各个部分

单例模式

03-05 21:01