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.