简单聊聊Swift闭包的用法

Swift ——闭包 之前在代码的书写过程中,我们已经或多或少的接触过函数,函数本身也有自己的类型,它由形式参数类型,返回类型组成。如果将函数传递给a变量,那么就可以借助a来调用方法,这里addTwoInts代表函数类型。如果出现了同名函数,但是返回值或者参数不一样,那么就需要指明函数类型。否则就会报 ambiguous user of *** 错误,因为这个时候编译器不知道要给a赋值哪一个参数。把函数赋值给a,那么a里面储存的是什么呢? 运行后打印a,这里看懂存储的是函数类型.这里函数类型也是引用类型,当把函数赋值给a的时候, 阅读详情

1.闭包
闭包是一个捕获了外部变量或者常量的函数,可以有名字的函数,可以是匿名的函数,也可以是不捕获外部变量的函数。所以可以说闭包是特殊的函数。
闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 ObjC 中的代码块(blocks)比较相似。


捕获的变量,可以写在捕获列表里. 如果使用捕获列表,即使省略了参数名字、参数类型、返回类型,也必须要用 in 的关键字
●捕获列表里面的是捕获的是值,不可变,
●未在捕获列表里,捕获到的是地址,可以修改

案例1: 闭包内部不能修改值传递的


案例2: 闭包外部修改值传递的数据,也是无效的


2. 闭包表达式
下面这种,是我们熟知的闭包表达式:一个匿名函数 + 捕获了外部的变量或者常量: 

{ (age: Int) -> Int in 
 return age + 1
}


闭包表达式还可以按照下面的规则,变的更加简洁:
●如果参数及返回值类型可以根据上下文推断出来,则可以省略参数 / 返回值的类型
●如果只有一行,是单表达式,可以省略 return 关键字
●参数的名称可以根据参数的位置,简写成 $0、$1
●如果最后一个参数是闭包,可以使用尾随闭包表达式
●如果只有一个参数,且是闭包,可以省略小括号,直接写尾随闭包

var array = [1, 2, 3]

// 常规写法
array.sort(by: {(item1 : Int, item2: Int) -> Bool in return item1 < item2 }) 
// 省略参数类型
array.sort(by: {(item1, item2) -> Bool in return item1 < item2 })
// 省略返回值类型
array.sort(by: {(item1, item2) in return item1 < item2 })
// 省略 return 关键字
array.sort(by: {(item1, item2) in item1 < item2 })
// 省略小括号(尾随闭包)
array.sort{(item1, item2) in $0 < $1 }
// 省略参数,使用默认的$0 $1
array.sort{ $0 < $1 }
// 甚至整个闭包表达式,只剩下一个 < 符号
array.sort(by: <)


闭包可以当做类型使用,也就是可以用来定义变量、参数、返回值

// 定义变量
var closure : ((Int) -> Int)?
closure = { (age: Int) -> Int in 
   return age + 1
}

// 定义参数
func test(param: ((Int) -> Int)) {
	print(param())
}

// 作为返回值
func getClosure() -> ((Int) -> Int) {
    var closure : ((Int) -> Int) = { (age: Int) -> Int in 
       return age + 1
    }
	return closure
}


3.尾随闭包
当函数的最后一个参数是闭包时,可以使用尾随闭包来增强函数的可读性。在使用尾随闭包时,你不用写出它的参数标签:

func test(closure: () -> Void) {
    ...
}

// 不使用尾随闭包
test(closure: {
    ...
})

// 使用尾随闭包
test() {
    ...
}


4.逃逸闭包
逃逸闭包是指闭包作为参数传入函数中,然而它的生命周期比函数的声明周期还长,也就是闭包需要在函数释放后也可以调用,我们就称这个闭包为逃逸闭包。编译器默认闭包为非逃逸闭包,用@nonescaping修饰。逃逸闭包使用@escaping 修饰。

var completions: [() -> Void] = []
func testClosure(completion: () -> Void) {
    completions.append(completion)
}

此时编译器会报错,提示你这是一个逃逸闭包,我们可以在参数名之前标注 @escaping,用来指明这个闭包是允许“逃逸”出这个函数的。

var completions: [() -> Void] = []
func testEscapingClosure(completion: @escaping () -> Void) {
    completions.append(completion)
}


