在本文中,我们将带你了解iOSswift关闭包在这篇文章中,我们将为您详细介绍iOSswift关闭包的方方面面,并解答swift包管理常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Acer
在本文中,我们将带你了解iOS swift 关闭包在这篇文章中,我们将为您详细介绍iOS swift 关闭包的方方面面,并解答swift包管理常见的疑惑,同时我们还将给您一些技巧,以帮助您实现更有效的Acer Swift 3笔记本怎么样 Acer Swift 3笔记本上手图赏、Apple 不再在 iOS 16.2 发布之前签署 iOS 16.1 和 iOS 16.1.1、C++ write and read file via fstream in ios::out,ios::in,ios::app mode、iOS 18发布啦!iOS 18好吗?iOS 18值得更新吗?iOS 18beta版。
本文目录一览:- iOS swift 关闭包(swift包管理)
- Acer Swift 3笔记本怎么样 Acer Swift 3笔记本上手图赏
- Apple 不再在 iOS 16.2 发布之前签署 iOS 16.1 和 iOS 16.1.1
- C++ write and read file via fstream in ios::out,ios::in,ios::app mode
- iOS 18发布啦!iOS 18好吗?iOS 18值得更新吗?iOS 18beta版
iOS swift 关闭包(swift包管理)
一. 闭包表达式(Closure Expression)
在Swift中,可以通过func定义一个函数,也可以通过闭包表达式定义一个函数,闭包表达式和闭包是两回事
闭包表达式的格式如下:
{
(参数列表) -> 返回值类型 in
函数体代码
}
通过func定义一个函数:
func sum(_ v1: Int, _ v2: Int) -> Int { v1 + v2 }
通过闭包表达式定义一个函数:
//通过闭包表达式定义一个函数,然后调用
var fn = {
(v1: Int, v2: Int) -> Int in
return v1 + v2
}
fn(10, 20) //闭包调用的时候默认不用写参数名称的
//通过闭包表达式定义一个函数,并且直接调用
{
(v1: Int, v2: Int) -> Int in
return v1 + v2
}(10, 20)
二. 闭包表达式的简写
//传入两个Int变量,返回一个函数
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int) {
print(fn(v1, v2))
}
//什么都不省略
exec(v1: 10, v2: 20, fn: {
(v1: Int, v2: Int) -> Int in
return v1 + v2
})
//省略参数类型、返回值类型 (因为编译器能推断出来)
exec(v1: 10, v2: 20, fn: {
v1, v2 in return v1 + v2
})
//省略return
exec(v1: 10, v2: 20, fn: {
v1, v2 in v1 + v2
})
//超级简写:$0代表第一个参数,$1代表第二个参数
exec(v1: 10, v2: 20, fn: { $0 + $1 })
//终极简写:只用一个+
exec(v1: 10, v2: 20, fn: +)
三. 尾随闭包
如果将一个很长的闭包表达式作为函数的最后一个实参,使用尾随闭包可以增强函数的可读性。
尾随闭包是一个被书写在函数调用括号外面(后面)的闭包表达式。
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int) {
print(fn(v1, v2))
}
//写成尾随闭包,增强函数的可读性
exec(v1: 10, v2: 20) {
$0 + $1
}
如果闭包表达式是函数的唯一实参,而且使用了尾随闭包的语法,那就不需要在函数名后边写圆括号(因为没其他参数了,肯定可以省略圆括号)
func exec(fn: (Int, Int) -> Int) {
print(fn(1, 2))
}
exec(fn: { $0 + $1 }) //都不省略
exec() { $0 + $1 } //省略标签
exec { $0 + $1 } //省略标签和()
- 忽略参数
func exec(fn: (Int, Int) -> Int) {
print(fn(1, 2))
}
//用_忽略参数
exec { _,_ in 10 } //10
- 示例:数组的排序
sort函数要求传入一个(Element, Element) -> Bool类型的参数:
func sort(by areInIncreasingOrder: (Element, Element) -> Bool)
可以传入函数:
// 返回true: i1排在i2前面,返回false: i1排在i2后面
func cmp(i1: Int, i2: Int) -> Bool {
// 大的排在前面
return i1 > i2
}
var nums = [11, 2, 18, 6, 5, 68, 45]
nums.sort(by: cmp)
// [68, 45, 18, 11, 6, 5, 2]
也可以传入闭包表达式:
nums.sort(by: {
(i1: Int, i2: Int) -> Bool in
return i1 < i2
})
nums.sort(by: { i1, i2 in return i1 < i2 })
nums.sort(by: { i1, i2 in i1 < i2 })
nums.sort(by: { $0 < $1 })
nums.sort(by: <)
nums.sort() { $0 < $1 }
nums.sort { $0 < $1 } //[2, 5, 6, 11, 18, 45, 68]
四. 闭包(Closure)
1. 什么是闭包
网上有各种关于闭包的定义,个人觉得比较严谨的定义是:
一个函数和它所捕获的变量\常量环境组合起来,称为闭包
一般指定义在函数内部的函数
一般它捕获的是外层函数的局部变量\常量
闭包如下:
typealias Fn = (Int) -> Int
//func函数加上捕获的num变量组成闭包
func getFn() -> Fn {
var num = 0
func plus(_ i: Int) -> Int {
num += i
return num
}
return plus
} // 返回的plus和num变量形成了闭包
//闭包表达式加上捕获的num组成闭包
func getFn() -> Fn {
var num = 0
return {
num += $0
return num
}
}
var fn1 = getFn() //想象成创建了一个实例对象
var fn2 = getFn() //想象成再创建一个实例对象
fn1(1) // 1
fn1(3) // 4
fn1(5) // 9
fn2(2) // 2
fn2(4) // 6
fn2(6) // 12
解释如上代码:getFn函数调用的时候,getFn函数里面的num是在栈空间,在getFn函数调用完之前会将num变量拷贝到堆空间,返回的plus和堆空间的num变量形成了闭包,所以以后每次调用闭包的时候闭包里面的num变量一直都是刚开始捕获的那个值。(当getFn函数调用完的时候,栈空间的num变量就被销毁了)
可以把闭包想象成是一个类的实例对象:
内存在堆空间
捕获的局部变量\常量就是对象的成员(存储属性)
组成闭包的函数就是类内部定义的方法
类如下:
class Closure {
var num = 0
func plus(_ i: Int) -> Int {
num += i
return num
}
}
var cs1 = Closure()
var cs2 = Closure()
cs1.plus(1) // 1
cs1.plus(3) // 4
cs1.plus(5) // 9
cs2.plus(2) // 2
cs2.plus(4) // 6
cs2.plus(6) // 12
2. 闭包的本质
typealias Fn = (Int) -> Int
func getFn() -> Fn {
var num = 0
func plus(_ i: Int) -> Int {
num += i
return num
}
return plus
} // 返回的plus和num形成了闭包
var fn1 = getFn() //想象成创建了一个实例对象
var fn2 = getFn() //想象成再创建一个实例对象
fn1(1) // 1
fn1(3) // 4
fn1(5) // 9
fn2(2) // 2
fn2(4) // 6
fn2(6) // 12
print(MemoryLayout.size(ofValue: fn1)) //16
print(MemoryLayout.stride(ofValue: fn1)) //16
print(MemoryLayout.alignment(ofValue: fn1)) //8
下面结论都是MJ老师通过汇编一步一步验证的:
- 没捕获
当plus函数没有捕获外面变量,fn1占用16字节,前8字节存放的是plus函数地址,后8字节为空。
- 全局变量
如果num是全局变量,全局变量不会捕获到堆空间,捕获到堆空间的目的是保住num的命,全局变量在程序运行中一直活着,根本没必要捕获。这时候fn1占用16字节,前8字节存放的是plus函数地址,后8字节为空。
- 捕获了
① 当plus函数捕获了外面变量,fn1占用16个字节,前8个字节存放的是plus函数地址,后8个字节存放的是堆空间的地址值(堆空间分配24字节,前8字节放类型信息,后8字节放引用计数,最后8字节放num)。
② 执行fn1(1)、fn1(3)...最终会调用plus函数,调用plus函数的时候传入两个参数,一个是i,一个是堆空间的地址值,有了堆空间的地址值就能访问num进行一些运算了。
③ fn2也是16字节,前8字节和fn1前8字节一样的,因为都是plus函数的地址值,但是后8字节和fn1不一样,因为堆空间的内存是重新分配的,所以堆空间的地址值不一样。
- 问题:如果将上面的num换成Person对象呢?
func testClosure() {
class Person {
var age: Int = 10
}
typealias Fn = (Int) -> Int
func getFn() -> Fn {
// 局部变量,对象类型
var person1 = Person()
var person2 = Person()
func plus(_ i: Int) -> Int {
person1.age += i
person2.age += i
return person1.age + person2.age
}
return plus
} // 返回的plus和num形成了闭包
var fn1 = getFn()
print(fn1(1)) // 22
print(fn1(3)) // 28
var fn2 = getFn()
print(fn2(2)) // 24
print(fn2(4)) // 32
}
testClosure()
由于我不会看汇编,猜测一下:由于Person对象本来就在堆空间,所以如果plus函数捕获了Person对象,应该是将Person对象的指针保存到闭包里面了,plus函数内部会根据Person对象的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,形成强引用(retain)或者弱引用,这样以后如果要使用Person对象,就直接通过闭包里面Person对象的指针访问就可以了。
3. 关于闭包练习
练习①:
typealias Fn = (Int) -> (Int, Int)
func getFns() -> (Fn, Fn) {
var num1 = 0
var num2 = 0
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += i << 1 //左移1就是乘以2
return (num1, num2)
}
func minus(_ i: Int) -> (Int, Int) {
num1 -= i
num2 -= i << 1 //左移1就是乘以2
return (num1, num2)
}
return (plus, minus)
}
let (p, m) = getFns()
p(5) // (5, 10)
m(4) // (1, 2)
p(3) // (4, 8)
m(2) // (2, 4)
上面的闭包中有两个变量num1、num2,两个函数plus、minus,现在的问题是两个函数是分别捕获num1、num2还是共同捕获num1、num2。
通过汇编分析可知,调用一次getFns(),num1、num2各分配一次堆空间,然后这两个堆空间给plus、minus函数共享。
其实,如果把闭包当成类就更容易理解了,num1、num2相当于类的成员变量,两个函数相当于类的成员函数,结果是一样的,如下:
class Closure {
var num1 = 0
var num2 = 0
func plus(_ i: Int) -> (Int, Int) {
num1 += i
num2 += i << 1
return (num1, num2)
}
func minus(_ i: Int) -> (Int, Int) {
num1 -= i
num2 -= i << 1
return (num1, num2)
}
}
var cs = Closure()
cs.plus(5) // (5, 10)
cs.minus(4) // (1, 2)
cs.plus(3) // (4, 8)
cs.minus(2) // (2, 4)
练习②:
var functions: [() -> Int] = []
for i in 1...3 {
functions.append { i }
//上面是尾随闭包(不接收参数返回i的函数,这个函数作为append的参数)
//和下面注释表示的是一个意思,三个myFunc()函数对应三个i
//func myFunc() -> Int {
// return i
//}
//functions.append(myFunc)
for f in functions {
print(f())
}
// 1
// 2
// 3
首先要看懂上面的尾随闭包。接下来分析为什么打印:1 2 3
分析汇编可知:上面的i捕获了三次(i == 1,i == 2,i == 3),各分配一次堆空间,for循环里面的三个“myFunc()函数”分别访问对应的三个堆空间。
如果把上面的闭包想象成类就是下面这样:
class Closure {
var i: Int
init(_ i: Int) {
self.i = i
}
func get() -> Int {
return i
}
}
var clses: [Closure] = []
for i in 1...3 {
clses.append(Closure(i))
}
for cls in clses {
print(cls.get())
}
- 注意
如果返回值是函数类型,那么参数的修饰要保持统一
func add(_ num: Int) -> (inout Int) -> Void {
func plus(v: inout Int) {
v += num
}
return plus
}
var num = 5
add(20)(&num)
print(num)
如上,add函数返回的函数类型要和plus函数的类型保持一致。
五. 自动闭包
为什么使用延迟加载?如下代码:
func getNumber() -> Int {
let a = 10
let b = 11
print("getNumber")
return a + b
}
func getFirstPositive(_ v1: Int, _ v2: Int) -> Int {
return v1 > 0 ? v1 : v2
}
getFirstPositive(10, getNumber())
打印:getNumber
上面既然第一个参数传入了10,大于0,那么getNumber()就没必要调用了,但是上面还是调用了,所以可以使用延迟加载减少不必要的调用。
如果我们将第二个参数改成不接收任何参数返回一个Int的函数:
func getFirstPositive(_ v1: Int, _ v2: () -> Int) -> Int {
return v1 > 0 ? v1 : v2()
}
//调用getFirstPositive函数
getFirstPositive(10, {
let a = 10
let b = 11
print("getNumber")
return a + b
})
传入10,打印空
传入-10,打印:getNumber
这样就实现了,需要调用第二个函数的时候才调用第二个函数,不需要的时候就不调用。( 比如一些网络请求啊,如果前面的符合条件就没必要进行请求了)
再看下面代码:
// 如果第1个数大于0,返回第一个数。否则返回第2个数
func getFirstPositive(_ v1: Int, _ v2: Int) -> Int {
return v1 > 0 ? v1 : v2
}
getFirstPositive(10, 20) // 10
getFirstPositive(-2, 20) // 20
getFirstPositive(0, -4) // -4
// 改成函数类型的参数,可以让v2延迟加载
func getFirstPositive1(_ v1: Int, _ v2: () -> Int) -> Int? {
return v1 > 0 ? v1 : v2()
}
getFirstPositive1(-4) { 20 } //很丑
//改成自动闭包
func getFirstPositive2(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int? {
return v1 > 0 ? v1 : v2()
}
getFirstPositive2(-4, 20) //自动将 20 封装成闭包 { 20 }
由于我们把第二个参数改成了函数,当传入-4,20的时候就是:getFirstPositive(-4) { 20 },这样写比较丑,所以Swift提供了一种自动闭包的语法糖。
- @autoclosure 会自动将 20 封装成闭包 { 20 }
- @autoclosure 只支持 () -> T 格式的参数
- 空合并运算符 ?? 使用了 @autoclosure 技术,源代码如下:
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?)
rethrows -> T? {
switch optional {
case .some(let value):
return value
case .none:
return try defaultValue()
}
}
推荐
面试题持续更新记得关注我哦!
不同的圈子就有不同的学习方式 ;
(qq群搜索):651612063 群密码:111 进群文件可以直接获取大厂面试题
点击进群
Acer Swift 3笔记本怎么样 Acer Swift 3笔记本上手图赏
Acer Swift 3是宏碁推出的笔记本电脑,具有轻薄时尚等元素,这里为大家带来 Acer Swift 3笔记本上手图赏 ,一起来看看。
14英寸1920*1080的显示屏幕、2.5GHz的英特尔酷睿酷睿i3、i5-7200u/i7处理器、图形128mb英特尔高清显卡620、8GB/256GB的SSD、Windows Hello、指纹识别器,处理速度快可媲美MacBook,售价仅为1398美元(约£1090/1760美元),性价比方面还是不错的。
以上就是 Acer Swift 3笔记本上手图赏 相关内容,希望对你有帮助。
Apple 不再在 iOS 16.2 发布之前签署 iOS 16.1 和 iOS 16.1.1
继 ios 16.1.2 于 11 月 30 日发布后,apple 现已停止签署 ios 16.1 和 ios 16.1.1。
Apple 不再签署 iOS 16.1 和 iOS 16.1.1
iOS 16.1于 10 月发布,具有多项新功能和增强功能,例如 iCloud 共享照片库、适用于 iPhone 用户的 Fitness+、Live Activities 等。在11月份发布的iOS 16.1.1修复了缺陷并改进了安全性。
然后,在 11 月 30 日,Apple 发布了 iOS 16.1.2,以增强 iPhone 14 的崩溃检测功能,并提高无线运营商的兼容性。这是目前正式提供给用户的最新iOS版本。
与此同时,苹果即将在未来几天向公众发布iOS 16.2 。该更新将添加新的 Freeform 应用程序、对 Home 应用程序的改进、面向 iPhone 14 Pro 用户的新的永远在线选项、Apple Music Sing 等。
经常有越狱的iPhone和iPad用户恢复到旧版本的iOS。目前还没有任何迹象显示正在开发适用于 iOS 16 的越狱工具。将 Apple 设备恢复到以前版本的 iOS 有时也会对升级到最新版本的 iOS 后遇到重大错误的用户有所帮助。
从 iOS 16 降级到 iOS 15
即使您无法轻松恢复到iOS 16.1版本,仍有可能将您的设备降级至iOS 15版本以上。Apple正在为使用iOS 15.7.1的用户提供安全更新,导致此情况发生。如果想将 iPhone 或 iPad 降级,就必须使用 Mac 或 PC。
这不是苹果第一次提供让用户继续使用旧版 iOS 的选项。去年,一旦 iOS 15 可用, 用户可以选择在 iOS 14 上停留更长时间 ,而苹果仍在为其发布安全更新。然而, 该公司在几个月后取消了这个选项。
目前尚不清楚 iOS 15.7.1 作为 iOS 16 的替代选项将保留多长时间。
以上就是Apple 不再在 iOS 16.2 发布之前签署 iOS 16.1 和 iOS 16.1.1的详细内容,更多请关注php中文网其它相关文章!
C++ write and read file via fstream in ios::out,ios::in,ios::app mode
#include <iostream> #include <uuid/uuid.h> #include <ostream> #include <istream> #include <fstream> #include <iostream> using namespace std; void retrieveUuid(char *uuidValue); void writeFile2(); void readFile3(); int main() { writeFile2(); readFile3(); return 0; } void readFile3() { fstream wFile; wFile.open("log3.txt",ios::app|ios::in|ios::out); if(!wFile.is_open()) { cout<<"Create or open log3.txt Failed!"<<endl; } string uuidValue; int num=0; while(getline(wFile,uuidValue)) { cout<<"Id="<<++num<<",value="<<uuidValue<<endl; } wFile.close(); printf("Finished!\n"); } void writeFile2() { fstream wFile; wFile.open("log3.txt",ios::app|ios::out|ios::in); if(!wFile.is_open()) { cout<<"Create or open log3.txt Failed!"<<endl; } char *uuidValue=(char*)malloc(40); for(int i=0;i<10000;i++) { retrieveUuid(uuidValue); wFile<<uuidValue<<endl; } free(uuidValue); wFile.close(); } void retrieveUuid(char *uuidValue) { uuid_t newUUID; uuid_generate(newUUID); uuid_unparse(newUUID,uuidValue); }
Complile and run
g++ -g -std=c++2a h2.cpp -o h2 -luuid
Run the ./h2 command
./h2
iOS 18发布啦!iOS 18好吗?iOS 18值得更新吗?iOS 18beta版
ios 18 横空出世,带来了一系列激动人心的新功能。您是否好奇 ios 18 的亮点,它是否值得升级?php小编西瓜带来 ios 18 的全面解读,详细介绍了它的新特性、改进和已解决的错误。如果您正在考虑升级到 ios 18,请继续阅读以了解它的优缺点,并决定它是否适合您的设备和需求。
iOS 18 beta版终于发布啦!iOS 18此次更新是否与预期一样呢? iOS 18更新了哪些内容呢?是否真的值得果粉用户升级呢?
iOS 18的更新内容涵盖了多个方面,旨在提升用户体验和个性化设置。以下是iOS 18的更新内容概览:
定制主屏幕:
用户可以自由
移动应用程序,按照个人喜好调整主屏幕布局。 图标支持深色模式,用户可以为图标着色,打造独特的外观。
应用程序可以随意放置,深色模式APP有更深度的适配,且有色系可选,整体可调节成一种色系。
优化控制中心:
控制中心进行了重新设计,新增了多款快捷组件,用户可以根据需要选择和
排列。 控件页面支持多页布局,用户可滑动访问控制中心的其它页面。
控制中心界面设计已扩展为多页布局,允许用户将不常访问的功能移动到次级页面。
隐私与安全:
iOS 18支持给APP上锁,支持面容识别,同时也能隐藏APP,以加强用户的隐私权限。
用户可以专门控制第三方App可以访问哪些通讯录,进一步保障数据安全。
信息应用更新:
发送的字体样式和表情有更多自定义选项。
支持稍后发送功能。
在无网情况下,iPhone 14及后续机型支持卫星直发。
其他内置应用更新:
邮箱应用进行了更新,分类和摘要功能提高了效率。
钱包应用支持两个手机一碰即可相互转账。
地图应用带来了新的地形图。
相册应用引入了智能功能,查找照片和照片分类更加精准。
附上iOS 18升级方法:
※1、刷机前请做好重要数据资料的备份,或勾选“保留用户资料刷机”,防止重要资料丢失;
※2、请确保移动设备未开启激活锁,或者知道 ID 锁帐号、密码,否则刷机后可能会无法激活设备;
※3、设备升级到 iOS 18后,将无法再降级到“苹果已关闭验证”的固件版本,即使之前使用备份了 SHSH 也不能降级。
打开最新版电脑端,用数据线把手机设备连接到电脑。点击上方“智能刷机”进入到“一键刷机”界面,连接成功会自动匹配iOS 18固件,选择“保留用户资料刷机”立即刷机。
以上就是iOS 18发布啦!iOS 18好吗?iOS 18值得更新吗?iOS 18beta版的详细内容,更多请关注php中文网其它相关文章!
关于iOS swift 关闭包和swift包管理的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于Acer Swift 3笔记本怎么样 Acer Swift 3笔记本上手图赏、Apple 不再在 iOS 16.2 发布之前签署 iOS 16.1 和 iOS 16.1.1、C++ write and read file via fstream in ios::out,ios::in,ios::app mode、iOS 18发布啦!iOS 18好吗?iOS 18值得更新吗?iOS 18beta版的相关信息,请在本站寻找。
本文标签: