假设我们有:
let a:Int? = nil

// block not executed - unwapping done,type is inferred
if let unwrapped_a = a {
    println(unwrapped_a)
}

// block not executed - unwrapping done,type is specified
if let unwrapped_a:Int = a {
    println(unwrapped_a)
}

// block gets executed - unwrapping not done,new local constant + assignment is done instead? 
if let not_unwrapped_a:Int? = a {
    println(not_unwrapped_a)
}

那么我应该假设Swift在第一种情况下进行了解包,而在第二种情况下进行了分配吗?

这种语法是不是太接近造成混乱?我的意思是,是的,编译器警告您在使用not_unwrapped_a时使用的是可选类型,但仍然如此.

更新:

所以在Airspeed VeLocity的回答之后,我发现另一个(但实际上是相同的)奇怪的情况:

if let not_unwrapped_a:Int???? = a {
    println(not_unwrapped_a)
}

a将默默地包裹在Int ????中.所以这将是一种Int ????? (五) – 因为a已经是可选的.然后它将被解开一次.

解决方法

案例1和案例2是相同的 – 它们都是a对新变量的内容的赋值.唯一的区别是你要离开Swift来推断选项1中unwrapped_a的类型,而你手动给出选项2中的类型.你需要做选项2的主要原因是如果源值不明确 – 例如,如果它是一个可以返回多种类型的重载函数.

案例3非常有趣.

每当你有一个值时,Swift总是愿意默默地将它升级为一个可选的包装值,如果它有助于使类型匹配和代码编译.类型的Swift自动升级是相当罕见的(例如,它不会隐式地将Int16升级为Int32),但是对optionals的值是一个例外.

这意味着您可以在需要可选项的地方传递值,而无需费心去包装它:

func f(maybe: Int?) { ... }

let i = 1

// you can just pass a straight value:
f(i)

// Swift will turn this into this:
f(Optional(i))

所以在你的最后一个例子中,你告诉Swift你想要not_unwrapped_a成为一个Int?.但它是let的一部分,需要在分配给它之前将其解包.

有了这个,Swift可以使其工作的唯一方法是隐式地包装另一个可选项,这就是它的作用.现在它是一个可选项,包含一个包含nil的可选项.这不是一个零值可选 – 这是一个包含值的可选项(包含nil的可选值).展开会给你一个包含nil的可选项.好像什么也没发生.但它确实 – 它被包裹了第二次,然后解开了一次.

如果使用swiftc -dump-ast source.swift编译示例代码,则可以看到这一点.你会看到短语inject_into_optional implicit type =’Int ??’. Int ?? ??是一个包含可选项的可选项.

包含选项的选项不是模糊的边缘情况 – 它们很容易发生.例如,如果你曾经…在包含选项的数组中,或者使用下标从包含选项的字典中获取值,则选项的选项已经参与该过程.

考虑这个问题的另一种方法是,如果你考虑让x = y {}作为*类似函数if_let,定义如下:

func if_let<T>(optVal: T?,block: T->()) {
    if optVal != nil {
        block(optVal!)
    }
}

现在假设您提供了一个采用Int的块? – 也就是说,T将是一个Int?.那么T?将是一个Int ??.当你通过常规的Int?进入if_let和那个块,然后Swift会隐式地将它升级为Int ??使它编译.那基本上是if let not_unwrapped_a:Int?正在发生什么.

我同意,隐式可选升级有时会令人惊讶(更令人惊讶的是Swift将升级返回选项的函数,即如果函数采用(Int) – > Int ?,它将升级(Int) – > Int返回一个可选的替代).但据推测,感觉是潜在的混乱是值得的,因为在这种情况下方便.

*只有一种

ios – 如果在明确指定类型时让它表现得很奇怪的更多相关文章

  1. ios – 类型不符合协议

    我仍然无法理解Swift中泛型的一些微妙之处.我定义了以下类型:viewForValue现在我定义了以下功能.我希望T是一个符合协议SomeProtocol的UIView.但是,当我执行代码时,我收到以下编译错误:似乎在where子句中我不能指定不实现协议的类.这是为什么?

  2. ios – 将Swift项目转换为易于使用的Cocoapods框架

    编辑1:我更新了项目,因此它已经具有框架结构,我只需要弄清楚我将如何向开发人员提供对自定义部件的访问权限.编辑2:我得到了一个答案,但我认为这个问题可能很容易被误解.目标是使其行为和行为像UICollectionView(与委托,数据源,…

  3. ios – 如何在Swift中解包数组元素? (即数组为数组)

    假设我有一个String数组,我想将它映射到一个Int数组我可以使用map功能:Numbers现在是一个Int?数组,但我想要一个Int数组.我知道我可以这样做:但这似乎并不是很迅速.从Int数组转换?对于ArrayofInt,需要使用相当多的样板函数来调用filter和map.有更快捷的方法吗?解决方法更新:Xcode7.2Swift2.1.1

  4. ios – Swift:方法重载只在返回类型上有所不同

    我一直在看Swift类,其中定义了两种方法,它们的返回类型不同.我不习惯使用允许这种语言的语言,所以我去寻找描述它如何在Swift中工作的文档.我在任何地方都找不到任何东西.我本来期望在Swift书中有关于它的整个部分.这记录在哪里?

  5. ios – Swift中没有输入参数的通用函数?

    我有一个通用的Swift函数,如下所示:编译器没有错误,但我不知道如何调用此函数.我试过了:但它不起作用.如何在没有输入参数的情况下在Swift中调用Generic函数?解决方法你需要通过一些调用上下文告诉Swift返回类型是什么:注意,在后一种情况下,只有当someCall采用类似于Any的模糊类型作为其参数时,才需要这样做.相反,someCall被指定为[Int]作为参数,函数本身提供上下文,你可以只写someCall事实上,有时可以非常推断出背景!

  6. ios – swift函数返回一个Array

    我学习Swift,我可以理解如何创建一个简单的函数,它接收一个Array并返回一个Array.我的代码:我得到的红色错误是:引用通用类型“Array”需要解决方法在SwiftArray中是通用类型,所以你必须指定什么类型的数组包含.例如:如果你希望你的函数是通用的,那么使用:如果您不想指定类型或具有通用功能使用任何类型:

  7. ios – 嵌套递归函数

    我试图做一个嵌套递归函数,但是当我编译时,编译器崩溃.这是我的代码:编译器记录arehere解决方法有趣的…它似乎也许在尝试在定义之前捕获到内部的引用时,它是bailing?以下修复它为我们:当然没有嵌套,我们根本没有任何问题,例如以下工作完全如预期:我会说:报告!

  8. ios – 键入’ViewController’不符合协议’UICollectionViewDataSource’

    解决方法您必须在ViewController类中实现这两个方法:附:–您的函数原型应该与上述函数完全匹配(如果存在,请删除任何’!

  9. ios – Swift错误:无法将不可变值作为inout参数传递:’pChData’是’let’常量

    解决方法您正在尝试访问/修改pChData参数,除非您将其声明为inout参数,否则您无法访问/修改该参数.了解有关inout参数here的更多信息.请尝试使用以下代码.

  10. ios – Swift:不能下标'[UIViewController]类型的值吗?

    我试图弄清楚如何在Xcode7(iOS9)上的Swift中解决这个问题,我也遇到了这个错误:Cannotsubscriptavalueoftype‘[UIViewController]?’withanindexoftype‘Int’任何建议表示赞赏.谢谢.我的代码:解决方法尝试:但是,写一下会更安全:另一种选择:这样做的好处是它安全,但不需要将函数的其余部分放在if块中.

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部