Attributed Text คือกลไก iOS SDK ที่แสดงโดยคลาส NSAttributedString และ NSMutableAttributedString ซึ่งช่วยให้สามารถใช้รูปแบบหลายแบบกับส่วนต่างๆ ของสตริงข้อความเดียวกันได้ แตกต่างจาก NSString ทั่วไป Attributed String จัดเก็บไม่เพียงแค่อักขระ แต่ยังมีพจนานุกรมแอททริบิวต์สำหรับแต่ละช่วง: แบบอักษร, สี, ช่องว่างระหว่างบรรทัด, เงา, และการจัดแนว ตาม เอกสารนักพัฒนา Apple, Attributed String เป็นพื้นฐานสำหรับการแสดงข้อความที่มีรูปแบบใน UILabel, UITextView และ UITextField เป็นวิธีมาตรฐานในการกำหนดรูปแบบข้อความโดยไม่ต้องใช้ WebKit หรือไลบรารีของบุคคลที่สาม
ข้อสำคัญ
NSAttributedString คือคลาสของเฟรมเวิร์ก Foundation ที่แสดงสตริงที่มีชุดของแอททริบิวต์ที่มีชื่อซึ่งผูกกับช่วงของอักขระ แต่ละแอททริบิวต์คือคู่คีย์-ค่า: คีย์ถูกกำหนดโดยค่าคงที่ (NSFontAttributeName, NSForegroundColorAttributeName) และค่าคือวัตถุที่สอดคล้องกัน (UIFont, UIColor) แอททริบิวต์จะถูกนำไปใช้กับช่วงของอักขระผ่าน NSRange
คลาสนี้มีให้บริการบนทุกแพลตฟอร์ม Apple: iOS (2.0+), macOS, tvOS, watchOS NSAttributedString ไม่สามารถเปลี่ยนแปลงได้ — เมื่อสร้างแล้ว แอททริบิวต์ของมันจะถูกกำหนดตายตัว สำหรับการเปลี่ยนแปลงแบบไดนามิก จะใช้ NSMutableAttributedString ซึ่งสืบทอดจาก NSAttributedString และเพิ่มเมธอด setAttributes, addAttributes, addAttribute, removeAttribute
NSString คือสตริงอักขระที่เรียบง่ายโดยไม่มีข้อมูลรูปแบบ ข้อความใดๆ ที่ส่งไปยัง UILabel ผ่าน text จะแสดงด้วยแบบอักษร, สี และขนาดเดียว NSAttributedString ที่ส่งผ่าน attributedText ช่วยให้แต่ละอักขระมีชุดแอททริบิวต์ของตัวเอง UILabel, UITextView และ UITextField จะรู้จัก NSAttributedString โดยอัตโนมัติและแสดงข้อความตามแอททริบิวต์ของมัน
ภายใน, NSAttributedString จัดเก็บ NSString กับข้อความและอาร์เรย์ของช่วงแอททริบิวต์ แต่ละช่วงแสดงโดยโครงสร้าง NSRange และพจนานุกรมแอททริบิวต์ ระหว่างการแสดงผล, ระบบจะดำเนินการผ่านช่วงต่างๆ และใช้แอททริบิวต์ที่สอดคล้องกันกับแต่ละส่วน ประสิทธิภาพขึ้นอยู่กับจำนวนการสลับแอททริบิวต์ — การเปลี่ยนแปลงบ่อยในส่วนสั้นๆ จะเพิ่มเวลาในการแสดงผล
แอททริบิวต์ของ NSAttributedString คือค่าคงที่ที่กำหนดใน UIKit (iOS) และ AppKit (macOS) แต่ละตัวสอดคล้องกับแง่มุมเฉพาะของการจัดรูปแบบข้อความด้วยสายตา แอททริบิวต์ทั้งหมดเป็นสตริง NSAttributedString.Key และค่าของมันคือวัตถุของคลาสเฉพาะ แอททริบิวต์แบ่งออกเป็นระดับอักขระ (มีผลต่ออักขระ) และระดับย่อหน้า (มีผลต่อย่อหน้า)
แอททริบิวต์ระดับอักขระรวมถึง แบบอักษร (NSFontAttributeName), สีข้อความ (NSForegroundColorAttributeName), สีพื้นหลัง (NSBackgroundColorAttributeName), ขีดเส้นใต้ (NSUnderlineStyleAttributeName), ขีดฆ่า (NSStrikethroughStyleAttributeName), เงา (NSShadowAttributeName) แอททริบิวต์ระดับย่อหน้าถูกกำหนดโดย NSParagraphStyleAttributeName ซึ่งควบคุมการจัดแนว, การเยื้อง, ช่องว่างระหว่างบรรทัด และการแท็บ
NSLinkAttributeName สร้างลิงก์ที่คลิกได้ในข้อความ: ค่าคือ URL หรือสตริง UITextView จะจัดการลิงก์เหล่านี้โดยอัตโนมัติหากเปิดใช้งานการโต้ตอบ NSAttachmentAttributeName ช่วยให้สามารถฝัง NSTextAttachment — รูปภาพภายในข้อความที่แสดงผลเป็นองค์ประกอบอินไลน์ ซึ่งใช้ในการสร้างข้อความที่มีไอคอน, อีโมจิ หรือมุมมองที่กำหนดเองภายในสตริง
แต่ละแอททริบิวต์ของ NSAttributedString มีค่าที่ถูกกำหนดชนิดอย่างเข้มงวด มาดูแอททริบิวต์ที่ใช้กันทั่วไปที่สุดในการพัฒนา iOS แบบอักษรถูกกำหนดโดยวัตถุ UIFont, สีโดย UIColor, ช่องว่างระหว่างบรรทัดโดย NSMutableParagraphStyle ซึ่งช่วยให้สามารถกำหนดค่าการจัดแนว, การเยื้อง และช่องว่างในวัตถุเดียว
| คีย์แอททริบิวต์ | ชนิดค่า | วัตถุประสงค์ |
|---|---|---|
| NSFontAttributeName | UIFont | แบบอักษรข้อความ |
| NSForegroundColorAttributeName | UIColor | สีข้อความ |
| NSBackgroundColorAttributeName | UIColor | สีพื้นหลังด้านหลังข้อความ |
| NSUnderlineStyleAttributeName | NSNumber (Int) | รูปแบบขีดเส้นใต้ |
| NSParagraphStyleAttributeName | NSParagraphStyle | การตั้งค่าย่อหน้า |
| NSKernAttributeName | NSNumber (Float) | ช่องว่างระหว่างตัวอักษร (เคอร์นิง) |
NSParagraphStyle คือภาชนะสำหรับแอททริบิวต์ย่อหน้า: alignment, lineSpacing, paragraphSpacing, firstLineHeadIndent, lineBreakMode, minimumLineHeight และอื่นๆ สำหรับการเปลี่ยนแปลงพารามิเตอร์เหล่านี้, จะสร้าง NSMutableParagraphStyle, กำหนดคุณสมบัติที่ต้องการ, และส่งวัตถุเป็นค่าของแอททริบิวต์ NSParagraphStyleAttributeName นี่เป็นวิธีเดียวในการควบคุมช่องว่างระหว่างบรรทัดใน NSAttributedString
NSShadow ช่วยให้เพิ่มเงาให้กับข้อความ: พารามิเตอร์ shadowOffset, shadowBlurRadius, shadowColor กำหนดการเลื่อนตำแหน่ง, การเบลอ และสีของเงา แอททริบิวต์ขีดเส้นใต้และขีดฆ่ารับการผสมผสานรูปแบบ: NSUnderlineStyle.single, .double, .thick, .patternDash, .patternDot สำหรับการควบคุมความหนาและสีของเส้นอย่างแม่นยำ, จะใช้ NSUnderlineColorAttributeName และ NSStrikethroughColorAttributeName
การสร้าง NSAttributedString ใน Swift ทำได้โดยใช้ตัวเริ่มต้นกับข้อความและพจนานุกรมแอททริบิวต์, หรือโดย NSMutableAttributedString ด้วยการใช้รูปแบบทีละขั้นตอน วิธีการพื้นฐานคือการกำหนดพจนานุกรมแอททริบิวต์สำหรับข้อความทั้งหมด, จากนั้นเพิ่มหรือเปลี่ยนแอททริบิวต์สำหรับช่วงเฉพาะ
ตัวอย่างง่ายๆ — การกำหนด แบบอักษร, สี และการจัดแนวสำหรับสตริงทั้งหมด พจนานุกรมแอททริบิวต์จะถูกส่งไปยังตัวเริ่มต้น NSAttributedString คีย์ของพจนานุกรมคือค่าคงที่ NSAttributedString.Key, ค่าคือวัตถุ UIKit ที่สอดคล้องกัน นี่เป็นกรณีพื้นฐานเมื่อข้อความทั้งหมดถูกจัดรูปแบบอย่างสม่ำเสมอ
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.systemFont(ofSize: 16),
.foregroundColor: UIColor.darkGray,
.paragraphStyle: let style = NSMutableParagraphStyle()
style.alignment = .center
style.lineSpacing = 4
return style
]
let attributedString = NSAttributedString(
string: "Hello world",
attributes: attributes
)
label.attributedText = attributedString
ข้อความจะแสดงด้วย systemFont 16, สีเทาเข้ม, การจัดแนวกลาง และช่องว่างระหว่างบรรทัด 4pt วิธีการนี้สะดวกสำหรับหัวเรื่องและปุ่มแบบคงที่
NSMutableAttributedString ช่วยให้สามารถใช้รูปแบบที่แตกต่างกับส่วนต่างๆ ของข้อความ เมธอด addAttribute เพิ่มแอททริบิวต์เดียวในแต่ละช่วง, addAttributes เพิ่มพจนานุกรมแอททริบิวต์ เมธอด setAttributes จะแทนที่แอททริบิวต์ที่มีอยู่ทั้งหมดของช่วงด้วยแอททริบิวต์ใหม่ นี่เป็นเครื่องมือหลักสำหรับการสร้างข้อความที่มีการเน้น
let text = "Price: 1999 rubles"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.foregroundColor,
value: UIColor.green, range: NSRange(location: 6, length: 4))
attributed.addAttribute(.font,
value: UIFont.boldSystemFont(ofSize: 20), range: NSRange(location: 6, length: 4))
label.attributedText = attributed
คำว่า "1999" จะเป็นสีเขียวและตัวหนา, ส่วนที่เหลือของข้อความจะเป็นมาตรฐาน NSRange จะถูกคำนวณด้วยตนเอง — สิ่งสำคัญคือการนับความยาวเป็นอักขระอย่างถูกต้อง, โดยเฉพาะเมื่อทำงานกับอีโมจิและอักขระ Unicode แบบประกอบ
NSMutableAttributedString มีเมธอดสำหรับการเปลี่ยนแปลงข้อความและแอททริบิวต์แบบไดนามิก: append, insert, replace, delete, setAttributes, addAttribute, removeAttribute, enumerateAttributes ซึ่งช่วยให้สามารถสร้างข้อความจากแหล่งที่แตกต่างกัน, รวมรูปแบบ และตอบสนองต่อเหตุการณ์อินเทอร์เฟซ
แตกต่างจาก NSAttributedString ที่ไม่เปลี่ยนแปลงได้, เวอร์ชันที่เปลี่ยนแปลงได้รองรับการเปลี่ยนเนื้อหาโดยไม่ต้องสร้างวัตถุใหม่ ซึ่งสำคัญสำหรับโปรแกรมแก้ไขข้อความ, แชท และฟอร์มที่ผู้ใช้สามารถแก้ไขข้อความได้ในขณะที่รูปแบบต้องถูกคงไว้
ในแอปพลิเคชันส่งข้อความ, แต่ละข้อความประกอบด้วย ชื่อผู้ใช้ (ตัวหนา), ข้อความ (ปกติ), เวลา (สีเทา) NSMutableAttributedString ช่วยให้สามารถสร้างสตริงดังกล่าวได้ในครั้งเดียวโดยการเพิ่มส่วนต่างๆ ในลำดับที่ต้องการพร้อมกับแอททริบิวต์ที่สอดคล้องกัน
let result = NSMutableAttributedString()
let name = NSAttributedString(string: "Anna: ",
attributes: [.font: UIFont.boldSystemFont(ofSize: 15)])
let message = NSAttributedString(string: "Hello, how are you?",
attributes: [.font: UIFont.systemFont(ofSize: 15)])
let time = NSAttributedString(string: " 12:30",
attributes: [.foregroundColor: UIColor.gray])
result.append(name)
result.append(message)
result.append(time)
label.attributedText = result
ผลลัพธ์คือสตริงเดียวกับสามส่วนที่มีรูปแบบ Append จะ คำนวณ NSRange โดยอัตโนมัติ, ไม่จำเป็นต้องคำนวณตำแหน่งด้วยตนเอง วิธีการนี้สามารถขยายไปได้กับจำนวนส่วนย่อยเท่าใดก็ได้
เมธอด enumerateAttributes(in:options:using:) จะดำเนินการผ่านช่วงแอททริบิวต์ทั้งหมดในช่วงที่ระบุ ซึ่งมีประโยชน์สำหรับการวิเคราะห์รูปแบบ: ค้นหาลิงก์ทั้งหมด, เปลี่ยนสีของแอททริบิวต์เฉพาะ หรือส่งออกข้อความเป็น HTML ไปยังคลอเจอร์จะได้รับพจนานุกรมแอททริบิวต์และ NSRange ของส่วนปัจจุบัน
ส่วนประกอบ UI หลักทั้งหมดสำหรับการแสดงข้อความใน UIKit รองรับ NSAttributedString ผ่านคุณสมบัติ attributedText UILabel แสดงข้อความที่มีรูปแบบแบบคงที่, UITextView รองรับการแก้ไขและลิงก์, UITextField รับแอททริบิวต์แยกต่างหากสำหรับข้อความตัวแทนและข้อความที่ป้อน
UILabel เป็นส่วนประกอบที่เบาที่สุดสำหรับการแสดงข้อความที่มีรูปแบบ มันรองรับแอททริบิวต์ระดับอักขระทั้งหมด แต่ไม่จัดการลิงก์ที่คลิกได้โดยอัตโนมัติ (สำหรับสิ่งนั้นต้องใช้ UITextView) UILabel เหมาะสำหรับหัวเรื่อง, ป้ายกำกับ และข้อความที่มีรูปแบบสั้นๆ
UITextView จัดการ NSLinkAttributeName และแสดงลิงก์เป็นองค์ประกอบเชิงโต้ตอบ เพื่อเปิดใช้งานฟังก์ชันนี้, ให้ตั้งค่า isSelectable = true และ isEditable = false เมื่อแตะลิงก์, ตัวแทนจะได้รับการเรียก textView(_:shouldInteractWith:in:interaction:) UITextView ยังรองรับ NSTextAttachment สำหรับรูปภาพภายในข้อความ
let text = "Details on developer.apple.com"
let attributed = NSMutableAttributedString(string: text)
attributed.addAttribute(.link,
value: URL(string: "https://developer.apple.com")!,
range: NSRange(location: 0, length: text.count))
textView.attributedText = attributed
textView.isSelectable = true
textView.isEditable = false
หลังจากตั้งค่า isSelectable และ isEditable แล้ว, พื้นที่ข้อความจะทำงานเหมือนบล็อกข้อความคงที่, แต่ลิงก์จะยังคงทำงาน UITextViewDelegate จะควบคุมพฤติกรรมเมื่อแตะ
Core Text เป็นเฟรมเวิร์กระดับต่ำของ Apple สำหรับการแสดงผลข้อความที่ทำงานโดยตรงกับ NSAttributedString แตกต่างจาก UIKit, Core Text ไม่ใช้ NSAttributedString โดยตรงเป็นวัตถุแสดงผล — แต่จะแปลงมันเป็น CTFramesetter, จากนั้นเป็น CTFrame และแสดงผลในบริบท Core Graphics ซึ่งให้การควบคุมอย่างสมบูรณ์เหนือการจัดเรียงบรรทัดและกลิฟ
การใช้ Core Text เป็นสิ่งที่สมเหตุสมผลสำหรับเลย์เอาต์ข้อความที่กำหนดเอง: คอลัมน์, การห่อรูปภาพ, การหมุนข้อความ, การขึ้นบรรทัดใหม่ที่ไม่เป็นมาตรฐาน NSMutableParagraphStyle ของ Core Text มีแอททริบิวต์ที่ไม่มีใน UIKit: kCTParagraphStyleSpecifierMaximumLineSpacing, kCTParagraphStyleSpecifierLineBreakMode พร้อมโหมดเพิ่มเติม
NSAttributedString สามารถถ่ายโอนระหว่าง UIKit และ Core Text ได้อย่างราบรื่น เนื่องจากทั้งสองเฟรมเวิร์กทำงานกับชนิดเดียวกัน แอททริบิวต์ของ UIKit (NSFontAttributeName, NSForegroundColorAttributeName) จะถูกรู้จักโดย Core Text โดยอัตโนมัติ และในทางกลับกัน — แอททริบิวต์ของ Core Text (kCTFontAttributeName) จะถูกอ่านโดย UIKit ซึ่งช่วยให้สามารถใช้ UIKit สำหรับงานง่ายๆ และ Core Text สำหรับการแสดงผลแบบกำหนดเองบนวัตถุ NSAttributedString เดียวกัน
คำถามที่พบบ่อย
NSString จัดเก็บเฉพาะข้อความโดยไม่มีข้อมูลรูปแบบ NSAttributedString เพิ่มข้อความด้วยพจนานุกรมแอททริบิวต์สำหรับแต่ละช่วงของอักขระ เมื่อส่งไปยัง UILabel ผ่านคุณสมบัติ text, NSString จะแสดงเป็นข้อความล้วน เมื่อ NSAttributedString ถูกส่งผ่าน attributedText, แอททริบิวต์ทั้งหมดจะถูกนำไปใช้: แบบอักษร, สี และช่องว่างที่แตกต่างกันในสตริงเดียว
ใช้เมธอด addAttributes(_:range:) กับพจนานุกรมแอททริบิวต์: addAttributes([.font: font, .foregroundColor: color], range: range) สำหรับการเพิ่มหรือเปลี่ยนแอททริบิวต์เดียว, ใช้ addAttribute(_:value:range:) เมธอด setAttributes จะแทนที่แอททริบิวต์ที่มีอยู่ทั้งหมดในช่วงด้วยแอททริบิวต์ที่ให้มา
สร้าง NSMutableParagraphStyle, ตั้งค่าคุณสมบัติ lineSpacing, จากนั้นส่งมันเป็นค่าของแอททริบิวต์ NSParagraphStyleAttributeName สำหรับการควบคุมอย่างสมบูรณ์, minimumLineHeight, maximumLineHeight, paragraphSpacing, lineBreakMode และ alignment ก็มีให้บริการเช่นกัน ParagraphStyle เป็นวิธีเดียวในการควบคุมช่องว่างระหว่างบรรทัด
ใช่, SwiftUI รองรับ NSAttributedString ผ่าน Text(attributedString:) ใน iOS 15+ ในเวอร์ชันเก่ากว่า, ใช้ UIViewRepresentable กับ UILabel หรือ UITextView SwiftUI ยังมีชนิด AttributedString ของตัวเอง (SwiftUI, ไม่ใช่ Foundation) สำหรับการจัดรูปแบบแบบประกาศด้วยไวยากรณ์คล้าย Markdown
ใช้เมธอด boundingRect(with:options:context:), ซึ่งคืนค่า CGRect ที่จำเป็นสำหรับการแสดงสตริงด้วยแอททริบิวต์ที่กำหนด พารามิเตอร์ options: [.usesLineFragmentOrigin, .usesFontLeading] คำนึงถึงช่องว่างระหว่างบรรทัดและเมตริกของแบบอักษร สำหรับ UILabel ที่มีจำนวนบรรทัดจำกัด, ใช้ sizeThatFits
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม