Swift - ประเภทใดที่จะใช้? NSString หรือ String


109

ด้วยการแนะนำ Swift ฉันพยายามที่จะเปลี่ยนภาษาใหม่

ฉันเป็นนักพัฒนา iOS และจะใช้ประเภทต่างๆเช่นNSString, NSInteger, NSDictionaryในแอปพลิเคชัน ฉันสังเกตเห็นว่าใน ebook "The Swift Programming Language" ของ Apple พวกเขาใช้ประเภท SwiftString, Int, Dictionary

ฉันสังเกตเห็นว่าประเภท Swift ไม่มี (หรือมีชื่อต่างกัน) ฟังก์ชันบางอย่างที่ประเภท Foundation ทำ ตัวอย่างเช่นNSStringมีlengthคุณสมบัติ แต่ฉันไม่สามารถหา Swift ที่คล้ายกันStringได้

ฉันสงสัยว่าสำหรับแอปพลิเคชัน iOS ฉันควรใช้ประเภท Foundation หรือไม่?


3
Stringชอบ อย่างไรก็ตามStringฟังก์ชันการทำงานยังมีข้อ จำกัด เล็กน้อยในรุ่นอัลฟ่าดังนั้นNSStringจะมีการใช้งานมากขึ้น เราหวังว่าพวกเขาจะแก้ไข API จนถึง GA
Sulthan

1
นอกจากนี้คุณสามารถโทรcountElements(str)เพื่อตอบคำถามเฉพาะส่วนนั้นได้
Nate Cook

ดีกว่าคุณสามารถเรียก"foo".length" directly in Swift. An implicit cast to NSString` ได้โดยคอมไพเลอร์!
Gabriele Petronella

1
@GabrielePetronella .length อาจทำงานไม่ถูกต้องสำหรับอักขระพิเศษ เช่น Emoji หรืออักษรจีนที่ใช้อักขระ Unicode 2 หรือ 3 ตัว countElements เป็นวิธีการที่ถูกต้องในการใช้
Fogmeister

คำตอบ:


98

คุณควรใช้ Swift แบบเนทีฟทุกครั้งที่ทำได้ ภาษาได้รับการปรับให้เหมาะกับการใช้งานและฟังก์ชันส่วนใหญ่จะเชื่อมโยงระหว่างประเภทดั้งเดิมและFoundationประเภทต่างๆ

ในขณะที่StringและNSStringส่วนใหญ่ใช้แทนกันได้กล่าวคือคุณสามารถส่งผ่านStringตัวแปรไปยังวิธีการที่ใช้NSStringพารามิเตอร์และในทางกลับกันบางวิธีดูเหมือนจะไม่เชื่อมโยงโดยอัตโนมัติในขณะนี้ ดูคำตอบนี้สำหรับการอภิปรายเกี่ยวกับวิธีรับความยาวของสตริงและคำตอบนี้สำหรับการอภิปรายเกี่ยวกับการใช้containsString()เพื่อตรวจสอบสตริงย่อย (ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียนสำหรับคำตอบทั้งสองนี้)

ฉันยังไม่ได้สำรวจประเภทข้อมูลอื่น ๆ อย่างสมบูรณ์ แต่ฉันคิดว่าบางเวอร์ชันของสิ่งที่ระบุไว้ข้างต้นจะถือเป็นจริงสำหรับArray/ NSArray, Dictionary/ NSDictionaryและประเภทตัวเลขต่างๆใน Swift และNSNumber

เมื่อใดก็ตามที่คุณจำเป็นต้องใช้ประเภทพื้นฐานประเภทใดประเภทหนึ่งคุณสามารถใช้เพื่อพิมพ์ตัวแปร / ค่าคงที่อย่างชัดเจนเช่นเดียวกับในvar str: NSString = "An NSString"หรือใช้bridgeToObjectiveC()กับตัวแปร / ค่าคงที่ที่มีอยู่ของประเภท Swift ดังstr.bridgeToObjectiveC().lengthตัวอย่างเช่น คุณยังสามารถส่งStringต่อNSStringโดยใช้str as NSStringไฟล์.

อย่างไรก็ตามความจำเป็นสำหรับเทคนิคเหล่านี้ในการใช้ประเภท Foundation อย่างชัดเจนหรืออย่างน้อยก็บางอย่างอาจล้าสมัยในอนาคตเนื่องจากจากสิ่งที่ระบุไว้ในการอ้างอิงภาษาตัวอย่างเช่นString/ NSStringbridge ควรจะราบรื่นอย่างสมบูรณ์

สำหรับการสนทนาอย่างละเอียดในหัวข้อนี้โปรดดูการใช้ Swift กับ Cocoa และ Objective-C: การทำงานกับประเภทข้อมูลโกโก้


4
+1 สำหรับการอ้างอิงbridgeToObjectiveC()และอธิบายการเชื่อมต่อระหว่าง NSString และ Swift's String
คริส

2
เฮ้เซซาร์ฉันคิดว่า bridgeToObjectiveC เลิกใช้งานแล้วหากคุณต้องการอัปเดตคำตอบของคุณ
Dan Beaulieu

ฉันสังเกตเห็นในคู่มือ Swift 3 ว่าประเภทพื้นฐานถูกส่งผ่านโดยการอ้างอิงในขณะที่ประเภทเนทีฟจะถูกส่งผ่านด้วยค่า (หรือบางอย่างที่ฉันไม่เข้าใจในตอนนี้) จะเป็นการดีมากหากคุณสามารถอัปเดตคำตอบของคุณโดยพูดถึงผลกระทบของสิ่งนั้น
Nigel B. Peck

27

