Swift - quels types utiliser? NSString ou chaîne

109

Avec l'introduction de Swift, j'ai essayé de comprendre la nouvelle langue

Je suis un développeur iOS et j'utiliserais des types tels que NSString, NSInteger, NSDictionarydans une application. J'ai remarqué que dans l'ebook "The Swift Programming Language" d'Apple, ils utilisent les types SwiftString, Int, Dictionary

J'ai remarqué que les types Swift n'ont pas (ou sont nommés différemment) certaines des fonctions des types Foundation. Par exemple NSStringa une lengthpropriété. Mais je n'ai pas pu en trouver un similaire pour le Swift String.

Je me demande, pour une application iOS, devrais-je toujours utiliser les types Foundation?

Alec
la source
3
Préférez String. Cependant, la Stringfonctionnalité est encore un peu limitée dans la version alpha, elle NSStringsera donc plus utilisée pour le moment. Nous espérons qu'ils corrigeront l'API jusqu'à GA.
Sulthan le
1
Vous pouvez également appeler countElements(str)pour répondre à cette partie spécifique de votre question.
Nate Cook
Mieux, vous pouvez appeler "foo".length" directly in Swift. An implicit cast to NSString` est ajouté pour vous par le compilateur!
Gabriele Petronella
1
@GabrielePetronella .length peut ne pas fonctionner correctement pour les caractères spéciaux. Tels que les caractères Emoji ou chinois qui occupent 2 ou 3 caractères unicode. countElements est la bonne méthode à utiliser.
Fogmeister

Réponses:

98

Vous devez utiliser les types natifs Swift dans la mesure du possible. Le langage est optimisé pour les utiliser et la plupart des fonctionnalités sont reliées entre les types natifs et les Foundationtypes.

