2 คะแนน โดย GN⁺ 2024-03-06 | 1 ความคิดเห็น | แชร์ทาง WhatsApp

โครงสร้างภายในเชิงเทคนิคของโปรแกรมแก้ไขข้อความของ Apple

  • อธิบายรายละเอียดการทำงานของ Paper ในฐานะโปรแกรมแก้ไขข้อความที่อิงกับ TextView
  • ปัจจุบัน Paper สร้างอยู่บนเฟรมเวิร์ก TextKit 1 และใน TextKit 2 ก็ยังคงแนวคิด การทำ abstraction และหลักการเดิมไว้ หรือเปลี่ยนเป็น API ที่ดีกว่า

มุมมองข้อความ

  • คลาส TextView คือแกนหลักของงานแก้ไขข้อความในโปรแกรมแก้ไขข้อความของ Apple
  • แม้ NSTextView และ UITextView จะมีความแตกต่างกัน แต่ API คล้ายกัน จึงมองเป็นคลาส TextView เดียวกัน
  • TextView เป็นคอมโพเนนต์ขนาดใหญ่ที่มีความซับซ้อนเพิ่มขึ้นในทุกการออกเวอร์ชันของ OS
  • Apple แยก TextView ออกเป็นหลายชั้นเพื่อมอบประสบการณ์การแก้ไขข้อความ

NSTextStorage

  • เก็บสตริงข้อความดิบ
  • เก็บแอตทริบิวต์ที่กำหนดให้กับช่วงข้อความ (คู่สตริง-ค่า)
  • ส่งอีเวนต์เมื่อมีการเปลี่ยนแปลงข้อความและแอตทริบิวต์

NSTextContainer

  • กำหนดรูปร่างและขนาดของพื้นที่ที่ใช้วาง glyph ของข้อความ

NSLayoutManager

  • ดูช่วงแอตทริบิวต์ที่ใช้กับสตริงข้อความใน NSTextStorage แล้วคำนวณขนาดและระยะห่างของ glyph
  • จัดเลย์เอาต์ glyph และคำนวณว่าบรรทัดแต่ละบรรทัดของข้อความเริ่มและจบตรงไหน รวมถึงความสูงของข้อความทั้งหมด

TextView

  • วาดเลย์เอาต์ glyph ที่สร้างโดย NSLayoutManager
  • ซิงก์ความสูงของวิวให้ตรงกับความสูงปัจจุบันของข้อความที่จัดเลย์เอาต์แล้ว
  • จัดการการเลือกข้อความ แคเร็ต และแอตทริบิวต์การพิมพ์ที่ใช้กับข้อความที่เพิ่งแทรก

ScrollView

  • แสดงส่วนที่มองเห็นได้ของ TextView
  • จัดการการเลื่อน แถบเลื่อน และการซูม

แอตทริบิวต์

  • NSAttributedString คือรากฐานของการแก้ไข rich text ในเฟรมเวิร์กของ Apple
  • ประกอบด้วยสตริงข้อความธรรมดาและแอตทริบิวต์ (คู่สตริง-ค่า) ที่แนบกับช่วงข้อความ
  • แอตทริบิวต์มักใช้เพื่อการจัดสไตล์เป็นหลัก แต่ก็ไม่ได้มีข้อจำกัดในการกำหนดคู่สตริง-ค่าแบบกำหนดเอง

การจัดสไตล์

  • การจัดสไตล์หมายถึงการใช้แอตทริบิวต์พิเศษที่เฟรมเวิร์กกำหนดไว้กับช่วงข้อความ
  • Paper ใช้เมตาแอตทริบิวต์เพื่อระบุโครงสร้างข้อความก่อน แล้วจึงนำการจัดสไตล์ไปใช้
  • แอตทริบิวต์จะซิงก์กับ ข้อความ Markdown ใน NSTextStorage ที่เปลี่ยนไปตามอินพุตของผู้ใช้ และกับ การตั้งค่าที่มีผลต่อข้อความ ที่ผู้ใช้ปรับผ่านรายการเมนู สไลเดอร์ และ gesture

