Swift: print () vs println () vs NSLog ()


450

คือสิ่งที่แตกต่างระหว่างprint, NSLogและprintlnและเมื่อฉันควรใช้แต่ละคน?

ตัวอย่างเช่นใน Python ถ้าฉันต้องการพิมพ์พจนานุกรมฉันแค่print myDictแต่ตอนนี้ฉันมี 2 ตัวเลือกอื่น ๆ ฉันควรใช้แต่ละวิธีอย่างไรและเมื่อใด



2
สิ่งที่เกี่ยวกับ NSLog และการพิมพ์ NSDictionary ไม่มีประโยชน์อะไรเลย?
ผู้ใช้

จาก iOS 10.0 os_logไปข้างหน้าก็ขอแนะนำให้ใช้อย่างใดอย่างหนึ่ง โปรดดูคำตอบของฉันด้านล่าง
HuaTham

นอกเหนือจากการดูเอกสารประกอบ Swift ในos_log: ลองดูเอกสารทั้งหมดของหน้าวัตถุประสงค์ -C มันมากขึ้นสมบูรณ์
น้ำผึ้ง

คำตอบ:


758

ข้อแตกต่างเล็กน้อย:

  1. printvs println:

    printฟังก์ชั่นการพิมพ์ข้อความในคอนโซล Xcode เมื่อแก้จุดบกพร่องปพลิเคชัน

    นี่printlnคือรูปแบบของสิ่งนี้ที่ถูกลบออกใน Swift 2 และไม่ได้ใช้อีกต่อไป ถ้าคุณเห็นรหัสเดิมที่ใช้ตอนนี้คุณสามารถได้อย่างปลอดภัยแทนที่ด้วยprintlnprint

    ย้อนกลับไปในสวิฟท์ 1.x, printไม่ได้เพิ่มตัวละครขึ้นบรรทัดใหม่ในตอนท้ายของสตริงที่พิมพ์ออกมาในขณะที่printlnไม่ได้ทำ แต่ในปัจจุบันprintมักจะเพิ่มตัวละครขึ้นบรรทัดใหม่ในตอนท้ายของสตริงและถ้าคุณไม่ต้องการที่จะทำว่าจัดหาพารามิเตอร์ของterminator""

  2. NSLog:

    • NSLog ช้ากว่า

    • NSLogเพิ่มการประทับเวลาและตัวระบุลงในเอาต์พุตในขณะที่printจะไม่

    • NSLogคำสั่งปรากฏในทั้งคอนโซลของอุปกรณ์และคอนโซลของดีบักเกอร์ในขณะที่printปรากฏเฉพาะในคอนโซลดีบักเกอร์

    • NSLogใช้printfสตริงรูปแบบสไตล์เช่น

      NSLog("%0.4f", CGFloat.pi)

      ที่จะผลิต:

      2017-06-09 11: 57: 55.642328-0700 MyApp [28937: 1751492] 3.1416

  3. iOS ที่มีประสิทธิภาพ 10 / macOS 10.12 มีทางเลือกที่สามos_logซึ่งเป็นส่วนหนึ่งของระบบ "การบันทึกแบบครบวงจร" (ดูการบันทึกการทำงานแบบวิดีโอภาพรวมของ WWDC 2016 และการติดตามกิจกรรม )

    • คุณต้องนำเข้าos.logก่อนใช้os_logฟังก์ชัน:

      import os.log
    • ชอบNSLog, os_logข้อความจะส่งออกไปยังทั้ง Xcode แก้จุดบกพร่องและคอนโซลคอนโซลอุปกรณ์ที่มากเกินไป

    • ตอนนี้คุณสามารถควบคุมฟิลด์ "ระบบย่อย" และ "หมวดหมู่" ที่มีอยู่ในแอพคอนโซล ตัวอย่างเช่น:

      let log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "network")
      os_log("url = %@", log: log, url.absoluteString)
      

      เมื่อคุณสังเกตแอพผ่านแอพคอนโซลภายนอกคุณไม่เพียง แต่สามารถเพิ่มคอลัมน์เหล่านี้ไปยังมุมมองหลัก แต่คุณสามารถกรองตามสิ่งเหล่านี้ได้ มันมีประโยชน์มากเมื่อต้องการแยกแยะข้อความที่ดีบั๊กจาก (ก) ข้อความที่สร้างโดยระบบย่อยอื่น ๆ ในนามของแอพของคุณ หรือ (b) ข้อความจากหมวดหมู่หรือประเภทอื่น ๆ

    • คุณสามารถระบุความแตกต่างของการเข้าสู่ระบบข้อความอย่างใดอย่างหนึ่ง.info, .debug, .error, .fault(หรือ.default):

      os_log("web service did not respond", type: .error)

      ดังนั้นหากใช้แอปคอนโซลภายนอกคุณสามารถเลือกที่จะเห็นข้อความของบางหมวดหมู่เท่านั้น (เช่นแสดงเฉพาะข้อความที่ดีบั๊กหากคุณเลือก "รวมข้อความดีบั๊ก" ในเมนู "การกระทำ" ของคอนโซล) การตั้งค่าเหล่านี้ยังบอกรายละเอียดของปัญหาที่ละเอียดอ่อนหลายอย่างเกี่ยวกับว่าสิ่งต่าง ๆ นั้นถูกบันทึกไว้ในดิสก์หรือไม่ ดูวิดีโอ WWDC สำหรับรายละเอียดเพิ่มเติม

    • os_logคุณไม่สามารถใช้สตริงแก้ไขเมื่อใช้ ตัวอย่างเช่นคุณไม่สามารถทำได้:

      os_log("foo \(url.absoluteString)")

      คุณจะต้องทำ:

      os_log("url = %@", url.absoluteString)
    • หนึ่งในเหตุผลสำหรับข้อ จำกัด ข้างต้นคือการสนับสนุนความเป็นส่วนตัวของข้อมูล ประเภทข้อมูลดั้งเดิม (เช่นตัวเลข) เป็นสาธารณะโดยค่าเริ่มต้นและวัตถุ (เช่นสตริง) เป็นส่วนตัวโดยค่าเริ่มต้น ในตัวอย่างก่อนหน้านี้ที่คุณบันทึก URL หากแอปถูกเรียกใช้จากอุปกรณ์และคุณกำลังดูจากแอปคอนโซลของ Mac คุณจะเห็น:

      url = <private>

      หากคุณต้องการที่จะเห็นมันจากอุปกรณ์ภายนอกคุณต้องทำ:

      os_log("url = %{public}@", url.absoluteString)
    • หมายเหตุNSLogตอนนี้ใช้ระบบการแจ้งเตือนแบบรวมเบื้องหลัง แต่ด้วยคำเตือนต่อไปนี้:

      • คุณไม่สามารถควบคุมระบบย่อยหรือหมวดหมู่หรือประเภทบันทึก

      • ไม่รองรับการตั้งค่าความเป็นส่วนตัว

