编程进阶网 编程进阶网
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接

杨充

专注编程 · 终身学习者
首页
  • 计算机原理
  • 操作系统
  • 网络协议
  • 数据库原理
  • 面向对象
  • 设计原则
  • 设计模式
  • 系统架构
  • 性能优化
  • 编程原理
  • 方案设计
  • 稳定可靠
  • 工程运维
  • 基础认知
  • 线性结构
  • 树与哈希
  • 工业级实现
  • 算法思想
  • 实战与综合
  • 算法题考核
  • C语言入门
  • C综合案例
  • C专栏博客
  • C标准集库
  • C++入门教程
  • C++综合案例
  • C++专栏博客
  • C++开发技巧
  • Java入门教程
  • Java综合案例
  • Java专栏博客
  • Go入门教程
  • Go综合案例
  • Go专栏博客
  • Go开发技巧
  • JavaScript入门
  • JavaScript高级
  • Android库解读
  • Android专栏
  • Android智能硬件
  • iOS ObjC入门
  • iOS Swift入门
  • iOS入门精通
  • Web之Html手册
  • Web之TypeScript
  • Web之Vue高级进阶
  • Linux之QML入门
  • Linux之QT核心库
  • Linux实践开发
  • Python教程
  • Shell&Bash教程
  • 工具脚本
  • 自动化脚本
  • 质量保障
  • 产品思考
  • 软实力
  • 开发流程
  • Git应用
  • 技术模版
  • 技术规范
  • Markdown
  • Mermaid
  • 开源协议
  • JSON工具
  • 文本工具
  • 图片处理
  • 文档转化
  • 代码压缩
  • 关于我
  • 自我精进
  • 职场管理
  • 职场面试
  • 心情杂货
  • 友情链接
  • README
  • Android提升进阶

  • iOS开发和进阶

    • README
    • ObjC编程入门

      • README
      • ObjC基础语法
      • 面向对象编程
      • ObjC高级语法
        • 3.1 枚举的设计和使用
          • 3.1.1 枚举的定义
          • 3.1.2 枚举的使用
          • 3.1.3 枚举的场景
          • 3.1.4 枚举定义值
        • 3.2 协议设计和使用
          • 3.2.1 协议的作用
          • 3.2.2 协议的声明
          • 3.2.3 协议使用步骤
          • 3.2.4 协议实际案例
          • 3.2.5 协议使用场景
          • 3.2.6 协议的判断
        • 3.3 理解动态类型设计
          • 3.3.1 理解动态类型
          • 3.3.2 理解id类型
          • 3.3.3 动态类型检查
          • 3.3.4 动态类型转化
          • 3.3.5 动态类型调用
          • 3.3.6 动态类型弊端
        • 3.4 类别如何使用
          • 3.4.1 理解类别机制
          • 3.4.2 类别使用场景
          • 3.4.3 类别使用案例
        • 3.5 Blocks设计
          • 3.5.1 Block是什么
          • 3.5.2 Block使用
        • 3.6 KVO(键值观察)
          • 3.6.1 添加观察者
          • 3.6.2 回调
        • 3.7 多线程使用
          • 3.7.1 线程基本概念
          • 3.7.2 使用NSThread
          • 3.7.3 NSOperation
          • 3.7.4 GCD多线程
          • 3.7.5 线程安全
      • ObjC内存管理
    • Swift编程入门

    • iOS入门到精通

  • Web开发和进阶

  • Linux应用开发

  • Apps
  • iOS开发和进阶
  • ObjC编程入门
杨充
2025-07-23
目录

ObjC高级语法

# 03.ObjC高级语法

# 目录介绍

  • 3.1 枚举的设计和使用
    • 3.1.1 枚举的定义
    • 3.1.2 枚举的使用
    • 3.1.3 枚举的场景
    • 3.1.4 枚举定义值
  • 3.2 协议与委托
    • 3.2.1 协议的作用
    • 3.2.2 协议的声明
    • 3.2.3 协议使用步骤
    • 3.2.4 协议实际案例
    • 3.2.5 协议使用场景
    • 3.2.6 协议的判断
  • 3.3 理解动态类型设计
    • 3.3.1 理解动态类型
    • 3.3.2 理解id类型
    • 3.3.3 动态类型检查
    • 3.3.4 动态类型转化
    • 3.3.5 动态类型调用
    • 3.3.6 动态类型弊端
  • 3.4 类别如何使用
    • 3.4.1 理解类别机制
    • 3.4.2 类别使用场景
    • 3.4.3 类别使用案例
  • 3.5 Blocks设计
    • 3.5.1 Block是什么
    • 3.5.2 Block使用
  • 3.6 KVO(键值观察)
    • 3.6.1 添加观察者
    • 3.6.2 回调
  • 3.7 多线程使用
    • 3.7.1 线程基本概念
    • 3.7.2 使用NSThread
    • 3.7.3 NSOperation
    • 3.7.4 GCD多线程
    • 3.7.5 线程安全

