Swift - sử dụng loại nào? NSString hoặc String


109

Với sự ra đời của Swift, tôi đã cố gắng tìm hiểu ngôn ngữ mới

Tôi là nhà phát triển iOS và sẽ sử dụng các loại như NSString, NSInteger, NSDictionary trong một ứng dụng. Tôi nhận thấy rằng trong ebook "Ngôn ngữ lập trình Swift" của Apple, họ sử dụng các loại SwiftString, Int, Dictionary

Tôi nhận thấy rằng các loại Swift không có (hoặc được đặt tên khác) một số chức năng mà các loại Foundation thực hiện. Ví dụ NSStringcó mộtlength tài sản. Nhưng tôi không thể tìm thấy một cái tương tự cho Swift String.

Tôi đang tự hỏi, đối với một ứng dụng iOS, tôi có nên sử dụng các loại Foundation không?


3
Thích hơn String. Tuy nhiên, Stringchức năng vẫn còn một chút hạn chế trong bản phát hành alpha, vì vậy NSStringsẽ được sử dụng nhiều hơn cho đến bây giờ. Chúng tôi hy vọng họ sẽ sửa API cho đến GA.
Sulthan

1
Ngoài ra, bạn có thể gọi countElements(str)để trả lời phần cụ thể của câu hỏi của bạn.
Nate Cook

Tốt hơn, bạn có thể gọi "foo".length" directly in Swift. An implicit cast to NSString` được trình biên dịch thêm cho bạn!
Gabriele Petronella

1
@GabrielePetronella .length có thể không hoạt động chính xác đối với các ký tự đặc biệt. Chẳng hạn như Biểu tượng cảm xúc hoặc các ký tự Trung Quốc chiếm 2 hoặc 3 ký tự unicode. countElements là phương pháp chính xác để sử dụng.
Fogmeister

Câu trả lời:


98

Bạn nên sử dụng các kiểu gốc Swift bất cứ khi nào có thể. Ngôn ngữ được tối ưu hóa để sử dụng chúng và hầu hết các chức năng được kết nối giữa các loại bản địa và các Foundationloại.

Trong khi StringNSStringhầu hết có thể hoán đổi cho nhau, tức là bạn có thể truyền Stringcác biến vào các phương thức nhận NSStringtham số và ngược lại, một số phương thức dường như không được bắc cầu tự động vào thời điểm này. Xem câu trả lời này để thảo luận về cách lấy độ dài của một chuỗi và câu trả lời này để thảo luận về cách sử dụngcontainsString() để kiểm tra các chuỗi con. (Tuyên bố từ chối trách nhiệm: Tôi là tác giả của cả hai câu trả lời này)

Tôi chưa khám phá đầy đủ các kiểu dữ liệu khác, nhưng tôi cho rằng một số phiên bản của những gì đã nêu ở trên cũng sẽ đúng với Array/ NSArray, Dictionary/NSDictionary và các loại số khác nhau trong Swift vàNSNumber

Bất cứ khi nào bạn cần sử dụng một trong các kiểu Foundation, bạn có thể sử dụng chúng để gõ biến / hằng một cách rõ ràng, như trong var str: NSString = "An NSString"hoặc sử dụng bridgeToObjectiveC()trên một biến / hằng hiện có của kiểu Swift, str.bridgeToObjectiveC().lengthchẳng hạn như trong ví dụ. Bạn cũng có thể truyền StringmộtNSString bằng cách sử dụng str as NSString.

Tuy nhiên, sự cần thiết đối với các kỹ thuật này để sử dụng rõ ràng các loại Nền tảng, hoặc ít nhất một số trong số chúng, có thể lỗi thời trong tương lai, vì từ những gì được nêu trong tham chiếu ngôn ngữ, String/NSString , ví dụ, bridge phải hoàn toàn liền mạch.

Để thảo luận kỹ lưỡng về chủ đề này, hãy tham khảo Sử dụng Swift với Ca cao và Mục tiêu-C: Làm việc với Các loại Dữ liệu Ca cao


4
+1 để tham khảo bridgeToObjectiveC()và giải thích kết nối giữa NSString và Swift's String.
Chris

2
hey cezar, tôi nghĩ bridgeToObjectiveC không được dùng nữa nếu bạn muốn cập nhật câu trả lời của mình.
Dan Beaulieu

Tôi nhận thấy trong sổ tay Swift 3 rằng các loại Foundation được chuyển bằng tham chiếu, trong khi các loại gốc được chuyển theo giá trị (hoặc một cái gì đó tương tự như vậy tôi không hiểu đầy đủ vào thời điểm này). Sẽ thật tuyệt nếu bạn có thể cập nhật câu trả lời của mình thảo luận về ý nghĩa của điều đó.
Nigel B. Peck

27

NSString: Tạo các đối tượng nằm trong heap và luôn được chuyển qua tham chiếu.