ประสิทธิภาพ

  • การแยกเมตา แอตทริบิวต์เลย์เอาต์ และแอตทริบิวต์ตกแต่งออกจากกัน ช่วยให้รองรับการเปลี่ยนแปลงบางอย่างในตัวแก้ไขได้รวดเร็ว
  • ความเร็วในการพิมพ์คือปัจจัยด้านประสิทธิภาพที่สำคัญที่สุดในโปรแกรมแก้ไขข้อความ
  • ด้วยลักษณะการทำงานของ Markdown การเปลี่ยนข้อความอาจส่งผลต่อการจัดสไตล์ของทั้งย่อหน้าได้

เมตาแอตทริบิวต์

  • นอกเหนือจากตรรกะการไฮไลต์แล้ว เมตาแอตทริบิวต์ยังมีบทบาทสำคัญในฟีเจอร์ต่าง ๆ ที่ต้องรู้โครงสร้างของข้อความ

คีย์ลัดการจัดรูปแบบ

  • ให้ข้อมูลรายละเอียดที่จำเป็นในการสลับสไตล์ของข้อความ Markdown ที่เลือกไว้

การย้ายข้ามบท (chapter)

  • ช่วยค้นหาหัวข้อที่สัมพันธ์กับตำแหน่งของแคเร็ต

โครงร่าง (Outline)

  • อาศัยความสามารถในการไล่ดูหัวข้อทั้งหมด

การจัดเรียงบท (chapter) ใหม่

  • เปิดให้มีการจัดเรียงบทใหม่จากโครงร่าง

การแปลงรูปแบบ

  • ต้องรู้โครงสร้างเพื่อแปลงเนื้อหา Markdown เป็น RTF, HTML, DOCX

คณิตศาสตร์ของ text container

  • กฎที่สำคัญที่สุดของ text container คือการรักษาความยาวบรรทัดตามที่ต้องการ
  • บางครั้งต้องทำให้ดูสมมาตร เช่น เมื่อแท็กหัวข้อถูกวางไว้นอก flow ปกติของข้อความ

การยึดตำแหน่งการเลือก

  • การเลือกข้อความจะมีจุด anchor เสมอ
  • บน Mac สามารถคลิกแล้วลากเพื่อเลือกข้อความ ส่วนบน iOS สามารถลากปลายด้านหนึ่งของส่วนที่เลือกได้

Selection affinity

  • ในการแก้ไขข้อความมีแนวคิดที่น่าสนใจอย่าง selection affinity
  • เมื่อย้ายแคเร็ตด้วยปุ่มลูกศร จะเป็นเพียงการเปลี่ยนบรรทัด แต่เมื่อใช้คีย์ลัดเพื่อไปท้ายบรรทัด มันจะอยู่ในบรรทัดเดิมและชิดด้านขวา

Uniform Type Identifiers (UTIs)

  • กล่าวถึง UTIs ซึ่งเป็นระบบพื้นฐานสำหรับการแลกเปลี่ยนข้อมูลระหว่างแอป
  • เป็นระบบแบบลำดับชั้นที่ชนิดข้อมูลสามารถ conform to (สืบทอด) ชนิดข้อมูลแม่ได้

คลิปบอร์ด (Pasteboard)

  • คลิปบอร์ดคือพจนานุกรมที่ UTIs ถูกแมปเข้ากับข้อมูลที่ซีเรียลไลซ์แล้ว
  • การทำงาน คัดลอก เพียงครั้งเดียวจะเขียนหลายรูปแบบของข้อมูลเดียวกันพร้อมกัน
  • การจัดการ UTIs แบบสาธารณะและแบบส่วนตัวนั้นค่อนข้างตรงไปตรงมา แต่การจัดการรูปแบบที่ยอมรับกันอย่างกว้างขวางซึ่ง Apple ไม่ได้กำหนดไว้นั้นซับซ้อนกว่า

สรุป

  • หากดูบทความแรก จะได้ข้อมูลเพิ่มเติมเกี่ยวกับแอปและกระบวนการพัฒนา

