Swift: ¿qué tipos usar? NSString o String

109

Con la introducción de Swift, he intentado entender el nuevo idioma

Soy un desarrollador de iOS y usaría tipos como NSString, NSInteger, NSDictionaryen una aplicación. Noté que en el libro electrónico "El lenguaje de programación Swift" de Apple, usan los tipos SwiftString, Int, Dictionary

He notado que los tipos Swift no tienen (o tienen un nombre diferente) algunas de las funciones que tienen los tipos Foundation. Por ejemplo NSStringtiene una lengthpropiedad. Pero no he podido encontrar uno similar para Swift String.

Me pregunto, para una aplicación iOS, ¿debería seguir usando los tipos Foundation?

Alec
fuente
3
Preferir String. Sin embargo, la Stringfuncionalidad todavía es un poco limitada en la versión alfa, por NSStringlo que se utilizará más por ahora. Esperamos que arreglen la API hasta GA.
Sulthan
1
Además, puede llamar countElements(str)para responder esa parte específica de su pregunta.
Nate Cook
Mejor, puedes llamar a "foo".length" directly in Swift. An implicit cast to NSString` ¡El compilador agrega para ti!
Gabriele Petronella
1
@GabrielePetronella .length puede no funcionar correctamente para caracteres especiales. Como Emoji o caracteres chinos que ocupan 2 o 3 caracteres Unicode. countElements es el método correcto a utilizar.
Fogmeister

Respuestas:

98

Debería utilizar los tipos nativos Swift siempre que sea posible. El lenguaje está optimizado para usarlos y la mayor parte de la funcionalidad está puenteada entre los tipos nativos y los Foundationtipos.

Si bien Stringy NSStringson en su mayoría intercambiables, es decir, puede pasar Stringvariables a métodos que toman NSStringparámetros y viceversa, algunos métodos parecen no estar puenteados automáticamente a partir de este momento. Vea esta respuesta para una discusión sobre cómo obtener la longitud de una cadena y esta respuesta para una discusión sobre el uso containsString()para verificar subcadenas. (Descargo de responsabilidad: soy el autor de ambas respuestas)

No he explorado completamente otros tipos de datos, pero supongo que alguna versión de lo que se indicó anteriormente también será válida para Array/ NSArray, Dictionary/ NSDictionaryy los diversos tipos de números en Swift yNSNumber

Siempre que necesite usar uno de los tipos Foundation, puede usarlos para escribir variables / constantes explícitamente, como en var str: NSString = "An NSString"o usar bridgeToObjectiveC()en una variable / constante existente de un tipo Swift, como str.bridgeToObjectiveC().lengthpor ejemplo. También puedes convertir un Stringa un NSStringusando str as NSString.

Sin embargo, la necesidad de que estas técnicas utilicen explícitamente los tipos Foundation, o al menos algunos de ellos, puede quedar obsoleta en el futuro, ya que a partir de lo que se indica en la referencia del lenguaje, el String/ NSStringbridge, por ejemplo, debería ser completamente transparente.

Para una discusión detallada sobre el tema, consulte Uso de Swift con Cocoa y Objective-C: Trabajar con tipos de datos de Cocoa

Cezar
fuente
4
+1 para la referencia bridgeToObjectiveC()y explicación de la conexión entre NSString y Swift's String.
Chris
2
hey cezar, creo que bridgeToObjectiveC está en desuso si desea actualizar su respuesta.
Dan Beaulieu
Noto en el manual de Swift 3 que los tipos de Foundation se pasan por referencia, mientras que los tipos nativos se pasan por valor (o algo así, no lo entiendo completamente en este momento). Sería genial si pudiera actualizar su respuesta discutiendo las implicaciones de eso.
Nigel B. Peck
27

NSString: crea objetos que residen en el montón y siempre se pasan por referencia.

Cadena: Es un tipo de valor cada vez que lo pasamos, se pasa por valor. como Struct y Enum, String en sí mismo es Struct en Swift.

