Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/94.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift变量-为什么有这么多?_Ios_Swift - Fatal编程技术网

Ios Swift变量-为什么有这么多?

Ios Swift变量-为什么有这么多?,ios,swift,Ios,Swift,Swift(或者至少是Xcode)似乎非常聪明,在创建不会改变的变量时,推荐letvsvar,甚至推荐特殊的\uuu变量名 但是对于许多let变量,我们创建它们只是为了将它们传递到另一个函数中。我们为什么不把任务的“正确的一面”放在它的位置上呢 因此,不是: if let url = NSURL(string: "http://xyzapi.com") { if let data = NSData(contentsOfURL: url) { self.myArray.append(d

Swift(或者至少是Xcode)似乎非常聪明,在创建不会改变的变量时,推荐
let
vs
var
,甚至推荐特殊的
\uuu
变量名

但是对于许多
let
变量,我们创建它们只是为了将它们传递到另一个函数中。我们为什么不把任务的“正确的一面”放在它的位置上呢

因此,不是:

if let url = NSURL(string: "http://xyzapi.com") {
  if let data = NSData(contentsOfURL: url) {
    self.myArray.append(data)
  }
}
…我们可以说:

if let data = NSData(contentsOfURL: NSURL(string: "http://xyzapi.com")!) {
  self.myArray.append(data)
}
我试过这个,看起来效果不错。但是每一个例子、教程、示例代码等等,每一步都会创建(并展开)自己的变量——即使对于不可能为空的东西(比如硬编码字符串“xyzapi.com”)

请不要纠缠于这个确切的例子。这不是关于NSData或NSURL的问题,而是创建这么多无用变量的想法

在其他语言中,我倾向于不在实时/生产代码中创建变量,除非我需要它们。Swift有什么特别的地方可以让它好起来吗?或者(可能)只是因为我在看教程

if let x = something { 

}
在if语句中执行变量的展开,这样您就可以不使用它了!或这通常比使用更安全、更清洁!或者?,但并不总是这样

比如说

var x: Int? = nil

if let y = x {
    // Code will not be done
}

x = 3

if let y = x {
    // y will have a value of 3 and you won't need to use ! or ? to access it.
}

我还可以想象另一个原因:调试时,您可以查找局部变量和常量的内容。创建NSURL实例时,它还可能引发异常或以某种方式不可用

我发现自己也在创建“不必要的”变量,只是为了编写更容易理解和调试的代码


如果你不记录你为什么要做这些事情,那么你能做的下一个最糟糕的事情就是“未命名”。

在第二个例子中,你强制打开url是可选的,而在第一个例子中,你有条件地解除绑定

而且


在第一个示例中,您可以区分哪一个正在归档。它正在创建url对象。或者正在创建数据对象

这在很大程度上是一个风格问题(因此容易以基于意见的方式结束),但无论如何都要尝试提供帮助

在运行时,您提供的选项之间几乎没有差别。这实际上是关于两个问题:

是否要编写防御代码?

<代码> NSURL.init(String:)/CODE >是一个可失败的初始化器,不是每个字符串都是有效的URL,所以API使您考虑如何处理传递不是有效URL的字符串的情况。类似地,

NSData.init(contentsOfURL:)
可能会由于多种原因而失败,因此您需要为零结果做好准备

现在,你对可能失败的准备可能只是忽略它(即当结果为零时什么也不做)或让你的应用程序崩溃。因此,从某种意义上说,这个问题是没有意义的——Swift要求您处理空选项的情况至少需要一个基本的防御编程级别,无论是通过
if let
guard let
、可选链接还是强制展开

如果您是防御性编码,您希望如何处理失败? 所以,一旦你开始编写防御代码,你就需要决定你想要防御的程度。你在做什么样的假设?你想以多快的速度坚持这些假设

对于示例中的第一种情况,当输入字符串不是有效的URL时,
NSURL.init(string:)
会失败。您传递的是一个常量字符串文字,所以您可能知道(或者在开发过程中很快就会发现)您是否有一个有效的URL。而且您肯定知道,在您的配送应用程序中,该URL的有效性在运行时永远不会改变

因此,您完全有理由在
NSURL(字符串:)中强制展开结果(
)http://xyzapi.com”)
)。即使强制展开会导致你的应用程序崩溃,如果可选的是nil,强制展开存在的原因就是为了在你可以断言编译器不能断言的事实的情况下,减少样板文件

现在,一些开发商认为武力解散是一种黑暗势力,并坚持在任何情况下回避它。这就是为什么您会看到这样的教程:

if let url = NSURL(string: "http://xyzapi.com") {
    // ...
}
这种方法有一个好处,在字符串包含无效URL的情况下,强制展开会崩溃,而
if let
则不会

但仍有一个问题是,这是否真的是一个令人满意的优势。在
NSURL.init(字符串:)
失败的情况下,此示例不做任何其他操作。。。因此,括号之间的任何事情都不会发生,括号之后应该发生的任何事情都会继续发生。这可能会导致以后应用程序中出现其他问题,而你也不知道原因

使用强制展开,您可以确切地知道失败的位置,因为您在那里崩溃了,并且因为您在编译时强制展开的是常量,所以您可以断言对常量字符串文本的一个修复对于所有情况都是好的

如果你学究式地避免强制展开,你也应该学究式地处理你的错误。也就是说,您应该这样做:

if let url = NSURL(string: "http://xyzapi.com") {
    // use url
} else {
    // do something about the fact that there's no url
}
或者这个:

guard let url = NSURL(string: "http://xyzapi.com") 
    else { /* do something about no url */ }
// use url

我认为分步骤创建它的目的是因为它更清楚地了解用户正在发生什么。想象一个教程,其中大多数代码都是在一行中创建的。这不是很清楚,也不能帮助用户理解实际发生的事情。埃里克:我希望有第三种选择。我相信会有一些意见,但我也希望有人会知道,通过创建更多变量来浪费内存是可以的。谢谢你,@Eendje。您是在生产代码中保持这种方式(每行创建一个新变量),还是像我在ot中习惯的那样减少变量的数量