Chuỗi: Nó là một kiểu giá trị bất cứ khi nào chúng ta chuyển nó, nó được truyền theo giá trị. giống như Struct và Enum, String chính nó là một Struct trong Swift.

public struct String {
 // string implementation 
}

Nhưng bản sao không được tạo ra khi bạn vượt qua. Nó tạo ra bản sao khi bạn thay đổi nó lần đầu tiên.

Chuỗi được tự động bắc cầu tới Objective-C dưới dạng NSString. Nếu Thư viện chuẩn Swift không có, bạn cần nhập khuôn khổ Foundation để có quyền truy cập vào các phương thức do NSString xác định.

Swift String rất mạnh mẽ, nó có rất nhiều chức năng có sẵn.

Khởi tạo trên chuỗi:

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"

tạo Chuỗi từ các giá trị lặp lại:

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

Trong Swift 4 -> Chuỗi là tập hợp các ký tự:

Giờ đây, String có khả năng thực hiện tất cả các thao tác mà bất kỳ ai cũng có thể thực hiện trên loại Bộ sưu tập.

Để biết thêm thông tin, vui lòng tham khảo tài liệu của apple.


2
Câu trả lời này sẽ nhận được nhiều phiếu bầu hơn. Đây là sự khác biệt cơ bản giữa String và NSString. Ở mọi nơi khác, chúng gần như có thể hoán đổi cho nhau
Tối đa

Câu trả lời chính xác. đặc biệt là giá trị so với loại ref.
spnkr

11

Đặt cược tốt nhất của bạn là sử dụng các loại và lớp gốc Swift, vì một số người khác đã lưu ý rằng NSString có bản dịch miễn phí sang Chuỗi, tuy nhiên, chúng không giống nhau 100%, lấy ví dụ như sau

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

nsstring.length
count(string)

bạn cần sử dụng phương thức count () để đếm các ký tự trong chuỗi, cũng lưu ý rằng nsstring.length trả về 2, vì nó tính độ dài của nó dựa trên UTF16.

Tương tự, CÓ Giống nhau, KHÔNG


7

StringNSStringcó thể hoán đổi cho nhau, vì vậy bạn sử dụng cái nào không thực sự quan trọng. Bạn luôn có thể truyền giữa cả hai, sử dụng

let s = "hello" as NSString

hoặc thậm chí

let s: NSString  = "hello"

NSIntegerchỉ là một bí danh cho một inthoặc một long(tùy thuộc vào kiến ​​trúc), vì vậy tôi chỉ sử dụngInt .

NSDictionary là một vấn đề khác, vì Dictionary là một triển khai hoàn toàn riêng biệt.

Nói chung, tôi sẽ sử dụng các loại nhanh chóng bất cứ khi nào có thể di động và bạn luôn có thể chuyển đổi giữa hai loại này khi cần, sử dụng bridgeToObjectiveC()phương pháp được cung cấp bởi các lớp nhanh.


IntTrong cuốn sách, kiểu dữ liệu của Swift được nêu là giống với kích thước từ của kiến ​​trúc. NSIntegercũng có cùng kích thước với kích thước từ của kiến ​​trúc.
MaddTheSane

6

Vì các loại mục tiêu C vẫn được điều động động nên chúng có thể sẽ chậm hơn. Tôi muốn nói rằng bạn được phục vụ tốt nhất khi sử dụng các loại gốc Swift trừ khi bạn cần tương tác với các API target-c


Vâng, đó chính xác là câu trả lời. Và việc tránh các phương thức được điều động động và truy cập biến đối tượng là tất cả những gì tạo nên sự cải tiến tốc độ mà họ đã đề cập tại WWDC. Trước đây, mọi người lo lắng về hiệu suất đã sử dụng chuỗi C ++ và vùng chứa để nhận điều phối tĩnh.
Lothar

5

Sử dụng các kiểu gốc Swift bất cứ khi nào bạn có thể. Tuy nhiên, trong trường hợp Chuỗi, bạn có quyền truy cập "liền mạch" vào tất cả các NSStringphương thức như sau:

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

4

Bản cập nhật Swift 4

Chuỗi được sửa đổi nhanh chóng 4. Giờ đây, bạn có thể trực tiếp gọi số đếm trên đó và nó coi các cụm grapheme là 1 mảnh, giống như một biểu tượng cảm xúc. NSString không được cập nhật và đang đếm nó theo cách khác.

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

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

1
NSStrings có thể sẽ không được cập nhật để đối phó với các cụm grapheme: Nó sẽ phá vỡ quá nhiều ứng dụng dựa trên hành vi cũ. Ngoài ra, NSString.lengthđếm các ký tự UTF16.
MaddTheSane,

0

Chuỗi là một cấu trúc

// trong Mô-đun Swift

chuỗi cấu trúc công cộng

{

}

NSString là một lớp

// trong Mô-đun nền tảng

mở lớp NSString: NSObject

{

}

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.