快速有哪些可选项?

如果您是iOS开发人员,则可能遇到过敏捷的语言。 到那时,你们大多数人可能已经迅速成为专家。

当我开始学习Swift时,很难理解Swift中的可选内容。 因此,让我们了解它们是什么。

可选选项是快速编码的基本组成部分。 简单起见, 我们可以说可选函数帮助我们将好的代码与坏的代码分开,从而防止崩溃

不同的编程语言使用不同的预防措施来避免崩溃。 但是在大多数情况下,大多数人是无助的。 但是,在这种情况下,Swift更为实用,而可选选项将帮助您使代码免于崩溃。 嗯,这不是100%正确,但是它将帮助您编写更好的代码。

可选项不包含任何值或保留一些值 。 可选选项允许存储nil ,也就是没有值。

Optional类型是具有两种情况的枚举。 Optional.none等效于nil文字。 Optional.some(Wrapped)存储包装的值。

简而言之,可选是通用枚举。 为了便于理解,请看以下代码:

因此,optional是一个通用枚举,包含2种情况, nonesome和某些方法。 请参考Apple文档以获取更多详细说明。

因此,让我们开始吧。 打开您的xcode并创建一个新的游乐场。 让我们开始前进。

  //:游乐场-名词:人们可以玩耍的地方 
 导入UIKit 
  var numberOfCrashes:整数? 

请看上面的代码。 末尾的问号(?)表示它是一个可选变量。 如果在变量声明的末尾看到一个问号,请理解它可能包含也可能不包含值。 因此,在程序的某些部分,您不知道变量是否有值,然后将其标记为可选。

现在,尝试打印变量’ numberOfCrashes ‘的值。

 打印(numberOfCrashes!) 

变量末尾的感叹号(!)用于展开该值。 此时,代码将崩溃。 这是因为,您只需要强制解开一个没有值的可选变量即可。 您只是选择了一个可选变量,然后说:“嘿! ,给我以价值”,然后您尝试使用它。 但是,如果执行此操作,并且变量中没有值,则程序将崩溃。

  //:游乐场—名词:人们可以玩耍的地方 
 导入UIKit 
  var numberOfCrashes:整数? 
  numberOfCrashes = 3 
 打印(numberOfCrashes!) 

但是,如果在强制解开值之前为变量设置了值,则代码不会崩溃。 但是这种方式实际上是在滥用可选变量。 您不会每次都这样幸运。 但这是不好的编码习惯。

我们现在干什么? 可能我们应该在强制打开可选包装之前进行零检查。

  //:游乐场—名词:人们可以玩耍的地方 
 导入UIKit 
  var numberOfCrashes:整数? 
 如果numberOfCrashes!= nil { 
 打印(numberOfCrashes!) 
  } 

现在,您的代码将不会崩溃,因为仅在执行nil检查后才强制将其包装为可选变量。

快速执行nil检查的方法是使用if let语句(可选绑定,本文稍后会提到)。

  //:游乐场—名词:人们可以玩耍的地方 
 导入UIKit 
  var numberOfCrashes:整数? 
 如果让crashCount = numberOfCrashes { 
  print(crashCount)//与print(numberOfCrashes!)相同 
  } 

上面的方法将检查可选变量’ numberOfCrashes ‘是否包含某个值。 如果存在,则将其复制到名为crashCount的常量,然后仅执行代码块。

每当您看到带有问号的可选变量时,请使用if-let语句确保其不为nil。

问题 :好吧……等等。 我们可以使用if-var进行可选绑定吗?

答案是肯定的 ! 但是在大多数情况下,它是没有用的,因为变量的范围仅在if块内。

注意:如果您在不提供默认值的情况下定义了一个可选变量,则该变量会自动为您设置为nil

 var surveyAnswer: String? 
 // surveyAnswer is automatically set to nil 

解包可选

可以通过以下几种方法完成:

◙强制展开

◙隐式展开

◙可选装订

—强制展开:

如果将变量定义为optional ,则要从该变量获取值,必须将其拆包 。 这仅意味着在变量末尾添加一个感叹号。 通过在访问时直接在结尾添加一个感叹号来进行解包的这种方式称为“ 强制解包”

强制展开容易出错,因此不建议这样做。

  var myString:String? 

myString =“你好,斯威夫特!”
 让x = myString!  //强制展开成功!!! 
  // _______________________________ 
  var myOtherString:String? 

让x = myOtherString! //强制展开错误。 未设置该值。

—隐式展开:

