الوقت ليس مجرد أرقام: لماذا يخطئ حتى المطورون المحترفون
\n\nكل مطور iOS واجه مرة على الأقل مهمة: "فقط أريد الحصول على الوقت الحالي". قد يبدو الأمر بسيطًا، لكنه هنا بالتحديد يرتكب المبتدئون (وحتى المحترفون) أخطاءً تؤدي إلى أخطاء برمجية، وتعطل التطبيقات، واستياء المستخدمين.
\n\nفي هذه المقالة، سنستعرض خمسة من أكثر الأخطاء شيوعًا عند التعامل مع الوقت الحالي في Swift، والتي حصدت آلاف المشاهدات على Stack Overflow. ستتعلم كيفية تجنبها وكتابة كود نظيف وموثوق.
\n\n"أريد فقط الحصول على الوقت الحالي كـ datetime في Swift، لكني أحصل إما على nil أو شيء غير متوقع. ساعدوني!" — صرخة ألم نموذجية في المنتديات.\n\n
دعنا نفهم ما يحدث بشكل خاطئ.
\n\n1. خطأ DateFormatter: الإعدادات المحلية (Locale) هي العدو الأول
\n\nالمشكلة
\nالاستعلام الأكثر شيوعًا: "Swift get current time as datetime string". يكتب المطور:
\n\nlet dateFormatter = DateFormatter()\ndateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"\nlet currentTime = dateFormatter.string(from: Date())\nprint(currentTime) // هل يعمل؟ ليس تمامًا\n\nفي المحاكي أو على جهاز بإعدادات محلية إنجليزية، كل شيء يعمل بشكل رائع. ولكن بمجرد أن يختار المستخدم لغة مثل الألمانية أو العربية في الإعدادات، ستحصل على nil أو تنسيق غير متوقع.
لماذا يحدث هذا؟
\nافتراضيًا، يستخدم DateFormatter الإعدادات المحلية الحالية للجهاز. بالنسبة لتنسيقات التاريخ الثابتة التي يتم تحليلها أو عرضها في API، فهذه كارثة.
الحل
\nقم دائمًا بتعيين الإعدادات المحلية إلى en_US_POSIX للتنسيقات غير المخصصة لعرض المستخدم:
let dateFormatter = DateFormatter()\ndateFormatter.locale = Locale(identifier: "en_US_POSIX")\ndateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"\ndateFormatter.timeZone = TimeZone.current // لا تنسَ المنطقة الزمنية!\nlet currentTime = dateFormatter.string(from: Date())\nprint(currentTime) // "2024-12-25 14:30:00" — ثابت\n\nتذكر: en_US_POSIX هو أفضل صديق لك عند العمل مع تنسيقات التاريخ الثابتة في Swift.\n\n
2. تجاهل المنطقة الزمنية (TimeZone)
\n\nالمشكلة
\nلقد حصلت على سلسلة نصية بالوقت الحالي. ولكن أي وقت حصلت عليه بالفعل؟ محلي؟ UTC؟ وقت الخادم؟ يحدث الخطأ عندما لا يحدد المطور timeZone في DateFormatter.
مثال على الخطأ:
\nlet formatter = DateFormatter()\nformatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"\nlet now = formatter.string(from: Date())\n// النتيجة: "2024-12-25T14:30:00+0300" — هذا هو الوقت المحلي مع الإزاحة\n// ولكن ماذا لو كنت بحاجة دائمًا إلى UTC؟\n\nالحل
\nحدد دائمًا TimeZone بشكل صريح:
\n\n// للعمل مع الخادم (UTC)\nlet utcFormatter = DateFormatter()\nutcFormatter.timeZone = TimeZone(abbreviation: "UTC")\nutcFormatter.locale = Locale(identifier: "en_US_POSIX")\nutcFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"\nlet utcTime = utcFormatter.string(from: Date())\nprint(utcTime) // "2024-12-25T11:30:00Z"\n\n// لعرض المستخدم (وقته المحلي)\nlet localFormatter = DateFormatter()\nlocalFormatter.timeZone = TimeZone.current\nlocalFormatter.dateStyle = .medium\nlocalFormatter.timeStyle = .short\nlet localTime = localFormatter.string(from: Date())\nprint(localTime) // "25 ديسمبر 2024، 2:30 م"\n\n3. استخدام Date() للمقارنة: مخاطر خفية
\n\nالمشكلة
\nيعتقد الكثيرون أن Date() يُرجع نفس القيمة ضمن استدعاء واحد. لكن هذا غير صحيح. Swift Date هي لقطة زمنية لحظية. إذا استدعيت Date() مرتين في الكود، فقد تختلف القيم بميكروثانية.
المدونات
توصيات الكتب
اقرأ أيضًا