ios 字符串内插字符串


Swift 5 introduced a decent version of string interpolation with SE-228 and updated the old version of the ExpressibleByStringInterpolation protocol that has been deprecated since Swift 3. The new version of this protocol allows us to write powerful extensions to existing types that define how objects interact when used within string interpolation.

Swift 5引入了SE-228的体面版本的字符串插值,并更新了自Swift 3起就已弃用的ExpressibleByStringInterpolation协议的旧版本。该协议的新版本使我们能够对定义对象交互方式的现有类型编写强大的扩展。在字符串插值中使用时。

While developing apps, we’re oftentimes printing out data that helps us understand our apps during testing or debugging. Using custom debug descriptions to improve debugging is one way of improving the way we work with strings in Swift, but we can reach another level by combining this with the advantages of string interpolation.

在开发应用程序时,我们通常会打印出有助于我们在测试或调试过程中了解我们的应用程序的数据。 使用自定义调试描述来改善调试是一种改进我们在Swift中处理字符串的方式的方法,但是通过将其与字符串插值的优点结合起来,我们可以达到另一个层次。

(What Is String Interpolation?)

The name is quite self-explanatory — it’s all about interpolating values into strings. In other words, adding a string to another string.

这个名称是不言自明的-都是关于将值插值到字符串中。 换句话说,将一个字符串添加到另一个字符串。

The simplest example of this looks as follows:

最简单的示例如下所示:

let name = "Antoine van der Lee"
print("Hello, I'm \(name)")

In this example, we’ve interpolated the name into the print statement. This results in a printed sentence: “Hello, I’m Antoine van der Lee.” Underneath, we’ve made use of the DefaultStringInterpolation structure that handles interpolating values by default and added the name to the "Hello, I'm" string value.

在此示例中,我们将名称插入了print语句。 结果是一个打印的句子:“你好,我是Antoine van der Lee。” 在下面,我们利用了DefaultStringInterpolation结构,该结构默认处理插值,并将名称添加到"Hello, I'm"字符串值中。

Swift allows us to extend this default behavior by adding our own custom string interpolation logic for specific types, so let’s go over four useful cases you can use during day-to-day development.

Swift允许我们通过添加针对特定类型的自定义字符串插值逻辑来扩展此默认行为,因此让我们看一下可以在日常开发中使用的四种有用的情况。

情况1:打印可选 (Case 1: Printing Optionals)

Printing optionals in Swift can be quite painful. There are several options you can take:

在Swift中打印可选选项可能会很痛苦。 您可以采取几种选择:



The latter is often suggested by the compiler:

编译器通常建议使用后者:

String interpolation produces a debug description for an optional value; did you mean to make this explicit?- Use

I’ve been using this in projects, which resulted in cluttered outputs with not very useful Optional() keywords in my logs. In many cases, I ended up using the default value approach, which doesn’t always result in clean string interpolation. Therefore, I decided to write a custom string interpolation solution that handles optional values:

我在项目中一直使用它,导致输出混乱,日志中的Optional()关键字不是非常有用。 在许多情况下,我最终使用默认值方法,但这种方法并不总是会产生干净的字符串插值。 因此,我决定编写一个处理可选值的自定义字符串插值解决方案:



This now allows us to print out optionals as we could before, but we no longer get the compiler suggestion:

现在,这使我们能够像以前一样打印出可选选项,但不再获得编译器建议:

print("The title is \(title)")
// Prints: The title is SwiftLee - A blog about Swift

The value is printed out nicely without the Optional(..) keyword. If the value is not set, nil will be printed, which clearly states that the value is not set and will help us during debugging sessions.

无需Optional(..)关键字即可很好地打印出该值。 如果未设置该值,则将显示nil ,这清楚地表明未设置该值,这将在调试会话期间为我们提供帮助。

情况2:打印JSON (Case 2: Printing JSON)

Another common use case is printing out JSON responses from data requests. This can be useful during debugging, but the code to print out JSON might not always be on hand. I’ve found myself searching for code on Stack Overflow several times to find out how I could pretty-print JSON from Data.

另一个常见用例是从数据请求中打印出JSON响应。 这在调试期间可能很有用,但是打印出JSON的代码可能并不总是在手边。 我发现自己多次在Stack Overflow上搜索代码,以找出如何从Data漂亮地打印JSON。

To solve this, I’ve created a custom string interpolation method that takes Data as input:

为了解决这个问题,我创建了一个自定义字符串插值方法,该方法将Data作为输入:



This interpolation method introduces a new way of working with string interpolation and requires us to set a property name inside the interpolation. This might be uncommon for you at first, but it can become useful once you understand the possibilities it brings. In this case, our JSON is printed out nicely!