Implicitly Unwrapped Optional是不需要解包的可选内容,因为它是隐式完成的。 这些类型的可选变量用(!)而不是(?)声明。 唯一的变化是这次编译器不会对您大喊大叫。 您可以像普通变量一样使用它。 这样的可选变量将自动解包,并且您不需要在变量的末尾使用任何其他的感叹号来获取分配的值。这种解包的方式称为隐式解包,但是请记住,崩溃的风险很高您将必须手动跟踪变量用法。

 let someString: String! 
print(someString) // risk for crash is high.

我们不必使用! 打印出someString的值。 就像强制展开一样,访问为nil的隐式展开的可选内容将导致整个程序崩溃,并出现运行时错误。

好了,我们可以使用我们的Vehicle类来举一个例子。

 导入UIKit 
 车辆类别{ 
  var模型:字符串! 
  } 
  var cars = Vehicle() 
  print(cars.model)//有时可能会使应用程序崩溃。 该值为零。 

通过使用隐式解包的可选内容,我们保证了编译器在将来有时会为其分配一些值。

在大多数情况下,应避免使用隐式解开的Optionals,因为您无法一直跟踪所有变量,并且在nil时访问整个应用程序时将崩溃。 如果您不确定某个变量是否可以为nil ,请始终默认使用常规的Optional。 解包一个永不为零的变量肯定不会带来太大的伤害。

隐式展开容易出错,因此不建议使用。

让我们举一个简单的例子-

  var myString:String! 

myString =“你好,斯威夫特!”
  let x = myString // x是值为“ Hello,Swift!”的可选字符串。 
  // _______________________________ 
  var myOtherString:String! 

let x = myOtherString // x是可选字符串。 该值未设置(或为nil)。

强制与隐式解包:

 let possibleString: String? = "An optional string." 
 let forcedString: String = possibleString! // requires an exclamation mark 
  _______________ 
 let assumedString: String! = "An implicitly unwrapped optional string." 
 let implicitString: String = assumedString // no need for an exclamation mark 

—可选绑定:

使用可选绑定查找可选对象是否包含值,如果包含,则使该值可用作临时常量或变量。

if语句的可选绑定如下-

 如果让constantName = someOptional { 
//使用“ constantName”声明
}其他{
//未设置someOptional的值(或为nil)。
}

这是拆开可选组件的推荐方法。

  let possibleNumber = "123" // a string nonOptional constant 
 if let actualNumber = Int(possibleNumber) { 
 print("\"\(possibleNumber)\" has an integer value of \(actualNumber)") 
 } else { 
 print("\"\(possibleNumber)\" could not be converted to an integer") 
 } 
 // Prints ""123" has an integer value of 123" 

此代码可以读取为:

“如果由Int(possibleNumber)返回的可选Int包含一个值,则将一个新的常量[ 或变量 ]设置为可选中包含的值,称为actualNumber

您可以根据需要在单个if语句中包含尽可能多的可选绑定和布尔条件,并用逗号分隔。 如果可选绑定中的任何值均为nil或任何布尔条件求值为false ,则整个if语句的条件均视为false 。 以下if语句是等效的:

 if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 { 
 print("\(firstNumber) < \(secondNumber) < 100") 
 } 
 // Prints "4 < 42 < 100" 
 if let firstNumber = Int("4") { 
 if let secondNumber = Int("42") { 
 if firstNumber < secondNumber && secondNumber < 100 { 
 print("\(firstNumber) < \(secondNumber) < 100") 
 } 
 } 
 } 
 // Prints "4 < 42 < 100" 

if语句中使用可选绑定创建的常量和变量仅在if语句的主体内可用。 相反,在guard语句之后的代码行中提供了使用guard语句创建的常量和变量。

深层发掘 :

让我们更多地了解可选内容。 让我们了解一下如何在类内部使用可选参数。

让我们创建一个带有可选变量的类。

  //:游乐场—名词:人们可以玩耍的地方 
 导入UIKit 
 车辆类别{ 
  var模型:字符串? 
  } 

在此, Vehicle类包含一个称为model的可选变量。 现在,我们将创建“ 车辆 ”类型的汽车。

  var car:车辆? 

该可变是可选变量。 这意味着在某个时间点,它可能包含一个值。 那么,现在如果我们要获得汽车的模型,该怎么办? 也许我们可以像这样执行多级if-let语句:

  //:游乐场—名词:人们可以玩耍的地方 
 导入UIKit 
 车辆类别{ 
  var模型:字符串? 
  } 
  var car:车辆? 
 如果让c =汽车{ 
 如果让m = c.model { 
 打印(米) 
  } 
  } 

它将正常工作。 但是有更好的方法。

 如果让c =汽车,则让m = c.model { 
 打印(米) 
  } 