另外,将一个闭包标记为 @escaping 意味着你必须在闭包中显式地引用 self,而非逃逸闭包则不用。这提醒你可能会一不小心就捕获了self,注意循环引用。

有两种情况需要使用逃逸闭包:
●闭包被赋值给属性或者成员变量
●在延时后,使用闭包
4.1 闭包被赋值给属性或者成员变量

class LGTeacher{
    var age = 18
    var complitionHandler: ((Int)->Void)?

    func makeIncrementer(amount: Int,  handler: @escaping (Int) -> Void){
        var runningTotal = 0
        runningTotal += amount

        self.complitionHandler = handler
    }

    func doSomething(){
        self.makeIncrementer(amount: 10) {
            //会引起循环引用
//            self.age = 20
            print($0)
        }
    }

    deinit {
        print("LGTeaher deinit")
    }
}

func test() {
    let t = LGTeacher()
    t.doSomething()
    t.complitionHandler?(50)
}

test()


4.2 延时执行逃逸闭包

func makeIncrementer(amount: Int,  handler: @escaping (Int) -> Void){
    var runningTotal = 0
    runningTotal += amount

    self.complitionHandler = handler
	// 延时执行
    DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
        self.complitionHandler?(50)
    }
}


5. 自动闭包
解释1:
当闭包作为参数传入时,使用@autoclosure来修饰,就表示如果传入的是一个普通的值,就会被自动包装成一个闭包。这个闭包没有参数,返回值是String, 也就是我们传入的普通的字符串。
解释2:
自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。这种闭包不接受任何参数,让你能够省略闭包的花括号,用一个普通的表达式来代替显式的闭包。
并且自动闭包让你能够延迟求值,因为直到你调用这个闭包,代码段才会被执行。要标注一个闭包是自动闭包,需要使用@autoclosure。

例1:
func debugOutPrint(for condition: Bool , _ message: @autoclosure () -> String){
    if condition {
        print(message())
    }
}

func doSomething() -> String{
    //do something and get error message
    return "NetWork Error Occured"
}
debugOutPrint(for: true, doSomething())
debugOutPrint(for: true, "Application Error Occured")

例2:
// 未使用自动闭包,需要显示用花括号说明这个参数是一个闭包
func test(closure: () -> Bool) {
}
test(closure: { 1 < 2 } )

// 使用自动闭包,只需要传递表达式
func test(closure: @autoclosure () -> String) {
}
test(customer: 1 < 2)


6.闭包捕获的变量的内存结构
我们通过下面这个例子,来探索闭包捕获的变量的内存结构:

func makeIncrementer() -> () -> Int {
    var runningTotal = 12
    func incrementer() -> Int {
        runningTotal += 1
        return runningTotal
    }
    return incrementer
}


🤔 用下面两种方式,执行函数,打印结果是什么?

// 方式一: 直接执行3次函数
print("方式1 - 第1次执行函数:\(makeIncrementer()())")
print("方式1 - 第2次执行函数:\(makeIncrementer()())")
print("方式1 - 第3次执行函数:\(makeIncrementer()())")
print("\n")

// 方法二: 先创建一个函数变量,并执行这个函数变量3次
var makeInc2 = makeIncrementer()
print("方式2 - 第1次执行函数:\(makeInc2())")
print("方式2 - 第2次执行函数:\(makeInc2())")
print("方式2 - 第3次执行函数:\(makeInc2())")


打印结果:


可以看到方式1中,每次执行方法,都是在初始值12的基础上 + 1. 打印的是13。
方式2中,每次执行方法,都是在上一次执行结果的基础上 + 1. 打印的是13、14、15。

第一种结果是在我们的预期之中的,因为我们按照平时的逻辑思考,会认为 runningTotal是方法内的局部变量,每一次执行都会重新初始化成12。所以无论执行多少次,应该都是13呀,为什么方法2中的执行方式却打印出了非预期的值呢?我们尝试通过SIL来探索被 block 捕获的变量的内存结构:


