Swift: quali tipi utilizzare? NSString o String


109

Con l'introduzione di Swift ho cercato di capire la nuova lingua

Sono uno sviluppatore iOS e utilizzerei tipi come NSString, NSInteger, NSDictionaryin un'applicazione. Ho notato che nell'ebook "The Swift Programming Language" di Apple, usano i tipi SwiftString, Int, Dictionary

Ho notato che i tipi Swift non hanno (o sono denominati diversamente) alcune delle funzioni svolte dai tipi Foundation. Ad esempio NSStringha una lengthproprietà. Ma non sono riuscito a trovarne uno simile per Swift String.

Mi chiedo, per un'applicazione iOS dovrei ancora usare i tipi Foundation?


3
Prefer String. Tuttavia, la Stringfunzionalità è ancora un po 'limitata nella versione alpha, quindi NSStringsarà più utilizzata per ora. Ci auguriamo che risolveranno l'API fino a GA.
Sulthan

1
Inoltre, puoi chiamare countElements(str), per rispondere a quella parte specifica della tua domanda.
Nate Cook

Meglio, puoi chiamare "foo".length" directly in Swift. An implicit cast to NSString` aggiunto per te dal compilatore!
Gabriele Petronella

1
@GabrielePetronella .length potrebbe non funzionare correttamente per i caratteri speciali. Come emoji o caratteri cinesi che occupano 2 o 3 caratteri Unicode. countElements è il metodo corretto da usare.
Fogmeister

Risposte:


98

Dovresti usare i tipi nativi Swift quando possibile. Il linguaggio è ottimizzato per utilizzarli e la maggior parte delle funzionalità è collegata ai tipi nativi e ai Foundationtipi.

Sebbene Stringe NSStringsiano per lo più intercambiabili, ovvero è possibile passare Stringvariabili a metodi che accettano NSStringparametri e viceversa, alcuni metodi sembrano non essere automaticamente collegati a ponte a partire da questo momento. Vedi questa risposta per una discussione su come ottenere la lunghezza di una stringa e questa risposta per una discussione sull'uso containsString()per verificare la presenza di sottostringhe. (Disclaimer: sono l'autore di entrambe queste risposte)

Non ho esplorato completamente altri tipi di dati, ma presumo che alcune versioni di ciò che è stato affermato sopra valgono anche per Array/ NSArray, Dictionary/ NSDictionarye per i vari tipi di numeri in Swift eNSNumber

Ogni volta che è necessario utilizzare uno dei tipi Foundation, è possibile utilizzarli per digitare variabili / costanti in modo esplicito, come in var str: NSString = "An NSString"o utilizzare bridgeToObjectiveC()su una variabile / costante esistente di un tipo Swift, come str.bridgeToObjectiveC().lengthad esempio. Puoi anche trasmettere a StringaNSString utilizzando str as NSString.

Tuttavia, la necessità per queste tecniche di utilizzare esplicitamente i tipi Foundation, o almeno alcuni di essi, potrebbe essere obsoleta in futuro, poiché da quanto affermato nel linguaggio di riferimento, il String/NSString bridge, ad esempio, dovrebbe essere completamente trasparente.

Per una discussione approfondita sull'argomento, fare riferimento a Utilizzo di Swift con Cocoa e Objective-C: Lavorare con i tipi di dati Cocoa


4
+1 per il riferimento bridgeToObjectiveC()e la spiegazione della connessione tra NSString e Swift's String.
Chris

2
hey cezar, penso che bridgeToObjectiveC sia deprecato se ti interessa aggiornare la tua risposta.
Dan Beaulieu,

Noto nel manuale di Swift 3 che i tipi Foundation vengono passati per riferimento, mentre i tipi nativi vengono passati per valore (o qualcosa del genere non capisco completamente a questo punto). Sarebbe bello se potessi aggiornare la tua risposta discutendone le implicazioni.
Nigel B. Peck

27

