Swift - які типи використовувати? NSString або String


109

З впровадженням Swift я намагався обвести голову новою мовою

Я розробник iOS і використовую такі типи, як NSString, NSInteger, NSDictionaryу додатку. Я помітив, що в електронній книзі програми "Мова швидкого програмування" від Apple, вони використовують типи SwiftString, Int, Dictionary

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

Мені цікаво, чи для додатка iOS мені все ж слід використовувати типи Foundation?


3
Віддавайте перевагу String. Однак Stringфункціональність все ще дещо обмежена у випуску альфа-версії, тому NSStringзараз буде використовуватися більше. Ми сподіваємось, що вони виправлять API до GA.
Султан

1
Також ви можете зателефонувати countElements(str), щоб відповісти на конкретну частину вашого питання.
Нейт Кук

Краще, ви можете зателефонувати на "foo".length" directly in Swift. An implicit cast to NSString`, доданий вам компілятором!
Габріеле Петронелла

1
@GabrielePetronella .length може не працювати правильно для спеціальних символів. Наприклад, Emoji або китайські символи, які займають 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передати тесту NSString, використовуючи str as NSString.

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

Щоб детально обговорити цю тему, див. Використання Swift з какао та Objective-C: Робота з типами даних какао


4
+1 для посилання на bridgeToObjectiveC()та пояснення зв’язку між NSString та Swift's String.
Кріс

2
ей цезар, я думаю, що BridgeToObjectiveC застарілий, якщо ви хочете оновити свою відповідь.
Dan Beaulieu

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

27

NSString: створює об'єкти, які знаходяться в купі і завжди передаються посиланням.

Рядок: тип значення, коли ми передаємо його, передається за значенням. як Struct і Enum, String собі Struct у Swift.

public struct String {
 // string implementation 
}

Але копія не створюється при переході. Він створює копію, коли ви вперше мутуєте її.

Рядок автоматично приєднується до Objective-C як NSString. Якщо у стандартній бібліотеці 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"

створити рядок із повторюваних значень:

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

У Swift 4 -> Струни - це колекція персонажів:

Тепер String здатний виконувати всі операції, які кожен може виконати для типу Collection.

Для отримання додаткової інформації зверніться до яблучних документів.


2
Ця відповідь повинна отримати більше голосів. Це принципова відмінність між String і NSString. Скрізь вони майже взаємозамінні
Макс

Чудова відповідь. значення відносно типу примітки, особливо.
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У книзі зазначено, що тип даних Свіфта є таким самим, як і розмір слова архітектури. NSIntegerтакож має той же розмір, що і розмір слова архітектури.
MaddTheSane

6

Оскільки об'єктивні типи C все ще динамічно розсилаються, вони, ймовірно, будуть повільнішими. Я б сказав, що вам найкраще користуватися натурними типами Swift, якщо вам не потрібно взаємодіяти з API-програмами target-c


Так, саме відповідь. І уникнення динамічно відправлених методів та змінного доступу до об'єктів - це все, що сприяє покращенню швидкості, про яку вони говорили на WWDC. У минулому всі турбувалися про продуктивність, використовуючи рядок C ++ та контейнери для отримання статичної диспетчеризації.
Лотар

5

Використовуйте рідні типи Swift, коли тільки можете. У випадку String, однак, у вас є "безшовний" доступ до всіх таких NSStringметодів:

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

4

Швидке оновлення 4

Рядок швидко переглядає редакцію 4. Тепер ви можете безпосередньо зателефонувати на рахунок, і він вважає кластери графеми 1 частиною, як емоджи. NSString не оновлюється і рахує його по-іншому.

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

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

1
NSStrings, ймовірно, не буде оновлено для роботи з кластерами графем: це зламає занадто багато додатків, які покладаються на стару поведінку. Також NSString.lengthрахує символи UTF16.
MaddTheSane

0

Рядок - це структура

// у модулі Swift

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

{

}

NSString - клас

// у модулі Foundation

відкритий клас NSString: NSObject

{

}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.