被捕获的变量,会在对上开辟内存空间,所以是引用类型。
●方法 2 中, 创建一个函数的变量,每次执行的都是这个函数变量。对于同一个函数变量,它的内部只有一个 runningTotal的地址,每次执行函数,都会去 runningTotal 的地址上去取值,所以每次拿的都上次 + 1 后的结果。
●方法 1 不能每次都 +1 , 是因为它的本质是创建了3个函数变量,也就对应的在堆上创建了 3个不同的 runningTotal 的内存空间,每个 runningTotal 的初始值都是12,所以执行函数,都是 12 + 1 = 13。
7.闭包的内存结构


还是上面那个例子,我们探究一个方式2中的,定义的函数变量 makeInc2 的数据类型

// 方法二: 先创建一个函数变量,并执行这个函数变量3次
var makeInc2 = makeIncrementer()


1创建一个makeInc2的变量%3
2执行makeIncrementer函数,并将返回值存储到%5中
3将%5的内容存储给%3
这。。。什么都看不出啊。。。我们再下沉一层中间代码,看看 IR 代码:


IR代码就非常详细的展示了整个函数内部的逻辑:
1不止为捕获变量runningTotal在堆内存中创建了内存空间,还在后面追加了一个8字节存放runningTotal的值
2makeIncrementer() 函数的返回值是这个结构体: { i8*, %swift.refcounted* }
a第一个成员变量是闭包incrementer() 的地址
b第二个成员变量是追加了8字节的捕获的外部变量runningTotal地址

我们自己构建一下数据结构:

// makeIncrementer()函数返回的数据结构
struct FuntionData<T>{
    var closuresPointer: UnsafeRawPointer
    var captureValuePointer: UnsafePointer<T>
}

// 闭包incrementer()的数据结构
struct Closures<T> {
    var refCounted: HeapObject
    var value: T
}
// 捕获的外部变量runningTotal的数据结构
struct HeapObject{
    var matedataPointer: UnsafeRawPointer
    var refCount1: UInt32
    var refCount2: UInt32
}

将makeInc变量,与我们构建的数据结构进行内存绑定:

//包装的结构体
struct VoidIntFun {
    var f: () ->Int
}
// 要观察的函数变量
var makeInc = VoidIntFun(f: makeIncrementer())

// 将变量的地址,绑定到我们自己构建的数据结构
let ptr = UnsafeMutablePointer<VoidIntFun>.allocate(capacity: 1)
ptr.initialize(to: makeInc)
let ctx = ptr.withMemoryRebound(to: FuntionData<Closures<Int>>.self, capacity: 1) {
    $0.pointee
}

// 打印闭包incrementer()
print("闭包的地址:\(ctx.closuresPointer)" )

// 打印捕获的外部变量runningTotal
print("捕获的外部变量的HeapObject:\(ctx.captureValuePointer.pointee.heapObject)")
print("捕获的外部变量的value:\(ctx.captureValuePointer.pointee.value)")

打印结果:


由此,我们可以知道:
●闭包其实是个引用类型,
●闭包的数据结构是闭包地址 + 捕获的外部变量(外部变量的HeapObject + 外部变量的值)。
●由于闭包是特殊的函数,所以函数也是引用类型

iOS开发-Swift进阶之闭包,逃逸闭包 & 非逃逸闭包! swift进阶总汇 本文主要分析逃逸闭包 、非逃逸闭包、自动闭包 逃逸闭包 & 非逃逸闭包 逃逸闭包定义 当闭包作为一个实际参数传递给一个函数时,并且是在函数返回之后调用,我们就说这个闭包逃逸了。当声明一个接受闭包作为形式参数的函数时,可以在形式参数前写@escaping来明确闭包是允许逃逸的 如果用@escaping修饰闭包后,我们必须显示的在闭包中使用self swift3.0之后,系统默认闭包参数就是被@nonescaping,可以通过SIL来验证 1、执行时机:在函数体内. 阅读详情

相关推荐

Swift集成本地大模型:OllamaKit客户端库实战指南

在移动与桌面应用开发中,集成人工智能能力已成为提升用户体验的关键。通过REST API调用大语言模型,开发者可以为应用添加智能对话、文本生成等功能。其技术原理基于客户端-服务器架构,应用通过HTTP请求与模型服务交互,获取结构化响应。这一模式的价值在于将复杂的模型推理能力封装为可调用的服务,降低了AI集成的门槛。在实际工程中,Swift开发者常面临网络请求封装、流式响应处理和类型安全等挑战。OllamaKit作为专为Swift生态设计的客户端库,通过强类型结构体和原生async/await支持,优雅地解决了