# 3.1 枚举的设计和使用

# 3.1.1 枚举的定义

定义枚举类型:使用typedef enum关键字来定义枚举类型。在定义时,可以列出枚举的所有可能取值。

typedef enum {
    OptionA,
    OptionB,
    OptionC
} MyEnum;
1
2
3
4
5

枚举常量的默认值:如果没有为枚举常量指定具体的值,它们将按照顺序从0开始自动分配值。第一个常量的默认值为0,后续常量的值依次递增。

# 3.1.2 枚举的使用

使用枚举常量:定义枚举后,可以使用枚举常量来表示不同的取值。枚举常量的命名通常使用大写字母开头,以便与其他常量区分。

MyEnum myValue = OptionB;
1

一篇文章学会typedef enum、NS_ENUM、NS_OPTIONS和移位1 << 0:https://www.jianshu.com/p/dc26d719cc03

# 3.1.3 枚举的场景

应该用枚举来表示状态机的状态、传递给方法的选项以及状态码等值,给这些值起个易懂的名字。

用NS_ENUM与NS_OPRIONS宏来定义枚举类型, 并指明其底层数据类型.这样做可以确保枚举是用开发者所选的底层数据类型实现出来的,而不会采用编译器所选的类型。

# 3.1.4 枚举定义值

在 Objective-C 中,枚举(Enum)可以用来定义一组相关的命名常量。每个枚举常量都有一个与之相关联的整数值。

// 定义一个枚举类型
typedef NS_ENUM(NSInteger, Weekday) {
    Monday = 1,
    Tuesday = 2,
    Wednesday = 3,
    Thursday = 4,
    Friday = 5,
    Saturday = 6,
    Sunday = 7
};
1
2
3
4
5
6
7
8
9
10

# 3.2 协议设计和使用

# 3.2.1 协议的作用

协议(Protocol)是一种定义接口的机制,用于声明一组方法、属性或其他成员,以便其他类遵循(adopt)并实现(implement)。

协议的作用是定义了一套规范,使得不同的类可以遵循相同的接口,从而实现代码的重用和解耦。

# 3.2.2 协议的声明

//@protocol 是用于声明协议(Protocol)的关键字。协议定义了一组方法,用于描述类或对象应该遵循的行为和功能。
@protocol MyProtocol

//协议中的方法声明与类中的方法声明类似,使用以下语法:- (返回类型)方法名;

- (void) doSomething;
- (NSString *) getName;

//@required
@optional
- (NSString *) getAge;

@end
1
2
3
4
5
6
7
8
9
10
11
12
13

@required与@optional

  1. @required修饰的方法的声明,就必须实现,编译器会警告,默认属性
  2. @optional修饰的方法的声明,可以实现或者不实现,不实现编译器也不会警告

# 3.2.3 协议使用步骤

在实践中,可以按照以下步骤使用协议:

  1. 定义协议:使用@protocol关键字定义协议,并在其中声明需要的方法、属性等。
  2. 遵循协议:在类的声明中使用来遵循特定的协议。
  3. 实现协议方法:在类的实现中,根据协议的要求实现相应的方法。
  4. 使用协议:通过协议类型的指针或引用,可以调用协议中定义的方法,而不需要关心具体的类。

# 3.2.4 协议实际案例

// 遵循协议的类
@interface MyClass : NSObject <MyProtocol>
@end

@implementation MyClass
- (void)doSomething {
    NSLog(@"Doing something...");
}
@end

// 使用协议
MyClass *myObject = [[MyClass alloc] init];
id<MyProtocol> objectWithProtocol = myObject;
[objectWithProtocol doSomething];
1
2
3
4
5
6
7
8
9
10
11
12
13
14

# 3.2.5 协议使用场景

协议(Protocol)具有广泛的使用场景,以下是一些常见的协议使用场景:

  1. 委托模式(Delegate Pattern):协议常用于实现委托模式,其中一个类(委托方)将某些任务委托给另一个类(委托对象)来处理。
  2. 数据源模式(Data Source Pattern):协议可以用于实现数据源模式,其中一个类(数据源)提供数据给另一个类(数据使用者)。
  3. 视图控制器之间的通信:协议可以用于视图控制器之间的通信,例如一个视图控制器需要将数据传递给另一个视图控制器。
  4. 网络请求回调:协议可以用于处理网络请求的回调,例如在网络请求完成后通知调用方。

