Swift - quais tipos usar? NSString ou String

109

Com a introdução do Swift, tenho tentado entender a nova linguagem

Sou um desenvolvedor iOS e usaria tipos como NSString, NSInteger, NSDictionaryem um aplicativo. Notei que no e-book "The Swift Programming Language" da Apple, eles usam os tipos SwiftString, Int, Dictionary

Percebi que os tipos Swift não têm (ou têm nomes diferentes) algumas das funções que os tipos Foundation têm. Por exemplo, NSStringtem uma lengthpropriedade. Mas não consegui encontrar um semelhante para o Swift String.

Estou pensando: para um aplicativo iOS, ainda devo usar os tipos Foundation?

Alec
fonte
3
Prefira String. No entanto, a Stringfuncionalidade ainda é um pouco limitada na versão alfa, portanto, NSStringserá mais usada por enquanto. Esperamos que eles consertem a API até GA.
Sulthan
1
Além disso, você pode ligar countElements(str)para responder a essa parte específica de sua pergunta.
Nate Cook
Melhor, você pode chamar "foo".length" directly in Swift. An implicit cast to NSString` é adicionado para você pelo compilador!
Gabriele Petronella
1
@GabrielePetronella .length pode não funcionar corretamente para caracteres especiais. Como caracteres emoji ou chineses que ocupam 2 ou 3 caracteres Unicode. countElements é o método correto a ser usado.
Fogmeister

Respostas:

98

Você deve usar os tipos nativos Swift sempre que possível. A linguagem é otimizada para usá-los e a maior parte da funcionalidade é interligada entre os tipos nativos e os Foundationtipos.

Embora Stringe NSStringsejam quase sempre intercambiáveis, ou seja, você pode passar Stringvariáveis ​​para métodos que usam NSStringparâmetros e vice-versa, alguns métodos parecem não ter uma ponte automática neste momento. Veja esta resposta para uma discussão sobre como obter o comprimento de uma String e esta resposta para uma discussão sobre containsString()como verificar se há substrings. (Isenção de responsabilidade: sou o autor de ambas as respostas)

Eu não explorei totalmente outros tipos de dados, mas presumo que alguma versão do que foi declarado acima também se aplica a Array/ NSArray, Dictionary/ NSDictionarye os vários tipos de número em Swift eNSNumber

Sempre que você precisar usar um dos tipos Foundation, você pode usá-los para digitar variáveis ​​/ constantes explicitamente, como em var str: NSString = "An NSString"ou usar bridgeToObjectiveC()em uma variável / constante existente de um tipo Swift, como em str.bridgeToObjectiveC().lengthpor exemplo. Você também pode lançar um Stringpara um NSStringusando str as NSString.

No entanto, a necessidade dessas técnicas de usarem explicitamente os tipos Foundation, ou pelo menos alguns deles, pode se tornar obsoleta no futuro, uma vez que, pelo que está declarado na referência da linguagem, a ponte String/ NSString, por exemplo, deve ser completamente transparente.

Para uma discussão completa sobre o assunto, consulte Using Swift with Cocoa e Objective-C: Working with Cocoa Data Types

Cezar
fonte
4
+1 para a referência bridgeToObjectiveC()e explicação da conexão entre NSString e Swift's String.
Chris de
2
Ei cezar, acho que bridgeToObjectiveC foi descontinuado se você se importar em atualizar sua resposta.
Dan Beaulieu
Percebo no manual do Swift 3 que os tipos Foundation são passados ​​por referência, enquanto os tipos nativos são passados ​​por valor (ou algo parecido que não entendo totalmente neste ponto). Seria ótimo se você pudesse atualizar sua resposta discutindo as implicações disso.
Nigel B. Peck de
27

NSString: cria objetos que residem em heap e sempre são passados ​​por referência.

String: É um tipo de valor sempre que o passamos, é passado por valor. como Struct e Enum, o próprio String é um Struct em Swift.

public struct String {
 // string implementation 
}

Mas a cópia não é criada quando você passa. Ele cria uma cópia quando você a altera pela primeira vez.

String é automaticamente ligada a Objective-C como NSString. Se a Biblioteca Padrão Swift não tiver, você precisa importar a estrutura Foundation para obter acesso aos métodos definidos por NSString.

Swift String é muito poderoso, tem uma infinidade de funções embutidas.

Inicialização na 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"

criar String a partir de valores repetidos:

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

Em Swift 4 -> Strings São Coleção de Personagens:

Agora String é capaz de realizar todas as operações que qualquer um pode realizar no tipo Collection.

Para obter mais informações, consulte os documentos da apple.

Sandy Rawat
fonte
2
Esta resposta deve obter mais votos positivos. Esta é a diferença fundamental entre String e NSString. Em todos os outros lugares, eles são quase intercambiáveis
Máx.
Ótima resposta. valor vs ref digite nota especialmente.
spnkr
11

Sua melhor aposta é usar classes e tipos nativos Swift, como alguns outros notaram que NSString tem tradução gratuita para String, no entanto, eles não são 100% iguais, tome por exemplo o seguinte

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

nsstring.length
count(string)

você precisa usar o método count () para contar os caracteres em string, observe também que nsstring.length retorna 2, porque conta seu comprimento com base em UTF16.

Semelhante, SIM O mesmo, NÃO

Emanuel
fonte
7

Stringe NSStringsão intercambiáveis, então realmente não importa qual você usar. Você sempre pode lançar entre os dois, usando

let s = "hello" as NSString

ou mesmo

let s: NSString  = "hello"

NSIntegeré apenas um alias para um intou um long(dependendo da arquitetura), então eu apenas usaria Int.

NSDictionaryé um assunto diferente, pois Dictionaryé uma implementação completamente separada.

Em geral, preferiria os tipos swift sempre que possível e você sempre pode converter entre os dois quando necessário, usando o bridgeToObjectiveC()método fornecido pelas classes swift.

Gabriele Petronella
fonte
O Inttipo de dados do Swift é declarado, no livro, como sendo o mesmo que o tamanho da palavra da arquitetura. NSIntegertambém é do mesmo tamanho que o tamanho da palavra da arquitetura.
MaddTheSane
6

Como os tipos C objetivos ainda são despachados dinamicamente, provavelmente serão mais lentos. Eu diria que você é melhor servido usando os tipos nativos Swift, a menos que precise interagir com APIs objetivas-c

Jiaaro
fonte
Sim, essa é exatamente a resposta. E evitar métodos despachados dinamicamente e acesso a variáveis ​​de objeto é tudo o que torna essas melhorias de velocidade de que falaram na WWDC. No passado, todos se preocupavam com o desempenho e usavam strings e contêineres C ++ para obter despacho estático.
Lothar
5

Use os tipos nativos Swift sempre que puder. No caso de String, entretanto, você tem acesso "contínuo" a todos os NSStringmétodos como este:

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

Atualização do Swift 4

String obtém revisões no swift 4. Agora você pode chamar diretamente a contagem e considerar os agrupamentos de grafemas como uma peça, como um emoji. NSString não é atualizado e está contando de outra forma.

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

print(nsstring.length) // 11
print(string.count)    // 1
Fangming
fonte
1
NSStrings provavelmente não será atualizado para lidar com clusters de grafemas: isso interromperia muitos aplicativos que dependem do comportamento antigo. Além disso, NSString.lengthconta os caracteres UTF16.
MaddTheSane
0

String é uma estrutura

// no módulo Swift

public struct String

{

}

NSString é uma classe

// no módulo base

abrir classe NSString: NSObject

{

}

Kashish Makkar
fonte