weixin_30699955的博客 431

【Swift】闭包(Closure)

从上面的函数和闭包的定义中可以看到是相同的,都是传入参数,可对参数进行操作,然后返回一个值。从定义中可以看出,函数是有name的,而闭包没有。那么闭包是如何调用的呢?函数中给这个求面积的函数命名为area,而闭包是用{}包裹起来,在这里闭包是没有名字的,所以将闭包赋值相当于给闭包一个名字,这样闭包就能像函数一样使用。所以area约等于。闭包是特殊的函数,当函数作为参数,或返回值,或匿名函数时,称为闭包。从area函数看到,函数中只传入一个闭包,然后返回一个Double值。

Yzzzzw01的博客 1159

Qwen3.5在昇腾NPU上部署:vLLM-Ascend全链路实战

大语言模型推理框架(如vLLM)通过PagedAttention等内存调度机制,显著提升显存利用率与吞吐性能;国产AI芯片(如昇腾NPU)需配套专用算子优化与硬件感知调度才能释放真实算力。本文聚焦Qwen3.5大语言模型在昇腾平台的端到端部署,深入解析vLLM-Ascend如何协同CANN工具链、适配RoPE位置编码与Tokenizer映射、调优block_size与kv_cache_dtype等关键参数,实现单卡42 tokens/s高吞吐与112ms低延迟。内容覆盖环境验证、源码编译、模型权重转换、服务

weixin_34335458的博客 277

IOS11,Swift4从入门到精通-09闭包

本节内容转载于 http://www.swift51.com/swift4.0/chapter2/07_Closures.html 本页包含内容: 闭包表达式 尾随闭包 值捕获 闭包是引用类型 逃逸闭包 自动闭包 闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数比较相似。 闭包可以...

liu_jiuyang的博客 406

【AI实战】用Coze工作流打造抖音视频文案提取神器——从单链接到批量处理的进阶指南

本文详细介绍了如何利用Coze工作流打造抖音视频文案提取工具,从单链接处理到批量提取的进阶指南。通过AI技术和工作流的结合,用户可以高效提取抖音视频的ASR和OCR文本,大幅提升内容创作效率。文章还涵盖了性能优化、异常处理及实际应用场景扩展,助力开发者快速实现抖音文案自动化提取。

weixin_29210759的博客 278

gtsam 学习十(ISAM2 理论)

翻译自:iSAM2: Incremental Smoothing and Mapping Using the Bayes Tree 摘要 提出了一种新型的贝斯树处理稀疏矩阵,在转化为因子图,可以更好的求解平方根信息和映射问题。 文中提出了三个概念 使用概率密度项进行矩阵分解 介绍如何将矩阵分解转换为贝叶斯数和条件概率密度 基于贝叶斯树提供了一种新的系数非线性优化:ISAM2(进行重新排序和重新线性化,避免了批量更新) 问题描述 文章聚焦与如何用增量实时解决非线性问题, 利用增量即新的测量值实时更新估

weixin_37781153的博客 8407

Swift:闭包(Closures)

本人录制技术视频地址:https://edu.youkuaiyun.com/lecturer/1899 欢迎观看。一、 基本概念 闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。 在Swift中的闭包与C、OC中的blocks和其它编程语言(如C#)中的lambda, javascript中的函数嵌套等类似。 闭包可以捕获和存储上下文中定义的的任何常量和变量的引用。这就是所...

秋恨雪 3094

【项目实战】Qt6 录制屏幕、录制声音生成MP4、AVI、MA3等(完整源码,可直接编译使用)

本文将详细介绍如何利用Qt6多媒体模块中的QMediaCaptureSession、QMediaRecorder、QScreenCapture、QAudioInput、QMediaFormat等功能,实现对屏幕和声音的录制,并生成常见的媒体格式文件,如MP4、AVI、MA3等。我们将探讨如何利用这些功能来实现灵活的视频和音频参数设置,以满足不同需求下的录制和生成要求。我们将重点讨论如何配置视频和音频参数,包括分辨率、帧率、编解码器选择、音频采样率、声道设置等。

