Swift-使用哪种类型?NSString或String


109

随着Swift的推出,我一直在努力使自己适应新的语言

我是iOS开发人员,会NSString, NSInteger, NSDictionary在应用程序中使用诸如此类的类型。我注意到在Apple的“ Swift编程语言”电子书中,他们使用了Swift类型String, Int, Dictionary

我注意到Swift类型没有(或命名不同)Foundation类型具有的某些功能。例如NSString具有一个length属性。但是我不能为Swift找到一个类似的东西String

我想知道,对于iOS应用程序,我是否仍应使用Foundation类型?


3
更喜欢String。但是,Stringalpha发行版中的功能仍然受到一些限制,因此目前NSString将更多使用。我们希望他们能在GA之前修复该API。
Sulthan 2014年

1
另外,您可以致电countElements(str),以回答问题的特定部分。
Nate Cook

更好的是,您可以调用"foo".length" directly in Swift. An implicit cast to 编译器为您添加的NSString`!
加布里埃尔·彼得罗内拉2014年

1
@GabrielePetronella .length对于特殊字符可能无法正常工作。例如占2或3个Unicode字符的表情符号或汉字。countElements是使用的正确方法。
Fogmeister 2014年

Answers:


98

您应该尽可能使用Swift本机类型。语言经过优化以使用它们,并且大多数功能在本机类型和Foundation类型之间架起了桥梁。

尽管StringNSString几乎可以互换,即可以将String变量传递到采用NSString参数的方法中,反之亦然,但某些方法目前似乎尚未自动桥接。见这个答案就如何得到一个字符串的长度的讨论,这个答案的讨论使用containsString()来检查子。(免责声明:我是这两个答案的作者)

我还没有完全研究其他数据类型,但是我假设上面所述的某些版本也适用于Array/ NSArrayDictionary/ NSDictionary和Swift和NSNumber

每当您需要使用Foundation类型之一时,就可以使用它们来显式地键入变量/常量,例如,在中,var str: NSString = "An NSString"或者bridgeToObjectiveC()在Swift类型的现有变量/常量上使用,str.bridgeToObjectiveC().length例如。您也可以施放StringNSString使用str as NSString

但是,这些技术将来显式使用Foundation类型或其中至少一些类型的必要性可能会过时,因为例如从语言参考中所述,String/ NSString桥应该是完全无缝的。

有关此主题的详尽讨论,请参阅将Swift与Cocoa和Objective-C结合使用:使用Cocoa数据类型


4
+1,用于引用bridgeToObjectiveC()和说明NSString与Swift的String之间的连接。
克里斯(Chris

2
嘿cezar,如果您想更新答案,我认为bridgeToObjectiveC已过时。
Dan Beaulieu 2015年

我在Swift 3手册中注意到,基础类型是通过引用传递的,而本机类型是通过值传递的(或类似的东西,我目前还不完全了解)。如果您能更新讨论其含义的答案,那就太好了。
Nigel B. Peck

27

NSString:创建驻留在堆中并始终通过引用传递的对象。

字符串:每当我们传递它时,它就是一个值类型,它按值传递。像Struct和Enum一样,String本身也是Swift中的Struct。

public struct String {
 // string implementation 
}

但是,通过时不会创建副本。当您第一次对其进行突变时,它将创建副本。

String作为NSString自动桥接到Objective-C。如果没有Swift标准库,则需要导入Foundation框架以访问由NSString定义的方法。

Swift String非常强大,它具有大量内置函数。

在String上初始化:

var emptyString = ""             // Empty (Mutable)
let anotherString = String()     // empty String immutable    
let a = String(false)           // from boolean: "false"
let d = String(5.999)           //  "    Double "5.99"
let e = String(555)             //  "     Int "555"
// New in Swift 4.2 
let hexString = String(278, radix: 18, uppercase: true) // "F8"

通过重复值创建String:

 let repeatingString = String(repeating:"123", count:2) // "123123"

在Swift 4->字符串是字符集合:

现在,String可以执行任何人都可以对Collection类型执行的所有操作。

有关更多信息,请参阅Apple文档。


2
这个答案应该得到更多的赞成票。这是String和NSString之间的根本区别。它们在其他任何地方几乎都是可以互换的
Max

好答案。值与参考类型的注释尤其如此。
spnkr

11

最好的选择是使用Swift本机类型和类,正如其他一些人指出的那样,NSString具有免费转换为String的功能,但是它们不是100%相同的,例如以下示例

var nsstring: NSString = "\U0001F496"
var string: String = "\U0001F496"

nsstring.length
count(string)

您需要使用方法count()对字符串中的字符进行计数,还要注意nsstring.length返回2,因为它基于UTF16计算其长度。

类似,是相同,否


7

String并且NSString可以互换,因此使用哪一个都不重要。您始终可以使用以下方法在两者之间进行投射

let s = "hello" as NSString

甚至

let s: NSString  = "hello"

NSInteger只是a int或a 的别名long(取决于体系结构),所以我只使用Int

NSDictionary这是另一回事,因为Dictionary它是完全独立的实现。

通常,只要有可能,我都会坚持使用swift类型,并且您始终可以使用bridgeToObjectiveC()swift类提供的方法在所需的两种类型之间进行转换。


Int书中将Swift的数据类型声明为与体系结构的字长相同。NSInteger也与架构的字长相同。
MaddTheSane 2014年

6

由于目标C类型仍然是动态分配的,因此它们可能会变慢。我想说,最好使用Swift本机类型,除非需要与Objective-C API交互


是的,这就是答案。避免动态分派方法和对象变量访问,这就是他们在WWDC上谈到的提高速度的全部方法。过去,每个担心性能的人都使用C ++字符串和容器来获取静态调度。
Lothar 2014年

5

尽可能使用Swift本机类型。但是,对于String而言,您可以“无缝”访问所有这样的NSString方法:

var greeting = "Hello!"
var len = (greeting as NSString).length

4

Swift 4更新

字符串迅速得到修订。4。现在您可以直接在其上调用count,并且它将字素簇视为1个,就像表情符号一样。NSString未更新,并以其他方式对其进行计数。

var nsstring: NSString = "👩‍👩‍👧‍👦"
var string: String = "👩‍👩‍👧‍👦"

print(nsstring.length) // 11
print(string.count)    // 1

1
NSString可能不会更新以处理字素群集:它将破坏太多依赖旧行为的应用程序。另外,还要NSString.length计算UTF16字符。
MaddTheSane

0

字符串是一个结构

//在Swift模块中

公共结构字符串

{

}

NSString是一个类

//在基础模块中

打开类NSString:NSObject

{

}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.