这种插值方法引入了一种处理字符串插值的新方法,并要求我们在插值内部设置属性名称。 起初这对您来说并不常见,但是一旦您了解它带来的可能性,它就会变得很有用。 在这种情况下,可以很好地打印出我们的JSON!



This can also be used directly in URLSessionDataTask responses:

这也可以直接在URLSessionDataTask响应中使用:



情况3:打印URL请求 (Case 3: Printing URL Requests)

Just like with printing JSON responses, it can also be useful to print out any outgoing URLRequest. While developing apps, we often make use of networking requests, and it can be useful to know more about outgoing requests.

就像打印JSON响应一样,打印出所有传出的URLRequest也很有用。 在开发应用程序时,我们经常利用网络请求,这对了解传出请求很有用。

By default, a URLRequest is printed out as follows:

默认情况下, URLRequest的输出如下:



Although this gives us the URL, it could also provide us with information on the HTTP method, included headers, or other useful information that you can think of:

尽管这为我们提供了URL,但它也可以为我们提供有关HTTP方法的信息,包含的标头或您可以想到的其他有用信息:



字符串插值与CustomStringConvertible (String interpolation vs. CustomStringConvertible)

Although this works great, I’ve included this example to also point out that this could’ve been done by using the CustomStringConvertible protocol instead.

尽管这很好用,但我已经包含了此示例,以指出可以通过使用CustomStringConvertible协议来完成此操作。

The reason for pointing this out is that you have to understand that string interpolation only works if you actually combine the value inside a string.

指出这一点的原因是,您必须了解字符串插值仅在将字符串中的值实际组合时才有效。

For instance, the previous example would print out the URL without extra properties if used as follows, even though we’ve configured the string interpolation extension:

例如,即使我们已经配置了字符串插值扩展名,上一个示例也可以按以下方式打印出没有额外属性的URL:

print(request)
// Prints: https://www.avanderlee.com/feed?offset=10&limit=20

The reason for this is that the request is not used inside another string using the \(..) syntax. Instead, it's being printed out using the description value defined in the CustomStringConvertible protocol.

这样做的原因是,在使用\(..)语法的另一个字符串中未使用该请求。 而是使用CustomStringConvertible协议中定义的description值将其打印出来。

If you would like to learn more about this, you can read my article on Using custom debug descriptions to improve debugging.

如果您想进一步了解这一点,可以阅读我的文章“ 使用自定义调试描述来改善调试” 。

情况4:转换为HTML (Case 4: Converting to HTML)

Whenever you’re working with HTML, it might be more readable if you could make use of string interpolation. A common use case would be to include a link in a piece of text.

每当使用HTML时,如果可以使用字符串插值,它可能会更具可读性。 一个常见的用例是在一段文本中包含一个链接。

By default, your String could end up quite cluttered with HTML tags, while you want to keep it readable:

默认情况下,您的String可能最终会被HTML标记弄得很混乱,而您想保持可读性:

"""
   The blog post can be found at <a href="www.avanderlee.com">www.avanderlee.com</a>
"""

Due to the HTML <a></a> tag, we've added some extra syntax to our String, causing it to be less readable. Instead, we could add a custom string interpolation extension that handles adding HTML links to a String:

由于使用HTML <a></a>标签,我们在String添加了一些额外的语法,从而导致其可读性降低。 相反,我们可以添加一个自定义字符串插值扩展名,该扩展名处理将HTML链接添加到String



By using a custom string interpolation method, we allow ourselves to add extra validation logic to make sure that a valid URL is used. We make use of an assertion failure to give ourselves feedback early on during debugging that an invalid URL has been used.

通过使用自定义字符串插值方法,我们允许自己添加额外的验证逻辑,以确保使用了有效的URL。 我们利用断言失败来在调试过程中及早使用无效URL的过程中向自己提供反馈。

With the same idea, you could add support for markdown or other exporting methods. I’ll leave this as an exercise for you!

同样,您可以添加对markdown或其他导出方法的支持。 我将把它作为练习留给您!

(Conclusion)

Custom string interpolation allows you to further optimize working with strings in Swift. Common use cases like printing JSON or optionals can make developing in Swift an even better experience. However, it’s good to know when to use custom string interpolation versus using a CustomStringConvertible protocol implementation.

自定义字符串插值使您可以进一步优化在Swift中使用字符串的方式。 诸如打印JSON或可选对象之类的常见用例可以使在Swift中进行开发的体验更好。 但是,最好知道何时使用自定义字符串插值而不是使用CustomStringConvertible协议实现。

Thanks for reading!

谢谢阅读!