Console در Xcode یک ابزار اشکالزدایی برای توسعه iOS است که خروجی NSLog، print، os_log و لاگهای crash برنامه را در زمان واقعی نمایش میدهد. به گفته Apple Unified Logging، از iOS 10 به بعد اپل استفاده از os_log را به جای NSLog برای جمعآوری متمرکز پیامها از طریق Unified Logging System توصیه میکند. Console خروجی دیباگر و پیامهای سیستم را در یک پنجره واحد Debug Area ترکیب میکند که در هر لحظه از توسعه در دسترس است.
نکات اصلی
Console — بخشی از Debug Area در Xcode است که در پنل پایینی ویرایشگر قرار دارد (View → Debug Area → Activate Console، کلید ترکیبی Cmd + Shift + Y). Console تمام خروجی متنی برنامه در حال اجرا را نشان میدهد: پیامهای NSLog، os_log، print، هشدارهای زمان اجرا (runtime warnings) و dump خودکار استثناها هنگام crash برنامه.
Console هم روی شبیهساز و هم روی دستگاه فیزیکی کار میکند. روی شبیهساز پیامها بلافاصله از طریق pipe محلی میرسند، روی دستگاه — از طریق اتصال USB با تأخیر ۱–۳ فریم. برای برنامههای تولیدی، Console روی دستگاه در دسترس نیست — توسعهدهنده به Crashlytics یا Unified Logging با جمعآوری از راه دور از طریق log collect متکی است.
برخلاف برنامه سیستمی Console.app در مک، پنجره Console در Xcode فقط لاگهای برنامه در حال اجرای فعلی را نشان میدهد (با قابلیت فیلتر کردن). Console.app لاگهای همه فرآیندهای مک از جمله شبیهسازهای iOS را جمعآوری میکند. با این حال، برای اشکالزدایی برنامههای iOS، توسعهدهندگان از Console داخلی Xcode به دلیل یکپارچگی با دیباگر LLDB استفاده میکنند.
سه API اصلی برای توسعهدهنده iOS برای خروجی در Console در دسترس است: NSLog (منسوخ)، os_log (توصیهشده) و print (فقط Swift). هرکدام ویژگیهای خاص خود را از نظر عملکرد، قالببندی و سازگاری با Unified Logging System دارند.
NSLog — تابعی از Foundation، قابل دسترس در Objective-C و Swift. NSLog پیام را با برچسب زمانی، نام فرآیند و PID خروجی میدهد. معایب: NSLog به صورت synchronous در بافر سیستم مینویسد و thread فعلی را در زمان نوشتن مسدود میکند. در فراخوانیهای مکرر (مثلاً در حلقه)، NSLog تأخیر قابل توجهی ایجاد میکند. اپل NSLog را برای پروژههای جدید توصیه نمیکند، اما با کد قدیمی و کتابخانههای شخص ثالث سازگار باقی میماند.
os_log — API از os.framework، معرفیشده در iOS 10. os_log ناهمگام (asynchronous) است: پیام در صف قرار میگیرد و بدون مسدود کردن thread فراخوان در بافر نوشته میشود. به گفته WWDC 2016، os_log در سناریوهای با بار بالا ۵۰ برابر سریعتر از NSLog است. os_log همچنین از مدیریت پویا پشتیبانی میکند: پیامهای سطح DEBUG فقط در ساخت Debug جمعآوری میشوند، در Release بدون سربار عملکرد نادیده گرفته میشوند.
print() — سادهترین روش خروجی در Swift. print در stdout (خروجی استاندارد) مینویسد که Xcode آن را به Console هدایت میکند. print فراداده (زمان، سطح) اضافه نمیکند، اما از بافر stdout پشتیبانی میکند. برای اشکالزدایی سریع، print ابزار مناسبی است، اما برای لاگینگ دائمی از نظر عملکرد و کنترل از os_log پایینتر است.
import os.log
// NSLog — منسوخ، مسدودکننده
NSLog("Application started")
// os_log — توصیهشده، ناهمگام
let log = OSLog(
subsystem: "com.myapp",
category: "lifecycle"
)
os_log("Application started", log: log)
// print — خروجی سریع Swift
print("Application started")
Unified Logging System (ULS) — زیرساخت جامع لاگینگ اپل، معرفیشده در iOS 10 و macOS Sierra. ULS پیامهای همه فرآیندهای سیستم را در یک مخزن واحد جمعآوری میکند با امکان دسترسی از راه دور از طریق ابزار خط فرمان log در مک. توسعهدهنده از os_log برای نوشتن در ULS و از Console برای خواندن استفاده میکند.
هر OSLog با یک جفت subsystem (مثلاً com.myapp.network) و category (مثلاً http، websocket) شناسایی میشود. زیرسیستم دامنه برنامه است (یک برنامه میتواند چندین زیرسیستم برای ماژولهای مختلف داشته باشد). دستهبندی یک جزء در داخل زیرسیستم است. ترکیب subsystem + category امکان فیلتر کردن انعطافپذیر لاگها در Console و log collect را فراهم میکند.
| سطح | OSLogType | نمایش در Console | جمعآوری در Release |
|---|---|---|---|
| Default | .default | همیشه | بله |
| Info | .info | هنگام فعال بودن os_log UI | بله |
| Debug | .debug | فقط در ساخت Debug | خیر |
| Error | .error | همیشه با برچسب قرمز | بله |
| Fault | .fault | همیشه با برچسب بنفش | بله |
دستور log collect در مک لاگهای بایگانیشده را از دستگاه iOS متصل در یک فایل .logarchive جمعآوری میکند. این فایل را میتوان در Console.app در مک برای تحلیل دقیق باز کرد، از جمله پیامهای os_log، لاگهای crash و تشخیص سیستم. برای فعال کردن جمعآوری روی دستگاه، باید Developer Mode را فعال کرده و دستگاه را از طریق USB متصل کنید.
کار عملی با Console شامل سه سناریوی اصلی است: لاگینگ فعال در طول توسعه، تحلیل لاگهای crash پس از سقوط و تشخیص از راه دور از طریق .logarchive. برای هر سناریو مجموعه ابزار و تنظیمات بهینه وجود دارد.
توصیه میشود برای هر ماژول برنامه یک OSLog جداگانه با سطوح ایجاد کنید: debug (اشکالزدایی دقیق)، info (گذرهای کلیدی حالت)، error (استثناها و خرابیها). در Console Xcode فیلتر را بر اساس زیرسیستم برنامه خود فعال کنید تا پیامهای سیستمی که نویز ایجاد میکنند و از منطق برنامه منحرف میکنند، حذف شوند.
هنگام crash برنامه، Xcode به طور خودکار اجرا را متوقف میکند و threadای که crash در آن رخ داده با stack trace کامل در Console نشان میدهد. اولین خط لاگ crash شامل نوع استثنا (NSException، EXC_BAD_ACCESS) و دلیل (reason) است. Stack trace را از پایین به بالا بررسی کنید: آخرین متد فراخوانیشده محل crash است. برای آدرسهای رمزگذاریشده (در Release) symbolication از طریق dSYM مورد نیاز است.
// نمونه پیکربندی ماژولار OSLog
extension OSLog {
static let uiLifecycle = OSLog(
subsystem: "com.myapp.ui",
category: "lifecycle"
)
static let network = OSLog(
subsystem: "com.myapp.network",
category: "http"
)
static let database = OSLog(
subsystem: "com.myapp.data",
category: "core-data"
)
}
// استفاده با سطوح
os_log("View did load", log: .uiLifecycle, type: .debug)
os_log("HTTP 200 received", log: .network, type: .info)
os_log("Failed to save: \(error.localizedDescription)",
log: .database, type: .error)
Xcode Console از چندین عملکرد پیشرفته پشتیبانی میکند که فراتر از لاگینگ ساده هستند. Breakpoint-logs امکان خروجی پیامها در Console بدون توقف اجرا را فراهم میکنند و دستورات LLDB در Debugger Command کنترل کاملی بر قالببندی خروجی میدهند.
میتوانید breakpoint را طوری تنظیم کنید که پیامی را در Console خروجی دهد و به طور خودکار اجرا را ادامه دهد. Breakpoint را روی خط مورد نظر قرار دهید، کلیک راست → Edit Breakpoint → Debugger Command اضافه کنید: «po self» یا «expr @import UIKit» + Debugger Command: «po self.view». Automatically continue after evaluating را علامت بزنید. پس از اجرا، breakpoint در هر بار رسیدن به خط، نتیجه دستور را بدون قطع کردن thread در Console نمایش میدهد.
Console Xcode پشتیبانی میکند از اجرای دستورات دلخواه LLDB در زمان توقف روی breakpoint. po (print object) توضیح شیء را خروجی میدهد، p (print) — مقادیر اولیه، و expr — عبارات Swift/ObjC را اجرا میکند. برای خروجی قالببندیشده از p/CGRectGetWidth استفاده کنید. خروجی LLDB بلافاصله پس از رسیدن به breakpoint در Console نمایش داده میشود.
func processUserData(user: User) {
// Breakpoint اینجا با Debugger Command:
// po "User name: \(user.name)"
// expr user.age = 30
print("Processing user: \(user.name)")
}
// نمونه لاگینگ سفارشی با توالی
func trackMethodCall(
file: String = #file,
function: String = #function
) {
os_log("[\(function)] called",
log: .uiLifecycle, type: .debug)
}
Console Xcode به طور نزدیک با Instruments — ابزار پروفایل Xcode — یکپارچه شده است. هنگام اجرای برنامه از طریق Product → Profile با الگوی Logging، تمام پیامهای os_log در trace Instruments با برچسبهای زمانی ثبت میشوند. این امکان را فراهم میکند که همزمان لاگها، عملکرد و رویدادهای سیستم را روی یک مقیاس زمانی مشاهده کنید، که برای تشخیص race condition و پسرفت عملکرد حیاتی است.
سوالات متداول
NSLog — synchronous، thread را مسدود میکند و همیشه پیام را خروجی میدهد. os_log — asynchronous، در سناریوهای با بار بالا ۵۰ برابر سریعتر است، از دستهبندیها و غیرفعالسازی پویای سطوح debug در ساخت Release بدون افت عملکرد پشتیبانی میکند.
سطح لاگینگ را بررسی کنید: به طور پیشفرض Console فقط default و بالاتر را نشان میدهد. برای مشاهده info و debug، منوی os_log را در Console Xcode باز کنید و Include Info Messages و Include Debug Messages را انتخاب کنید، همچنین در تنظیمات Scheme (Edit Scheme → Run → Arguments → OS_ACTIVITY_MODE = debug).
پیامهای مورد نظر را در Console انتخاب کنید، کپی کنید (Cmd + C) و در هر ویرایشگر متنی جایگذاری کنید. برای dump کامل از دستور ترمینال استفاده کنید: sudo log collect --device --output /tmp/app_logs.logarchive — این دستور تمام لاگهای دستگاه iOS را در قالب ساختاریافته ذخیره میکند.
os_log از نوع .default و .error به طور پیشفرض در Release کار میکنند. برای .info و .debug در Release باید آرگومان راهاندازی -OSLogPreferencesApp «$(PRODUCT_BUNDLE_IDENTIFIER):debug» را به Scheme Xcode اضافه کنید. بدون این آرگومان، پیامهای debug در Release جمعآوری نمیشوند که باعث صرفهجویی در منابع دستگاه میشود.
پنجره Window → Organizer → Crashes را در Xcode باز کنید. Organizer تمام لاگهای crash جمعآوریشده از دستگاههای تستکنندگان را گروهبندیشده بر اساس نوع استثنا نشان میدهد. برای symbolication فایل .dSYM از همان ساختی که crash در آن رخ داده مورد نیاز است — Xcode در صورت وجود آرشیو آن را به طور خودکار پیدا میکند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.
همچنین بخوانید