บรรทัดล่างprintเพียงพอสำหรับงานง่าย ๆ แต่NSLogมีประโยชน์เนื่องจากมีข้อมูลเวลาประทับสำหรับคุณ

พลังของการos_logบรรเทาลงอย่างสิ้นเชิงเมื่อทำการดีบั๊กแอพ iOS ที่ต้องทดสอบภายนอก Xcode ตัวอย่างเช่นเมื่อการทดสอบพื้นหลังกระบวนการแอป iOS เช่นพื้นหลังดึงข้อมูลการเชื่อมต่อกับดีบัก Xcode เปลี่ยนแปลงวงจรชีวิตของแอป ดังนั้นคุณมักจะต้องการทดสอบอุปกรณ์ทางกายภาพเรียกใช้แอปจากอุปกรณ์เองไม่ใช่เริ่มต้นแอปจากดีบักเกอร์ของ Xcode การบันทึกแบบรวมช่วยให้คุณยังคงดูos_logคำสั่งอุปกรณ์ iOS ของคุณจากแอปคอนโซล macOS


37
สรุปดี! ในการเพิ่มอีกไม่กี่: คุณสามารถผ่าน NSString ไปยัง println แต่ไม่ใช่ NSLog; คุณสามารถเพิ่ม args สำหรับ NSLog แต่ไม่ใช่ println; การแก้ไขสตริงของ Swift ในบางครั้งอาจล้มเหลวสำหรับ NSLog แต่ไม่สามารถพิมพ์ได้
Bao Lei