ความเห็นของ GN⁺

  • บทความนี้อธิบายการทำงานภายในอันซับซ้อนของโปรแกรมแก้ไขข้อความที่อิงกับ TextView บนแพลตฟอร์ม Apple อย่างละเอียด จึงเป็นข้อมูลที่น่าสนใจสำหรับนักพัฒนาซอฟต์แวร์หรือผู้ใช้ที่สนใจ
  • วิธีจัดการแอตทริบิวต์และอัลกอริทึมเพื่อเพิ่มประสิทธิภาพของโปรแกรมแก้ไขข้อความเป็นกรณีศึกษาที่ดีให้นักพัฒนานำไปอ้างอิงในการออกแบบแอปพลิเคชันของตน
  • แนวทางเชิงเทคนิคที่ใช้เพื่อเพิ่มประสิทธิภาพของโปรแกรมแก้ไขข้อความให้แนวทางที่เป็นประโยชน์แก่นักพัฒนาคนอื่น ๆ เมื่อต้องแก้ปัญหาลักษณะคล้ายกัน
  • เมื่อต้องพัฒนาแอปพลิเคชันที่จัดการฟอร์แมตข้อความอย่าง Markdown ความเข้าใจเรื่อง UTIs มีความสำคัญต่อการแลกเปลี่ยนข้อมูลและความเข้ากันได้
  • บทความนี้ช่วยให้เข้าใจโครงสร้างภายในของโปรแกรมแก้ไขข้อความมากขึ้น แต่ในทางปฏิบัติ การจัดการความซับซ้อนเหล่านี้ยังคงเป็นความท้าทายอย่างมากสำหรับนักพัฒนา