# 3.2.6 协议的判断

如何判断类是否实现了某个协议?要判断一个类是否实现了某个协议,可以使用conformsToProtocol:方法。这个方法可以检查一个类是否遵循了指定的协议。

// 判断类是否实现了某个协议
if ([MyClass conformsToProtocol:@protocol(MyProtocol)]) {
    NSLog(@"MyClass 实现了 MyProtocol 协议");
} else {
    NSLog(@"MyClass 没有实现 MyProtocol 协议");
}
1
2
3
4
5
6

如果你想检查一个对象是否实现了某个协议,可以使用NSObject类的conformsToProtocol:方法。示例如下:

// 判断对象是否实现了某个协议
if ([myObject conformsToProtocol:@protocol(MyProtocol)]) {
    NSLog(@"myObject 实现了 MyProtocol 协议");
} else {
    NSLog(@"myObject 没有实现 MyProtocol 协议");
}
1
2
3
4
5
6

# 3.3 理解动态类型设计

# 3.3.1 理解动态类型

动态类型是指在运行时确定对象的类型,而不是在编译时确定。Objective-C是一种动态类型语言,它允许在运行时进行类型检查和类型转换。

# 3.3.2 理解id类型

id类型:id是Objective-C中的一种特殊类型,表示一个未知类型的对象。

可以将任何对象赋值给id类型的变量,而不需要进行编译时的类型检查。在运行时,可以使用动态类型检查和消息传递来操作id类型的对象。

//1.未知类型的对象:当你不确定一个对象的具体类型时,可以使用id类型来存储该对象的引用。
id unknownObject = someObject;

//2.动态类型检查:通过将对象赋值给id类型的变量,可以使用动态类型检查方法来判断对象的具体类型。
if ([unknownObject isKindOfClass:[NSString class]]) {
    // 对象是NSString类型
} else if ([unknownObject isKindOfClass:[NSNumber class]]) {
    // 对象是NSNumber类型
}

//3.动态方法调用:使用id类型可以在运行时动态调用对象的方法,而不需要在编译时知道方法的具体实现。
id someObject = [SomeClass new];
[someObject performSelector:@selector(someMethod)];

//泛型集合:在Objective-C中,可以使用id类型来实现泛型集合,以存储不同类型的对象。
NSArray<id> *genericArray = @[object1, object2, object3];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

要注意的是,由于id类型是一种未知类型,编译器无法提供类型检查和自动补全等功能。因此,在使用id类型时,需要确保在运行时进行适当的类型检查,以避免潜在的类型错误。

id 和 void * 的区别?id 表示一个指向 Objective-C 对象的指针,而 void * 可以表示为任何指针。

另外,使用 id 声明对象时编辑器不会报错,只有在运行时才会提示错误,所以,推荐使用 NSObject * 而不是直接使用 id 创建一个代表任何类的对象。

# 3.3.3 动态类型检查

动态类型检查:Objective-C提供了一些方法来进行动态类型检查,例如isKindOfClass:和isMemberOfClass:。

这些方法可以在运行时检查对象的类型,判断对象是否属于特定的类或其子类。

//该方法用于检查一个对象是否是指定类或其子类的实例。它会遍历整个继承链,包括父类和祖先类。
if ([someObject isKindOfClass:[NSString class]]) {
    // 对象是NSString类型或其子类的实例
}

//该方法用于检查一个对象是否是指定类的实例,而不包括其子类。
if ([someObject isMemberOfClass:[NSString class]]) {
    // 对象是NSString类型的实例,不包括其子类
}
1
2
3
4
5
6
7
8
9

如果需要检查对象是否遵循特定的协议,可以使用conformsToProtocol:方法。

if ([someObject conformsToProtocol:@protocol(MyProtocol)]) {
    // 对象遵循MyProtocol协议
}
1
2
3

# 3.3.4 动态类型转化

动态类型转换:Objective-C提供了一些方法来进行动态类型转换,例如isKindOfClass:和respondsToSelector:。

这些方法可以在运行时检查对象的类型,并根据需要将对象转换为其他类型。

//可以使用respondsToSelector:方法来检查对象是否实现了特定的方法。
if ([someObject respondsToSelector:@selector(someMethod)]) {
    // 对象实现了someMethod方法
}
1
2
3
4

# 3.3.5 动态类型调用

1.performSelector:动态调用无参数方法。

[obj performSelector:@selector(doSomething)];
1

2.performSelector:withObject:动态调用带一个参数的方法。