2
หมายเหตุที่น่าสนใจเกี่ยวกับการเพิ่มประสิทธิภาพคอมไพเลอร์ Swift และการใช้งานสื่อพิมพ์ () medium.com/ios-os-x-development/ …
Carl

@Rob ถ้าฉันใช้ print มันจะปรากฏในคอนโซลดีบักเกอร์หรือไม่? หรือเราควรใช้ debugPrint?

1
ถ้าคุณใช้printมันแสดงให้เห็นขึ้นมาในพื้นที่การแก้ปัญหาของ Xcode debugPrintเช่นเดียวกับ ความแตกต่างเพียงอย่างเดียวคือprintปลายขึ้นเรียกdescriptionวิธีการของวัตถุและdebugPrintสายซึ่งอาจจะมีมากขึ้นอย่างละเอียดกว่าdebugDescription description
Rob

@Honey, เธรดความคิดเห็นนี้ถูกตั้งค่าสถานะว่ายาวเกินไป, ดังนั้นฉันแค่ต้องการเตือนให้คุณทราบว่าความคิดเห็นนั้นไม่ได้มีไว้สำหรับการอภิปรายหรือการแก้ไขข้อผิดพลาดที่เพิ่มขึ้น. หากคุณมีสิ่งที่สามารถถามได้ว่าเป็นคำถามที่เหมาะสมกับรูปแบบ Stack Overflow แล้วโปรดถามเป็นคำถามเพื่อให้ทุกคนได้รับประโยชน์จากคำตอบ หากไม่ได้เป็นคำถามคุณจะต้องทำการสนทนาเพื่อสนทนา จองความคิดเห็นเพียงเพื่อขอคำชี้แจงหรือทำการสังเกตอย่างรวดเร็ว
Cody Gray

80

หากคุณใช้Swift 2ตอนนี้คุณสามารถใช้ print () เพื่อเขียนบางสิ่งบางอย่างไปยังเอาต์พุต

Apple ได้รวมฟังก์ชันprintln ()และprint ()ไว้ในที่เดียว

อัปเดตเป็น iOS 9

โดยค่าเริ่มต้นฟังก์ชั่นยกเลิกสายมันพิมพ์โดยการเพิ่มตัวแบ่งบรรทัด

print("Hello Swift")

Terminator

หากต้องการพิมพ์ค่าโดยไม่มีตัวแบ่งบรรทัดหลังจากผ่านให้ส่งสตริงว่างเป็นเทอร์มิเนเตอร์

print("Hello Swift", terminator: "")

เครื่องสกัด

ตอนนี้คุณสามารถใช้ตัวคั่นเพื่อต่อหลายรายการ

print("Hello", "Swift", 2, separator:" ")

ทั้งสอง

หรือคุณสามารถรวมการใช้ด้วยวิธีนี้

print("Hello", "Swift", 2, separator:" ", terminator:".")

5
appendNewlineมีค่าเริ่มต้นของtrue
Adam

1
ใน iOS (9.0) คุณต้องใช้terminator : ""เช่นprint("...", terminator: "")
Khotu Nam

คำสั่งในประโยคแรกของคุณไม่ถูกต้อง NSLog () ยังคงใช้ได้แม้ใน Swift 2.x ล่าสุด
เซบาสเตียน

62

นอกจากนี้ Swift 2 ยังมีdebugPrint()(และCustomDebugStringConvertibleโปรโตคอล)!