1 ความคิดเห็น

 
GN⁺ 2024-03-06
ความคิดเห็นบน Hacker News
  • บทความนี้ดีมากจริง ๆ ดูเหมือนว่าจะมาแทนที่ https://www.objc.io ในฐานะแหล่งอ้างอิงเบื้องต้นของผมเกี่ยวกับ TextKit ได้เลย

    • ความคิดเห็นนี้ประเมินว่าบทความดังกล่าวมีประโยชน์มากในฐานะบทนำพื้นฐานเกี่ยวกับ TextKit
  • ผมค่อนข้างสับสนเล็กน้อยเกี่ยวกับคุณสมบัติเชิงตกแต่งที่ทำงานนอกทรานแซกชันการแก้ไข เขาบอกว่า “และมันไม่รับรู้ทรานแซกชัน เพราะมันอยู่ใน NSLayoutManager เอง ไม่ได้อยู่ใน NSTextStorage” แต่คุณสมบัติเชิงตกแต่งอย่างสี ปกติก็อยู่ใน NSTextStorage นี่นา! ผู้เขียนกำลังสื่อว่าการลงสีให้ตัวอักษร Markdown ถูกทำผ่านการรองรับคุณสมบัติชั่วคราวของ NSLayoutManager (ที่โดยทั่วไปใช้ระบายสีคำสะกดผิด) อย่างนั้นหรือ? ถ้าใช่ จุดประสงค์ของมันคืออะไรกันแน่?

    • ผู้แสดงความคิดเห็นรู้สึกสับสนกับรายละเอียดเชิงเทคนิคที่เกี่ยวข้องกับการแก้ไขข้อความ และตั้งข้อสงสัยต่อคำอธิบายของผู้เขียนเกี่ยวกับการจัดการคุณสมบัติเชิงตกแต่งระหว่าง NSLayoutManager กับ NSTextStorage
  • เป็นบทความที่ยอดเยี่ยมจริง ๆ (และสำหรับผมก็มาถูกจังหวะมาก เพราะตอนนี้กำลังจัดการกับ NSTextViews อยู่) คุณไปได้ข้อมูลพวกนี้มาจากไหน? จากโค้ดของคนอื่น? จากประสบการณ์อันเจ็บปวด? จาก developer.apple.com?

    • ผู้แสดงความคิดเห็นมองว่าบทความมีประโยชน์มาก และสงสัยว่าผู้เขียนได้ความรู้เหล่านี้มาอย่างไร
  • ในยุคของเอกสารแบบ DOM (เช่น notion, gitbook) ผมมักใช้ attributed string เพื่อทำเรื่องมหัศจรรย์เกี่ยวกับการพาร์สและจัดการข้อความอยู่บ่อย ๆ มันเป็นโครงสร้างที่สง่างามมาก และผมไม่เข้าใจเลยว่าทำไมมันถึงไม่เป็นที่รู้จักมากกว่านี้ อนึ่ง บทความนี้สุดยอดมาก

    • ผู้แสดงความคิดเห็นมองว่าการใช้ attributed string เป็นวิธีที่สง่างาม และกล่าวว่าไม่เข้าใจว่าทำไมเทคนิคนี้จึงไม่เป็นที่รู้จักในวงกว้างกว่านี้ พร้อมทั้งชื่นชมบทความไปด้วย
  • ผมเคยพยายามเขียน text editor ของตัวเองตั้งแต่ศูนย์มาก่อน และถ้ามีแหล่งข้อมูลแบบนี้ในตอนนั้นคงยอดเยี่ยมมากจริง ๆ

    • ผู้แสดงความคิดเห็นพูดถึงประสบการณ์ที่เคยพยายามสร้าง text editor ขึ้นมาเองตั้งแต่ต้น และบอกว่าบทความนี้คงช่วยได้มากถ้ามีอยู่ในเวลานั้น
  • ผมเป็นนักพัฒนาแอป Android มานาน ดังนั้นจึงน่าสนใจมากที่ได้เห็นว่า Apple จัดการสิ่งต่าง ๆ ด้วยแนวทางที่แตกต่างและรอบคอบกว่าเล็กน้อย บน Android นั้นคลาส Layout (รวมถึงซับคลาสของมัน) จัดการทุกอย่างที่เกี่ยวกับเลย์เอาต์และการเรนเดอร์ ส่วน TextView ก็ทำตรรกะบางส่วนของการแก้ไข/การเลือกข้อความ ความแตกต่างเพียงอย่างเดียวระหว่าง EditText กับ TextView คือ EditText “เปิดใช้” ความสามารถในการแก้ไขที่มีอยู่แล้วใน TextView ปัญหาของแนวทางที่ค่อนข้างรวมทุกอย่างไว้ด้วยกันแบบนี้ (รวมถึง API ที่ไม่ค่อยดี) คือถ้าแอปต้องการควบคุมวิธีเรนเดอร์ข้อความมากขึ้น คุณก็แทบหมดทางเลือก ตัวอย่างเช่น ถ้าอยากเข้าถึง glyph แต่ละตัวหลังจากจัดเลย์เอาต์เสร็จแล้ว? ไม่ได้หรอก ขอโทษด้วย

    • ผู้แสดงความคิดเห็นอธิบายความแตกต่างของแนวทางด้านการเรนเดอร์และการแก้ไขข้อความระหว่าง Android กับ Apple พร้อมชี้ว่าในฝั่ง Android จะมีข้อจำกัดเมื่อจำเป็นต้องควบคุมในระดับละเอียดมากขึ้น
  • แอป TextEdit แทบจะประกอบขึ้นจาก TextView เดียวเกือบทั้งหมด ผมคิดว่า WordPad น่าจะเป็นตัวเทียบฝั่ง Windows ซึ่งอิงกับคอนโทรล RichEdit เกร็ดสนุกอีกอย่างคือ RTF โดยพื้นฐานแล้วคือรูปแบบที่ซีเรียลไลซ์แล้วของ NSAttributedString และสิ่งเดียวกันนี้ก็ใช้ได้กับคอนโทรล RichEdit ของ Windows จริง ๆ แล้วดูเหมือนว่าฝั่ง Windows จะมาก่อนด้วยซ้ำ: https://en.wikipedia.org/wiki/Rich_Text_Format

    • ผู้แสดงความคิดเห็นกล่าวถึงว่าแอป TextEdit สร้างอยู่บน TextView และ RTF (Rich Text Format) เป็นรูปแบบที่ซีเรียลไลซ์ของ NSAttributedString นอกจากนี้ยังกล่าวด้วยว่าคอนโทรล RichEdit ที่ทำหน้าที่คล้ายกันบน Windows อาจเกิดขึ้นก่อน
  • ผมชอบแอปนี้มากจริง ๆ มันมาแทนที่แอป Markdown อื่นทั้งหมดของผมไปแล้ว รวมถึง obsidian และ ia Writer!

    • ผู้แสดงความคิดเห็นพอใจมากที่แอปนี้มาแทนที่แอปเดิมทั้งหมดที่ใช้ทำงานกับ Markdown
  • อย่างน้อยก็ยังดีที่ในปี 2024 ยังมีใครสักคนใช้ Cocoa อยู่

    • ผู้แสดงความคิดเห็นแสดงความโล่งใจที่ยังมีนักพัฒนาที่ยังคงใช้เฟรมเวิร์ก Cocoa อยู่
  • อยากให้มีเอกสารเกี่ยวกับคอมโพเนนต์ iOS แบบนี้มากกว่านี้จริง ๆ!

    • ผู้แสดงความคิดเห็นแสดงความหวังว่าอยากเห็นเอกสารลักษณะนี้เกี่ยวกับคอมโพเนนต์ iOS มากขึ้น