NSString: สร้างวัตถุที่อยู่ในฮีปและส่งผ่านโดยการอ้างอิงเสมอ

String: เป็นประเภทค่าเมื่อใดก็ตามที่เราส่งผ่านค่าจะถูกส่งผ่านด้วยค่า เช่นเดียวกับ Struct และ Enum สตริงเป็นโครงสร้างใน Swift

public struct String {
 // string implementation 
}

แต่จะไม่มีการสร้างสำเนาเมื่อคุณผ่าน สร้างสำเนาเมื่อคุณกลายพันธุ์ครั้งแรก

String เชื่อมโยงกับ Objective-C เป็น NSString โดยอัตโนมัติ หากไม่มี Swift Standard Library คุณต้องนำเข้าเฟรมเวิร์ก Foundation เพื่อเข้าถึงวิธีการที่กำหนดโดย NSString

Swift 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"

สร้างสตริงจากค่าการทำซ้ำ:

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

ใน Swift 4 -> สตริงเป็นชุดของตัวละคร:

ตอนนี้ String สามารถดำเนินการทั้งหมดซึ่งทุกคนสามารถดำเนินการในประเภท Collection ได้

สำหรับข้อมูลเพิ่มเติมโปรดดูเอกสารของ apple


2
คำตอบนี้ควรได้รับการโหวตมากขึ้น นี่คือความแตกต่างพื้นฐานระหว่าง String และ NSString ที่อื่นแทบจะใช้แทนกันได้
สูงสุด

คำตอบที่ดี ค่าเทียบกับหมายเหตุประเภทอ้างอิงโดยเฉพาะ
spnkr

11

ทางออกที่ดีที่สุดของคุณคือใช้ประเภทและคลาสของ Swift แบบเนทีฟเนื่องจากคนอื่น ๆ บางคนตั้งข้อสังเกตว่า NSString มีการแปลฟรีเป็น String แต่ไม่เหมือนกัน 100% ตัวอย่างต่อไปนี้

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

nsstring.length
count(string)

คุณต้องใช้ method count () เพื่อนับอักขระในสตริงโปรดทราบว่า nsstring.length ส่งกลับ 2 เนื่องจากจะนับความยาวตาม UTF16

คล้ายกันใช่เหมือนกันไม่มี


7

StringและNSStringใช้แทนกันได้ดังนั้นจึงไม่สำคัญว่าคุณจะใช้อันไหน คุณสามารถโยนระหว่างทั้งสองโดยใช้

let s = "hello" as NSString

หรือแม้กระทั่ง

let s: NSString  = "hello"

NSIntegerเป็นเพียงนามแฝงสำหรับintหรือlong(ขึ้นอยู่กับสถาปัตยกรรม) Intดังนั้นฉันต้องการใช้เพียง

NSDictionaryเป็นเรื่องที่แตกต่างกันเนื่องจากDictionaryเป็นการใช้งานที่แยกจากกันโดยสิ้นเชิง

โดยทั่วไปฉันจะยึดติดกับประเภทที่รวดเร็วเมื่อใดก็ตามที่เป็นไปได้และคุณสามารถแปลงระหว่างสองสิ่งที่ต้องการได้ตลอดเวลาโดยใช้bridgeToObjectiveC()วิธีการที่จัดเตรียมโดยคลาสที่รวดเร็ว


Intประเภทข้อมูลของ Swift ระบุไว้ในหนังสือให้เหมือนกับขนาดคำของสถาปัตยกรรม NSIntegerยังมีขนาดเท่ากับขนาดคำของสถาปัตยกรรม
MaddTheSane

6

เนื่องจากประเภท C วัตถุประสงค์ยังคงถูกส่งแบบไดนามิกจึงอาจจะช้าลง ฉันจะบอกว่าคุณได้รับบริการที่ดีที่สุดโดยใช้ประเภทเนทีฟ Swift เว้นแต่คุณจะต้องโต้ตอบกับ objective-c APIs


ใช่นั่นคือคำตอบ และการหลีกเลี่ยงวิธีการส่งแบบไดนามิกและการเข้าถึงตัวแปรออบเจ็กต์เป็นสิ่งที่ทำให้การปรับปรุงความเร็วนี้เป็นสิ่งที่พวกเขาพูดถึงใน WWDC ในอดีตทุกคนกังวลเกี่ยวกับประสิทธิภาพการใช้งานสตริงและคอนเทนเนอร์ C ++ เพื่อรับการจัดส่งแบบคงที่
Lothar

5

ใช้ Swift แบบเนทีฟทุกครั้งที่ทำได้ อย่างไรก็ตามในกรณีของ String คุณสามารถเข้าถึงNSStringวิธีการทั้งหมดนี้ได้อย่าง "ไร้รอยต่อ" :

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

4

อัปเดต Swift 4

String ได้รับการแก้ไขใน swift 4 ตอนนี้คุณสามารถเรียกนับได้โดยตรงและจะพิจารณากลุ่ม grapheme เป็น 1 ชิ้นเช่นอิโมจิ NSString ไม่ได้รับการอัปเดตและกำลังนับด้วยวิธีอื่น

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

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

1
NSStringอาจจะไม่ได้รับการอัปเดตเพื่อจัดการกับคลัสเตอร์ grapheme: มันจะทำลายแอพจำนวนมากเกินไปที่อาศัยพฤติกรรมเก่า ๆ นอกจากนี้ให้NSString.lengthนับอักขระ UTF16
MaddTheSane

0

String เป็นโครงสร้าง

// ในโมดูล Swift

สตริงโครงสร้างสาธารณะ

{

}

NSString เป็นคลาส

// ในโมดูลพื้นฐาน

NSString คลาสเปิด: NSObject

{

}

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.