Alors que Stringet NSStringsont pour la plupart interchangeables, c'est-à-dire que vous pouvez passer des Stringvariables dans des méthodes qui prennent des NSStringparamètres et vice versa, certaines méthodes ne semblent pas être automatiquement pontées à partir de ce moment. Voir cette réponse pour une discussion sur la façon d'obtenir la longueur d'une chaîne et cette réponse pour une discussion sur l'utilisation containsString()de la vérification des sous-chaînes. (Avertissement: je suis l'auteur de ces deux réponses)

Je n'ai pas complètement exploré d'autres types de données, mais je suppose qu'une version de ce qui a été indiqué ci-dessus sera également vraie pour Array/ NSArray, Dictionary/ NSDictionary, et les différents types de nombres dans Swift etNSNumber

Chaque fois que vous avez besoin d'utiliser l'un des types Foundation, vous pouvez soit les utiliser pour taper des variables / constantes explicitement, comme dans, var str: NSString = "An NSString"soit les utiliser bridgeToObjectiveC()sur une variable / constante existante de type Swift, comme str.bridgeToObjectiveC().lengthpar exemple. Vous pouvez également convertir un Stringen un NSStringen utilisant str as NSString.

Cependant, la nécessité pour ces techniques d'utiliser explicitement les types Foundation, ou du moins certains d'entre eux, peut être obsolète à l'avenir, car d'après ce qui est indiqué dans la référence du langage, le String/ NSStringbridge, par exemple, devrait être complètement transparent.

Pour une discussion approfondie sur le sujet, reportez-vous à Utilisation de Swift avec Cocoa et Objective-C: Utilisation des types de données Cocoa

Cezar
la source
4
+1 pour la référence bridgeToObjectiveC()et l'explication de la connexion entre NSString et Swift's String.
Chris
2
hey cezar, je pense que bridgeToObjectiveC est obsolète si vous souhaitez mettre à jour votre réponse.
Dan Beaulieu
Je remarque dans le manuel Swift 3 que les types Foundation sont passés par référence, tandis que les types natifs sont passés par valeur (ou quelque chose du genre que je ne comprends pas complètement à ce stade). Ce serait formidable si vous pouviez mettre à jour votre réponse en discutant des implications de cela.
Nigel B.Peck
27

NSString: crée des objets qui résident dans le tas et toujours passés par référence.

String: C'est un type valeur chaque fois que nous le transmettons, il est passé par valeur. comme Struct et Enum, String lui-même est un Struct dans Swift.

public struct String {
 // string implementation 
}

Mais la copie n'est pas créée lorsque vous passez. Il crée une copie lors de sa première mutation.

La chaîne est automatiquement pontée vers Objective-C en tant que NSString. Si la bibliothèque standard Swift n'en possède pas, vous devez importer le framework Foundation pour accéder aux méthodes définies par NSString.

Swift String est très puissant, il a pléthore de fonctions intégrées.

Initialisation sur chaîne:

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"

créer une chaîne à partir de valeurs répétées:

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

Dans Swift 4 -> Les chaînes sont une collection de caractères:

Maintenant, String est capable d'effectuer toutes les opérations que n'importe qui peut effectuer sur le type Collection.

Pour plus d'informations, veuillez consulter les documents Apple.

Sandy Rawat
la source
2
Cette réponse devrait obtenir plus de votes positifs. C'est la différence fondamentale entre String et NSString. Partout ailleurs, ils sont presque interchangeables
Max
Très bonne réponse. valeur vs type ref note en particulier.
spnkr
11

Votre meilleur pari est d'utiliser des types et des classes natifs Swift, comme certains autres l'ont noté que NSString a une traduction gratuite en String, cependant, ils ne sont pas les mêmes à 100%, prenez par exemple ce qui suit

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

nsstring.length
count(string)

vous devez utiliser la méthode count () pour compter les caractères dans la chaîne, notez également que nsstring.length renvoie 2, car il compte sa longueur en fonction de UTF16.

Similaire, OUI Le même, NON

Emanuel
la source
7

Stringet NSStringsont interchangeables, donc peu importe celui que vous utilisez. Vous pouvez toujours lancer entre les deux, en utilisant

let s = "hello" as NSString

ou même

let s: NSString  = "hello"

NSIntegerest juste un alias pour an intou a long(en fonction de l'architecture), donc j'utiliserais simplement Int.

NSDictionaryest une question différente, puisqu'il Dictionarys'agit d'une implémentation complètement distincte.

En général, je m'en tiendrais aux types swift chaque fois que possible et vous pouvez toujours convertir entre les deux au besoin, en utilisant la bridgeToObjectiveC()méthode fournie par les classes swift.

Gabriele Petronella
la source
Le Inttype de données de Swift est indiqué, dans le livre, comme étant le même que la taille des mots de l'architecture. NSIntegerest également de la même taille que la taille du mot de l'architecture.
MaddTheSane
6

Puisque les types objectifs C sont toujours distribués dynamiquement, ils seront probablement plus lents. Je dirais que vous êtes mieux servi en utilisant les types natifs Swift, sauf si vous avez besoin d'interagir avec les API objective-c

Jiaaro
la source
Oui c'est exactement la réponse. Et le fait d'éviter les méthodes distribuées dynamiquement et l'accès aux variables d'objet est tout ce qui rend ces améliorations de vitesse dont ils ont parlé à la WWDC. Dans le passé, tout le monde s'inquiétait des performances et utilisait des chaînes et des conteneurs C ++ pour obtenir une distribution statique.
Lothar
5

Utilisez les types natifs Swift chaque fois que vous le pouvez. Dans le cas de String, cependant, vous avez un accès "transparent" à toutes les NSStringméthodes comme celle-ci:

var greeting = "Hello!"
var len = (greeting as NSString).length
Nate Cook
la source
4

Mise à jour Swift 4

La chaîne reçoit des révisions dans swift 4. Vous pouvez maintenant appeler directement le compte dessus et considérer les grappes de graphèmes comme une seule pièce, comme un emoji. NSString n'est pas mis à jour et le compte d'une autre manière.

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

print(nsstring.length) // 11
print(string.count)    // 1
Fangming
la source
1
NSStrings ne seront probablement pas mis à jour pour traiter les clusters de graphèmes: cela briserait trop d'applications qui reposent sur l'ancien comportement. En outre, NSString.lengthcompte les caractères UTF16.
MaddTheSane
0

La chaîne est une structure

// dans le module Swift

public struct String

{

}

NSString est une classe

// dans le module Fondation

classe ouverte NSString: NSObject

{

}

kashish makkar
la source