yegu001的博客 4937

Swift学习-基础的语法

i        励志作为iOS的开发人员,尽管写代码的时候不会专门的挑选Swift语言,但是肯定都会熟悉Swift这个名字,楼主表示从刚开始学习objc的时候就对Swift这个名字很感兴趣,感觉很高大上,但是从很多博客上也相应的看到相关文章,不得不说,Swift必将成为以后iOS开发的主流,尽管每次更新,Swift语言都会有比较大的更新,但不能代表就不了解他,闲话不多说,想了解Swift的历史可

RITL_Y 993

RTX 50系列显卡选购指南:从Stable Diffusion到深度学习,哪款最适合你的AI需求?

本文深入分析了RTX 50系列显卡如何满足不同的AI应用需求。针对Stable Diffusion图像生成,强调显存容量是关键;对于大语言模型本地推理,需平衡算力与显存;而深度学习训练则更看重算力效率。文章对比了RTX 5090、5080、5070等型号的核心规格与适用场景,并提供了从入门到专业的实战配置建议,帮助用户根据自身AI工作负载精准选择最具性价比的显卡。

linux6sysadmin的博客 689

把 Client 当成 ABAP 系统的多租户底座:从 sy-mandt 到 CDS_CLIENT 的隔离机制与工程实践

本文深入解析SAP ABAP系统中Client概念的本质与应用。Client不仅是数据表的MANDT字段,更是会话级别的隔离边界,贯穿用户登录、授权和数据访问控制全过程。文章从ABAP SQL的隐式Client处理机制出发,详细介绍了USING CLIENT、USING ALL CLIENTS等安全跨客户端访问方式,并对比了传统CLIENT SPECIFIED的风险。同时阐述了ABAP CDS中@ClientHandling注解的类型与算法选择,包括#AUTOMATED自动拼接和#SESSION_VARIA

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 182

iOS UIView动画详解(Swift)