[obj performSelector:@selector(doSomethingWith:) withObject:arg];
1

3.performSelector:withObject:withObject:动态调用带两个参数的方法。

[obj performSelector:@selector(doSomethingWith:with:) withObject:arg1 withObject:arg2];
1

4.NSInvocation,用于动态调用任意参数的方法。

SEL selector = @selector(doSomethingWith:with:);
NSMethodSignature *signature = [obj methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:obj];
[invocation setSelector:selector];
[invocation setArgument:&arg1 atIndex:2];
[invocation setArgument:&arg2 atIndex:3];
[invocation invoke];
1
2
3
4
5
6
7
8

动态类型调用的注意事项

  1. 性能开销:动态类型调用比静态类型调用慢,因为需要在运行时查找方法。
  2. 安全性:动态调用可能导致运行时错误(如方法不存在),需要做好检查。
  3. 可读性:过度使用动态类型调用会降低代码的可读性和可维护性。

# 3.3.6 动态类型弊端

动态类型的特性使得Objective-C具有灵活性和可扩展性。它允许在运行时根据实际情况进行类型检查和类型转换,以适应不同的需求和场景。

但需要注意,过度使用动态类型可能会导致代码的可读性和可维护性下降,因此需要谨慎使用。

# 3.4 类别如何使用

# 3.4.1 理解类别机制

类别(Category)是一种机制,用于在不修改原始类的情况下扩展类的功能。类别允许开发者向现有类添加新的方法,以及修改或重写现有方法的实现。

# 3.4.2 类别使用场景

1.扩展类的功能:类别允许在不创建子类或修改原始类的情况下,向现有类添加新的方法。这对于向系统类或第三方库的类添加自定义功能非常有用。

2.方法重写:类别可以重写原始类中的方法实现。当类别中的方法与原始类中的方法同名时,类别中的方法会覆盖原始类中的方法。这使得可以通过类别来修改现有方法的行为。

3.避免命名冲突:在使用类别时,需要注意避免与其他类别或原始类中的方法产生命名冲突。最好使用特定的前缀或命名约定来命名类别中的方法,以确保命名的唯一性。

# 3.4.3 类别使用案例

下面是一个简单的示例,演示了如何使用类别来扩展NSString类的功能:

// 假设有一个名为 NSString+CustomMethods 的类别文件
@interface NSString (CustomMethods)

//反转字符串
- (NSString *)reversedString;

@end

@implementation NSString (CustomMethods)

- (NSString *)reversedString {
    NSMutableString *reversedString = [NSMutableString string];
    for (NSInteger i = self.length - 1; i >= 0; i--) {
        [reversedString appendString:[NSString stringWithFormat:@"%C", [self characterAtIndex:i]]];
    }
    return reversedString;
}

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSString *originalString = @"Hello, World!";
        NSString *reversedString = [originalString reversedString];
        NSLog(@"%@", reversedString); // 输出:!dlroW ,olleH
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 3.5 Blocks设计

# 3.5.1 Block是什么

Blocks 是 Objective-C 中一种特殊的对象,它可以直接执行一段代码,类似其它语言中的 lambda 表达式。

# 3.5.2 Block使用

Block 字面量,我们可以使用 ^ 符创建一个 block 字面量:

^{
NSLog(@"This is a block");
}
1
2
3

类似与 C 中的方法指针,我们可以使用下面的语法去引用一个 block:

void (^simpleBlock)(void);
1

以上可以理解为我们创建了一个 simpleBlock 变量来表示一个参数为 void,返回值也为 void 的方法。之后,我们可以创建方法体:

simpleBlock = ^ {
  NSLog(@"This is a block");
}
1
2
3

当然,我们也可以将上面两个步骤合二为一:

void (^simpleBlock)(void) = ^ {
  NSLog(@"This is a block");
}
1
2
3

另外,block 也可以包含参数和返回值:

double (^addBlock)(double, double) = 
  ^(double firstValue, double secondValue) {
    return firstValue * secondValue;
  };
1
2
3
4

# 3.6 KVO(键值观察)

# 3.6.1 添加观察者

// 添加观察者
[person addObserver:self
         forKeyPath:@"age"
            options:NSKeyValueObservingOptionNew
            context:nil];
1
2
3
4
5

# 3.6.2 回调

// 回调
- (void)observeValueForKeyPath:(NSString *)keyPath 
                      ofObject:(id)object 
                        change:(NSDictionary *)change 
                       context:(void *)context {
    if ([keyPath isEqualToString:@"age"]) {
        NSLog(@"New age: %@", change[NSKeyValueChangeNewKey]);
    }
}
1
2
3
4
5
6
7
8
9