NSString: crea oggetti che risiedono nell'heap e sempre passati per riferimento.

String: è un tipo di valore ogni volta che lo si passa, viene passato per valore. come Struct e Enum, String stesso è uno Struct in Swift.

public struct String {
 // string implementation 
}

Ma la copia non viene creata quando passi. Crea una copia quando la muti per la prima volta.

La stringa viene automaticamente collegata a Objective-C come NSString. Se la Swift Standard Library non ha, è necessario importare il framework Foundation per accedere ai metodi definiti da NSString.

Swift String è molto potente e ha una miriade di funzioni integrate.

Inizializzazione su stringa:

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"

crea String da valori ripetuti:

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

In Swift 4 -> Le stringhe sono una raccolta di personaggi:

Ora String è in grado di eseguire tutte le operazioni che chiunque può eseguire sul tipo di raccolta.

Per ulteriori informazioni, fare riferimento ai documenti Apple.


2
Questa risposta dovrebbe ottenere più voti positivi. Questa è la differenza fondamentale tra String e NSString. Ovunque sono quasi intercambiabili
Max

Bella risposta. valore vs nota di tipo ref in particolare.
spnkr

11

La soluzione migliore è utilizzare tipi e classi nativi Swift, poiché alcuni altri hanno notato che NSString ha una traduzione gratuita in String, tuttavia, non sono uguali al 100%, prendi ad esempio quanto segue

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

nsstring.length
count(string)

è necessario utilizzare il metodo count () per contare i caratteri in stringa, inoltre si noti che nsstring.length restituisce 2, perché conta la sua lunghezza in base a UTF16.

Simile, SÌ Lo stesso, NO


7

Stringe NSStringsono intercambiabili, quindi non importa quale usi. Puoi sempre lanciare tra i due, usando

let s = "hello" as NSString

o anche

let s: NSString  = "hello"

NSIntegerè solo un alias per an into a long(a seconda dell'architettura), quindi userei solo Int.

NSDictionaryè una questione diversa, poiché Dictionaryè un'implementazione completamente separata.

In generale, mi atterrei ai tipi swift ogni volta che è possibile e puoi sempre convertire tra i due quando necessario, utilizzando il bridgeToObjectiveC()metodo fornito dalle classi swift.


Il Inttipo di dati di Swift è indicato, nel libro, per essere uguale alla dimensione della parola dell'architettura. NSIntegerè anche la stessa dimensione della dimensione della parola dell'architettura.
MaddTheSane

6

Poiché i tipi C dell'obiettivo vengono ancora inviati dinamicamente, probabilmente saranno più lenti. Direi che è meglio utilizzare i tipi nativi Swift a meno che non sia necessario interagire con le API Objective-c


Sì, questa è esattamente la risposta. E l'eliminazione dei metodi inviati dinamicamente e l'accesso alle variabili oggetto è tutto ciò che rende questi miglioramenti di velocità di cui hanno parlato al WWDC. In passato tutti preoccupati per le prestazioni utilizzavano stringhe e contenitori C ++ per ottenere l'invio statico.
Lothar

5

Usa i tipi nativi Swift ogni volta che puoi. Nel caso di String, tuttavia, hai accesso "senza interruzioni" a tutti i NSStringmetodi come questo:

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

4

Aggiornamento Swift 4

String riceve le revisioni in swift 4. Ora puoi chiamare direttamente count su di esso e considera i grapheme cluster come 1 pezzo, come un'emoji. NSString non è aggiornato e lo sta contando in un altro modo.

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

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

1
NSStringProbabilmente non verrà aggiornato per gestire i cluster di grafema: romperebbe troppe app che si basano sul vecchio comportamento. Inoltre, NSString.lengthconta i caratteri UTF16.
MaddTheSane

0

String è una struttura

// in Swift Module

public struct String

{

}

NSString è una classe

// nel modulo Foundation

classe aperta NSString: NSObject

{

}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.