这是单行的if-let语句。 首先它将检查第一个语句。 如果有效,则将执行右边的下一条语句,依此类推。 现在让我们看一下工作代码:

  //:游乐场—名词:人们可以玩耍的地方 
 导入UIKit 
  Vechicle类{ 
  var模型:字符串? 
  } 
  var car:Vechicle? 
  car = Vechicle()//创建了一辆新车 
  car?.model =“兰博基尼” 
 如果让c =汽车,则让m = c.model { 
//仅在car有效且car具有有效模型时执行。
 打印(米) 
  } 

IMP:每当我们在末尾使用带问号的可选内容时,无论何时您要使用dot(。)访问属性或其他内容时,都必须在其前面加上问号并说“嘿,它是可选的,我不知道里面是否有值

为了更好地理解,让我们创建一个可选的车辆阵列。

 导入UIKit 
 车辆类别{ 
  var模型:字符串? 
  } 
  var车:[车辆]? 
 汽车= [车辆]() 
  cars?.append(Vehicle())//点号前面的问号是因为它是一个可选变量。 
 如果让carArray =汽车,则carArray.count> 0 { 
  //仅在cars数组有效且其计数大于零时才执行。 
打印(carArray.count)
  } 

可选链接:

可选链接是用于查询和调用当前可能为nil的可选属性,方法和下标的过程。 如果可选包含值,则属性,方法或下标调用成功;否则,调用成功。 如果可选参数为nil ,则属性,方法或下标调用将返回nil 。 可以将多个查询链接在一起,如果链中的任何链接为nil ,整个链都会正常失败。

因此,在从可选查询中查询值时,我们可以使用可选链接,如果链中的任何值为nil,则整个链都会失败并返回nil。

 let legs = House?.DiningRoom?.Chairs?.Legs?.first 
// just an example.. if chairs is nil, legs will be nil, if house is nil, chairs will obviously be nil and hence the legs..

考虑一类人,它具有一个非可选的变量,称为age

 导入UIKit 
 人类类 
 变量年龄:整数 
  init(age:Int){ 
 自我年龄=年龄 
  } 
  } 

考虑另一个类House ,其类型为Human的可选变量。

 班级房{ 
  var human:人类? 
  } 

现在我们可以创建房屋的对象,并用值初始化人类的年龄。

  var houseObj = House() 
  houseObj.human =人类(年龄:10) 

现在,让我们尝试了解房子里人的年龄。

 让ageOfHumanInHouse = houseObj.human?.age // ageOfHumanInHouse是可选的Int 

由于人员的类型是可选的,因此? 自动添加。 当您访问类型为optional的属性时,Swift将添加? 。 之后有? 将是optional

重要说明:尽管年龄不是可选变量,但由于人类是可选变量,因此年龄也必须是可选变量,因为人类可能为零。

很简单,让我们假设您看到了一个梦,并且梦中有一座豪华住宅。 梦中的房子不是真实的,你知道的。 因此,屋子里的所有东西都像100英寸的弯曲LED电视,车库里的兰博基尼汽车,卧室里的豪华床等等。一切都会是虚构的。 这只是纯粹的常识。

由于ageOfHumanInHouse是可选的Int(Int?),我们可以使用可选的绑定对其进行包装。

 如果让ageOfHumanInHouse = ageOfHumanInHouse { 
 打印(“ \(ageOfHumanInHouse)”) 
  } 

重要提示:可选选项不会互相影响。 为此,我们必须打开一个可选的包装。

什么是零合并运算符?

资料来源: Hackingwithswift

可选选项是Swift中强大的安全来源,但是如果您发现它们在整个代码中乱七八糟,那么它们也会很烦人。 Swift的nil合并运算符可通过展开可选值(如果有值)或提供默认值(如果可选值为空)来帮助解决此问题。

这是一个入门的示例:

 let name: String? = nil 
let unwrappedName = name ?? "Anonymous"

因为name是一个可选字符串,所以我们需要安全地对其进行拆包以确保其具有有意义的值。 无合并运算符– ?? –完全可以做到这一点,但是如果发现可选参数没有值,则使用默认值。 在这种情况下,默认值为“匿名”。 这意味着unwrappedName的数据类型为String而不是String? 因为可以保证它具有价值。

您无需创建单独的变量即可使用nil合并。 例如,这也可以正常工作:

 let name: String? = nil 
print("Hello, \(name ?? "Anonymous")!")

而已。 !

请享用!!

如果您喜欢阅读这篇文章,请分享并给予一些鼓掌,以便其他人可以找到它👏👏👏👏👏!!!!

您可以在Medium上关注我以获取新文章。 另外,在LinkedIn上与我联系。

如果您有任何评论,问题或建议,请随时在下面的评论部分中发布它们!