อย่าลืมเกี่ยวกับdebugPrint()ที่ทำงานเหมือนprint()แต่ที่เหมาะสมที่สุดสำหรับการแก้จุดบกพร่อง

ตัวอย่าง:

  • เงื่อนไข
    • print("Hello World!") กลายเป็น Hello World
    • debugPrint("Hello World!")กลายเป็น"Hello World"(คำคม!)
  • ช่วง
    • print(1..<6) กลายเป็น 1..<6
    • debugPrint(1..<6) กลายเป็น Range(1..<6)

คลาสใด ๆ สามารถกำหนดสตริงการดีบักเองได้ผ่านCustomDebugStringConvertibleโปรโตคอล


2
DebugPrintableโปรโตคอลได้รับการเปลี่ยนชื่อเป็นโปรโตคอลCustomDebugStringConvertible
Franklin Yu

ขอบคุณแฟรงคลิน!
Valentin Shergin

ดังนั้นสวิฟท์descriptionคือการdebugDescriptionเป็น Python strคือการrepr?
BallpointBen

อืมฉันก็คิดแบบนั้น.
Valentin Shergin

39

เพื่อเพิ่มคำตอบของ Rob ตั้งแต่ iOS 10.0 แล้ว Apple ได้เปิดตัวระบบ "Unified Logging" ใหม่ทั้งหมดที่ใช้แทนระบบบันทึกที่มีอยู่ (รวมถึง ASL และ Syslog, NSLog) และยังเหนือกว่าวิธีการบันทึกที่มีอยู่ในปัจจุบันด้วยเทคนิคใหม่ ได้แก่ การบีบอัดข้อมูลล็อกและการรวบรวมข้อมูลที่เลื่อนออกไป

จากApple :

ระบบการบันทึกแบบครบวงจรจัดทำ API ที่มีประสิทธิภาพและมีประสิทธิภาพเดียวสำหรับการจับการส่งข้อความในทุกระดับของระบบ ระบบที่รวมเป็นหนึ่งนี้จะรวมศูนย์การจัดเก็บข้อมูลบันทึกในหน่วยความจำและในแหล่งข้อมูลบนดิสก์

Apple แนะนำอย่างยิ่งให้ใช้os_logการบันทึกข้อความทุกประเภทรวมถึงข้อมูลการดีบักข้อความแสดงข้อผิดพลาดเนื่องจากประสิทธิภาพที่ได้รับการปรับปรุงดีขึ้นมากเมื่อเทียบกับระบบการบันทึกก่อนหน้านี้และการรวบรวมข้อมูลจากส่วนกลาง ในความเป็นจริงระบบใหม่มีแนวโน้มต่ำมากซึ่งจะไม่ทำให้เกิด "ผู้สังเกตการณ์เอฟเฟกต์" ซึ่งข้อผิดพลาดของคุณจะหายไปหากคุณแทรกคำสั่งการบันทึกซึ่งรบกวนเวลาของข้อผิดพลาด

ประสิทธิภาพของการติดตามกิจกรรมตอนนี้เป็นส่วนหนึ่งของระบบ Unified Logging ใหม่

คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับการนี้ในรายละเอียดที่นี่

เพื่อสรุปผล: ใช้print()สำหรับการดีบักส่วนบุคคลของคุณเพื่อความสะดวก (แต่ข้อความจะไม่ถูกบันทึกเมื่อนำไปใช้กับอุปกรณ์ผู้ใช้) จากนั้นใช้ Unified Logging ( os_log) ให้มากที่สุดสำหรับทุกสิ่ง


5

มีวิธีอื่นที่เรียกว่าdump()ซึ่งสามารถใช้สำหรับการบันทึก:

func dump<T>(T, name: String?, indent: Int, maxDepth: Int, maxItems: Int)

ดัมพ์เนื้อหาของวัตถุโดยใช้มิเรอร์ไปยังเอาต์พุตมาตรฐาน

จากฟังก์ชันไลบรารีมาตรฐานของ Swift

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