# 3.7 多线程使用

# 3.7.1 线程基本概念

  • 线程:线程是程序执行的最小单位,一个进程可以包含多个线程。
  • 主线程:也称为 UI 线程,负责更新 UI 和处理用户交互。
  • 后台线程:用于执行耗时操作,避免阻塞主线程。

# 3.7.2 使用NSThread

NSThread 是 Objective-C 中最基础的线程管理类,可以显式创建和管理线程。

1.创建线程

// 方式 1:使用类方法
[NSThread detachNewThreadSelector:@selector(threadMethod:) toTarget:self withObject:nil];

// 方式 2:使用实例方法
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(threadMethod:) object:nil];
[thread start];
1
2
3
4
5
6

2.线程方法

- (void)threadMethod:(id)object {
    NSLog(@"Thread is running");
    // 执行耗时操作
    [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
    NSLog(@"Thread finished");
}
1
2
3
4
5
6

3.线程同步

使用 @synchronized 实现线程同步。

@synchronized(self) {
    // 线程安全的代码块
}
1
2
3

# 3.7.3 NSOperation

NSOperation 和 NSOperationQueue 是基于 GCD 的高级抽象,提供了更强大的任务管理功能。

1.创建 NSOperation

NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"Operation is running");
    // 执行耗时操作
    [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
    NSLog(@"Operation finished");
}];
1
2
3
4
5
6

2.创建 NSOperationQueue

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
queue.maxConcurrentOperationCount = 3; // 设置最大并发数
[queue addOperation:operation];
1
2
3

3.依赖关系

可以设置 NSOperation 之间的依赖关系。

NSBlockOperation *operation1 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"Operation 1");
}];
NSBlockOperation *operation2 = [NSBlockOperation blockOperationWithBlock:^{
    NSLog(@"Operation 2");
}];
[operation2 addDependency:operation1]; // operation2 依赖于 operation1
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation1];
[queue addOperation:operation2];
1
2
3
4
5
6
7
8
9
10

# 3.7.4 GCD多线程

Grand Central Dispatch (GCD),GCD 是 Apple 提供的多线程编程解决方案,基于 C 语言 API,性能高效且易于使用。

1.创建队列

  • 主队列:串行队列,用于更新 UI。
  • 全局队列:并发队列,用于执行后台任务。
  • 自定义队列:可以是串行或并发队列。
// 主队列
dispatch_queue_t mainQueue = dispatch_get_main_queue();

// 全局队列
dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// 自定义队列
dispatch_queue_t customQueue = dispatch_queue_create("com.example.customQueue", DISPATCH_QUEUE_SERIAL);
1
2
3
4
5
6
7
8

2.执行任务

// 异步执行
dispatch_async(globalQueue, ^{
    NSLog(@"Background task is running");
    // 执行耗时操作
    [NSThread sleepForTimeInterval:2]; // 模拟耗时操作
    NSLog(@"Background task finished");

    // 回到主线程更新 UI
    dispatch_async(mainQueue, ^{
        NSLog(@"Update UI");
    });
});

// 同步执行(会阻塞当前线程)
dispatch_sync(customQueue, ^{
    NSLog(@"Sync task is running");
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

3.延迟执行

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSLog(@"Delayed task");
});
1
2
3

4.任务组

使用 dispatch_group 管理一组任务。

dispatch_group_t group = dispatch_group_create();
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

dispatch_group_async(group, queue, ^{
    NSLog(@"Task 1");
});
dispatch_group_async(group, queue, ^{
    NSLog(@"Task 2");
});

dispatch_group_notify(group, dispatch_get_main_queue(), ^{
    NSLog(@"All tasks finished");
});
1
2
3
4
5
6
7
8
9
10
11
12
13

# 3.7.5 线程安全

1.使用 @synchronized

@synchronized(self) {
    // 线程安全的代码块
}
1
2
3

2.使用 NSLock

NSLock *lock = [[NSLock alloc] init];
[lock lock];
// 线程安全的代码块
[lock unlock];
1
2
3
4

3.使用 dispatch_semaphore

dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
// 线程安全的代码块
dispatch_semaphore_signal(semaphore);
1
2
3
4
上次更新: 2026/06/10, 11:13:41
面向对象编程
ObjC内存管理

← 面向对象编程 ObjC内存管理→

最近更新
01
信号崩溃快速排查
06-15
02
CoreDump破案
06-15
03
perf火焰图实战
06-15
更多文章>
Theme by Vdoing | Copyright © 2019-2026 杨充 | MIT License | 桂ICP备2024034950号 | 桂公网安备45142202000030
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式