Swift - какие типы использовать? NSString или String


109

С введением Swift я пытался обойти новый язык

Я разработчик iOS и буду использовать такие типы, как NSString, NSInteger, NSDictionaryв приложении. Я заметил, что в электронной книге Apple "Язык программирования Swift" используются типы Swift.String, Int, Dictionary

Я заметил, что типы Swift не имеют (или имеют другие названия) некоторых функций, которые выполняют типы Foundation. Например, NSStringесть lengthнедвижимость. А вот для Swift аналога найти не удалось String.

Мне интересно, должен ли я использовать типы Foundation для приложения iOS?


3
Предпочитаю String. Однако Stringв альфа-версии функциональные возможности все еще немного ограничены, поэтому на данный момент NSStringони будут использоваться в большей степени. Надеемся, они исправят API до GA.
Sulthan

1
Кроме того, вы можете позвонить countElements(str), чтобы ответить на эту конкретную часть вашего вопроса.
Nate Cook

Лучше вы можете вызвать "foo".length" directly in Swift. An implicit cast to NSString`, добавляемый за вас компилятором!
Gabriele Petronella

1
@GabrielePetronella .length может некорректно работать со специальными символами. Например, эмодзи или китайские иероглифы, которые занимают 2 или 3 символа Unicode. countElements - правильный метод.
Fogmeister

Ответы:


98

По возможности следует использовать собственные типы Swift. Язык оптимизирован для их использования, и большая часть функциональных возможностей связана между собственными типами и Foundationтипами.

Хотя Stringи NSStringв основном взаимозаменяемы, т. Е. Вы можете передавать Stringпеременные в методы, которые принимают NSStringпараметры, и наоборот, некоторые методы, похоже, на данный момент не соединяются автоматически. См. Этот ответ для обсуждения того, как получить длину строки, и этот ответ для обсуждения использованияcontainsString() для проверки подстрок. (Отказ от ответственности: я являюсь автором обоих этих ответов)

Я не изучал полностью другие типы данных, но предполагаю, что некоторая версия того, что было сказано выше, также будет верна для Array/ NSArray, Dictionary/NSDictionary и различных числовых типов в Swift иNSNumber

Всякий раз, когда вам нужно использовать один из типов Foundation, вы можете использовать их для явного ввода переменных / констант, как в, var str: NSString = "An NSString"или использовать bridgeToObjectiveC()для существующей переменной / константы типа Swift, как, str.bridgeToObjectiveC().lengthнапример, в. Вы также можете Stringпреобразовать a в объект NSStringс помощью str as NSString.

Однако необходимость в этих методах явно использовать типы Foundation или, по крайней мере, некоторые из них, может быть устаревшей в будущем, поскольку из того, что указано в справочнике по языку , например, String/ NSStringмост должен быть полностью бесшовным.

Подробное обсуждение этого вопроса см. В разделах Использование Swift с какао и Objective-C: Работа с типами данных какао.


4
+1 за ссылку bridgeToObjectiveC()и объяснение связи между NSString и Swift String.
Chris

2
эй, цезарь, я думаю, что bridgeToObjectiveC устарел, если вы хотите обновить свой ответ.
Дэн Болье

В руководстве по Swift 3 я заметил, что типы Foundation передаются по ссылке, а собственные типы передаются по значению (или что-то в этом роде, которое я не совсем понимаю на данный момент). Было бы здорово, если бы вы могли обновить свой ответ, обсуждая последствия этого.
Найджел Б. Пек

27

NSString: создает объекты, которые находятся в куче и всегда передаются по ссылке.

Строка: это тип значения, когда мы его передаем, он передается по значению. как Struct и Enum, String в Swift представляет собой Struct.

public struct String {
 // string implementation 
}

Но при прохождении копия не создается. Он создает копию при первом изменении.

Строка автоматически соединяется с Objective-C как NSString. Если в стандартной библиотеке Swift нет, вам необходимо импортировать платформу Foundation, чтобы получить доступ к методам, определенным NSString.

Swift 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. В остальном они почти взаимозаменяемы
Макс

Отличный ответ. значение vs тип ссылки особенно обратите внимание.
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это просто псевдоним для intили long(в зависимости от архитектуры), поэтому я бы просто использовал Int.

NSDictionaryДругое дело, поскольку Dictionaryэто совершенно отдельная реализация.

В общем, я бы по возможности придерживался быстрых типов, и вы всегда можете конвертировать между ними при необходимости, используя bridgeToObjectiveC()метод, предоставляемый быстрыми классами.


В Intкниге указано, что тип данных Swift совпадает с размером слова в архитектуре. NSIntegerтакже того же размера, что и размер слова архитектуры.
MaddTheSane 05

6

Поскольку целевые типы C по-прежнему отправляются динамически, они, вероятно, будут медленнее. Я бы сказал, что вам лучше всего использовать собственные типы Swift, если вам не нужно взаимодействовать с API-интерфейсами objective-c.


Да, это именно ответ. И отказ от динамически отправляемых методов и доступа к объектным переменным - это все, что делает эти улучшения скорости, о которых они говорили на WWDC. Раньше все, кто беспокоился о производительности, использовали строку C ++ и контейнеры для статической диспетчеризации.
Lothar

5

По возможности используйте собственные типы Swift. Однако в случае String у вас есть «плавный» доступ ко всем таким NSStringметодам:

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

4

Обновление Swift 4

Строка обновляется в Swift 4. Теперь вы можете напрямую вызвать для нее count, и она будет рассматривать кластеры графем как 1 кусок, как эмодзи. NSString не обновляется и подсчитывает его по-другому.

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

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

1
NSStrings, вероятно, не будет обновлен для работы с кластерами графем: это сломает слишком много приложений, которые полагаются на старое поведение. Также NSString.lengthподсчитывает символы UTF16.
MaddTheSane 05

0

Строка - это структура

// в Swift Module

публичная структура String

{

}

NSString - это класс

// в модуле Foundation

открытый класс NSString: NSObject

{

}

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.