public struct String {
 // string implementation 
}

Pero la copia no se crea cuando pasa. Crea una copia cuando lo mutas por primera vez.

La cadena se conecta automáticamente a Objective-C como NSString. Si la biblioteca estándar de Swift no lo tiene, necesita importar el marco Foundation para obtener acceso a los métodos definidos por NSString.

Swift String es muy poderoso y tiene una gran cantidad de funciones incorporadas.

Inicialización en cadena:

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"

crear String a partir de valores repetidos:

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

En Swift 4 -> Las cadenas son una colección de personajes:

Ahora String es capaz de realizar todas las operaciones que cualquiera puede realizar en el tipo de colección.

Para obtener más información, consulte los documentos de Apple.

Sandy Rawat
fuente
2
Esta respuesta debería obtener más votos a favor. Esta es la diferencia fundamental entre String y NSString. En cualquier otro lugar son casi intercambiables
Max
Gran respuesta. valor vs tipo de referencia nota especialmente.
spnkr
11

Su mejor opción es usar tipos y clases nativos de Swift, ya que algunos otros han notado que NSString tiene una traducción gratuita a String, sin embargo, no son iguales al 100%, tome por ejemplo lo siguiente

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

nsstring.length
count(string)

debe usar el método count () para contar los caracteres en una cadena, también tenga en cuenta que nsstring.length devuelve 2, porque cuenta su longitud según UTF16.

Similar, SI Lo mismo, NO

Emanuel
fuente
7

Stringy NSStringson intercambiables, por lo que realmente no importa cuál uses. Siempre puedes lanzar entre los dos, usando

let s = "hello" as NSString

o incluso

let s: NSString  = "hello"

NSIntegeres solo un alias para an into a long(dependiendo de la arquitectura), así que usaría Int.

NSDictionaryes un asunto diferente, ya que Dictionaryes una implementación completamente separada.

En general, me quedo con los tipos rápidos siempre que sea posible y siempre puede convertir entre los dos cuando lo necesite, utilizando el bridgeToObjectiveC()método proporcionado por las clases rápidas.

Gabriele Petronella
fuente
IntEn el libro se indica que el tipo de datos de Swift es el mismo que el tamaño de la palabra de la arquitectura. NSIntegertambién tiene el mismo tamaño que el tamaño de la palabra de la arquitectura.
MaddTheSane
6

Dado que los tipos C objetivo todavía se envían dinámicamente, probablemente serán más lentos. Yo diría que es mejor utilizar los tipos nativos de Swift a menos que necesite interactuar con las API de objetivo-c

Jiaaro
fuente
Sí, esa es exactamente la respuesta. Y evitar los métodos distribuidos dinámicamente y el acceso a variables de objeto es todo lo que hace que estas mejoras de velocidad de las que hablaron en la WWDC. En el pasado, todos los que estaban preocupados por el rendimiento usaban cadenas y contenedores C ++ para obtener un envío estático.
Lothar
5

Utilice los tipos nativos Swift siempre que pueda. En el caso de String, sin embargo, tiene acceso "transparente" a todos los NSStringmétodos como este:

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

Actualización de Swift 4

String recibe revisiones en Swift 4. Ahora puede llamar directamente a count y considerar los grupos de grafemas como 1 pieza, como un emoji. NSString no está actualizado y lo está contando de otra manera.

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

print(nsstring.length) // 11
print(string.count)    // 1
Colmillos
fuente
1
NSStrings probablemente no se actualizará para lidiar con grupos de grafemas: rompería demasiadas aplicaciones que se basan en el comportamiento anterior. Además, NSString.lengthcuenta los caracteres UTF16.
MaddTheSane
0

La cadena es una estructura

// en el módulo Swift

cadena de estructura pública

{

}

NSString es una clase

// en Foundation Module

clase abierta NSString: NSObject

{

}

kashish makkar
fuente