现在的iOS开发中,有很多的动画框架可以使用,包括苹果自带的CoreAnimation框架,Facebook的Pop等等,这些的确都是程序员的利器。但是如果我们仅仅是想要实现一些比较简单的动画呢?杀鸡焉用牛刀。我们直接用UIView就可以了。今天我们就来好好聊聊UIView动画,使用Swift编写(大家可以看到我有时候用OC,有时候用Swift,现在的iOS学习的基本技能看着OC代码能写出Swif

乞力马扎罗的雪CYF的博客 8042

畅游Diffusion数字人(0):专栏文章导航

畅游Diffusion数字人(0):专栏文章导航

沉迷单车的追风少年 1418

智捷公开课马上开始了-欢迎大家一起讨论学习-第一系列读《Swift开发指南(修订版) 》看Swift视频教程

智捷课堂携手51CTO学院、图灵教育联合举办iOS线上培训就业班系列体验公开课。 分享移动开发、移动设计方向最新,最热,最抢眼技术热点以及设计经验。我们每周将最少举办一次公开课,同时会提前安排公开课进度。关于公开课内容,我们将选择时下热门技术与大家分享,同时我们也希望能与大家进行交流,并搜集大家想了解的热点与大家分享。

「智捷课堂」关东升的博客 2334

【AI大模型】DeepSeek + Kimi 高效制作PPT实战详解

AI赋能,使用DeepSeek 高效制作PPT实战详解

congge 1万+

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

swift调用oc_Swift基础语法(三)

属性与方法我们在之前讲过的类和结构体中定义的常量/变量和函数,就是所谓的属性和方法。首先我们聊聊类中的属性。类的属性介绍在Swift的类中,属性分为如下三种:存储属性:用于存储类的实例的常量和变量计算属性:通过某种方式计算出来的属性类属性:与整个类自身相关的属性一、存储属性存储属性是最简单的属性,它作为类实例的一部分,用于存储常量和变量。我们可以给存储属性提供一个默认值,也可以在初始化方...

weixin_39722196的博客 494

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Swift面试题2024:从基础到高阶的全面解析

本文全面解析2024年Swift面试的核心考点,涵盖基础语法、高阶特性与实战陷阱。深入探讨字符串创建、错误处理、值类型与引用类型区别,以及map、协议、泛型等进阶内容,帮助开发者系统掌握Swift语言精髓,从容应对技术面试。

mm9012的博客 684

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

Swift在系统编程中的C交互

这里就体现出UnsafeMutableRawPointer的妙用了——直接拿到C传过来的void*指针,用load(as:)转成具体类型,比OC时代用NSData绕弯子利索多了。总之在系统编程这块,Swift既保持了现代语言的安全特性,又给足了操作底层的能力。说到底,Swift和C交互最关键的是搞清楚内存模型差异。C那边malloc的内存最好在C层释放,Swift创建的对象也要注意ARC会不会提前回收。这里defer保证内存释放,load(as:)明确指定指针类型,比C里直接void清晰多了。

2509_93945719的博客 291

Swift 异步序列 AsyncStream 新“玩法”以及内存泄漏、死循环那些事儿(上)

在本篇博文中,我们讨论了 Swift 5.5 新并发模型中用 AsyncStream 结构创建异步序列的新方法,并比较了它和之前旧的实现有哪些进步。

享受开发,颠倒银河 1964

智捷公开课马上开始了-欢迎大家一起讨论学习-第一系列读《Swift开发指南(修订版) 》看Swift视频教程...

引用: 智捷课堂携手51CTO学院、图灵教育联合举办iOS线上培训就业班系列体验公开课。 分享移动开发、移动设计方向最新,最热,最抢眼技术热点以及设计经验。我们每周将最少举办一次公开课,同时会提前安排公开课进度。关于公开课内容,我们将选择时下热门技术与大家分享,同时我们也希望能与大家进行交流,并搜集大家想了解的热点与大家分享。 直播时间1月16日至2月10日,每周二、周四晚8...

关东升 168

Swift在iOS中的ARKit开发

我的经验是,先别急着写复杂场景,从基础的世界跟踪配置入手——比如ARWorldTrackingConfiguration,它支持六自由度运动跟踪,比单纯的AROrientationTrackingConfiguration强多了。还有,记得处理session中断的情况,比如来电或App切后台,在applicationWillResignActive里暂停session,恢复时再runWithConfiguration,不然回来可能发现虚拟物体全歪了。平面检测是ARKit的常用功能,但新手常抱怨检测不稳定。

2509_93942857的博客 328

Swift 类型系统升级:当协议遇上不可拷贝的类型

今天我想和大家聊聊Swift语言一个很有意思的更新——标准库协议现在开始支持Copyable和Escapable约束了。这看起来可能是个很底层的特性,但实际上它会影响到我们日常的代码设计方式。

记录从移动端、鸿蒙到物联网与AI的完整实战与思考。专注于分享可复用的工程方案与产品思维,尤其深入鸿蒙生态与全栈开发。以十年工程与管理沉淀,为你提供清晰的技术纵深路径。坚信技术的价值在于“贯通”与“落地”。 960

Swift实现摩尔斯电码发送器:从算法到音频播放的完整实践

摩尔斯电码作为一种经典的二进制编码系统,其核心原理是通过点(Dot)和划(Dash)的不同组合来表示字符,这种基于时序的编码方式在通信史上具有重要地位。在现代移动开发中,实现摩尔斯电码的编码与播放,不仅是对字符串处理和状态机等基础算法的实践,更是对异步调度和系统API调用的综合运用。通过Swift语言结合AVFoundation框架,开发者可以构建一个能够实时转换文本并通过设备音频、闪光或振动进行反馈的交互工具。这种技术方案特别适合用于Swift初学者的项目练习,同时也能为有经验的开发者探索并发控制、自定义

weixin_34081595的博客 450

Swift网络编程(一)数据请求

一.前言 1.iOS开发中我们和服务器打交道用到最多的就是数据请求,如果你使用过OC进行开发,相信AFNetworking这个库你并不陌生,今天我们来聊聊swift中的网络请求具体该怎样操作 2.首先给大家介绍下Alamofire,Alamofire是出自AFNetworking开发人员之手的一个基于swift语言的网络操作库,功能类似于AFNetworking,下面我们看下该怎么样使用Ala...

weixin_33923148的博客 286
上一篇: NSNotificationCenter简单概述
下一篇: 2022年度总结|2023又得拼搏
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值