مقدمة: لماذا لا يترك هذا الخط الملعون المطورين ينامون؟
\n\nإذا سبق لك أن حاولت تصميم تطبيق "مثل Apple Music" أو "مثل Telegram" - فمن المؤكد أنك واجهت هذا. تقوم بإنشاء UINavigationBar مثالي مع تدرج جميل، أو شفافية، أو لون مخصص، وتشغل المحاكي - وترى هذا الخط الرمادي أو الأسود الرفيع (1 بكسل) في الأسفل. يبدو وكأنه قطعة أثرية، مثل الأوساخ على الزجاج. ونعم، إنه مزعج.
هذا الخط الذي يبلغ 1 بكسل ليس خطأ، بل هو ميزة. إنه shadowImage + backgroundImage اللذان تركتهما Apple افتراضيًا لسبب ما. حتى في iOS 17، لا يزال يظهر إذا لم تقل للنظام: "مرحبًا، أزل هذا". السؤال على Stack Overflow حول هذا الموضوع حصل على آلاف المشاهدات وعشرات الإجابات. هذا يعني أن الموضوع مؤلم حقًا.
\n\nفي هذه المقالة، سأعرض 3 طرق عملية بلغة Swift لإخفاء الخط السفلي لـ UINavigationBar. سنستعرض الطرق القديمة (iOS 13-) والطرق الحديثة عبر UINavigationBarAppearance. هيا بنا!
الطريقة 1: الطريقة الكلاسيكية - عبر backgroundImage و shadowImage
\n\nأقدم طريقة وأكثرها اختبارًا. تعمل منذ iOS 5 (نعم، منذ الأيام التي كان فيها السكيومورفيزم رائجًا). الفكرة بسيطة: نقوم بتعيين صورة فارغة كخلفية وظل.
\n\nالخطوة 1: إنشاء صورة فارغة
\n\nextension UIImage {\n static func pixelImage(withColor color: UIColor = .clear) -> UIImage {\n let rect = CGRect(x: 0, y: 0, width: 1, height: 1)\n UIGraphicsBeginImageContext(rect.size)\n color.setFill()\n UIRectFill(rect)\n let image = UIGraphicsGetImageFromCurrentImageContext()\n UIGraphicsEndImageContext()\n return image ?? UIImage()\n }\n}\n\nالخطوة 2: تطبيقها على navigationBar
\n\nfunc hideBottomLine() {\n let emptyImage = UIImage.pixelImage()\n navigationController?.navigationBar.setBackgroundImage(emptyImage, for: .default)\n navigationController?.navigationBar.shadowImage = emptyImage\n}\n\nالإيجابيات: تعمل في كل مكان، حتى على إصدارات iOS القديمة.
\nالسلبيات: لا تعمل دائمًا بشكل صحيح مع scrollEdgeAppearance والعناوين الكبيرة. إذا كان لديك UISearchBar - قد يعود الخط.
الطريقة 2: الطريقة الحديثة - عبر UINavigationBarAppearance (iOS 13+)
\n\nبدءًا من iOS 13، قدمت Apple UINavigationBarAppearance. هذا كائن واحد يدير جميع الحالات: القياسية، والتمرير، والمضغوطة. مثالي لمن يريد "ضبط مرة واحدة ونسيان الأمر".
مثال كامل لـ UIViewController
\n\nfunc setupTransparentNavigationBar() {\n let appearance = UINavigationBarAppearance()\n appearance.configureWithTransparentBackground()\n appearance.backgroundColor = .clear\n appearance.shadowColor = .clear // يزيل الخط\n \n navigationController?.navigationBar.standardAppearance = appearance\n navigationController?.navigationBar.scrollEdgeAppearance = appearance\n navigationController?.navigationBar.compactAppearance = appearance\n}\n\nلاحظ: shadowColor = .clear هو السطر الأساسي. إذا لم تكتبه، سيبقى الخط. configureWithTransparentBackground() يجعل الخلفية شفافة، لكنه لا يلمس الظل.
إذا كنت بحاجة إلى خلفية ملونة ولكن بدون خط:
\n\nlet appearance = UINavigationBarAppearance()\nappearance.configureWithOpaqueBackground()\nappearance.backgroundColor = .systemBlue\nappearance.shadowColor = .clear\n\nnavigationController?.navigationBar.standardAppearance = appearance\nnavigationController?.navigationBar.scrollEdgeAppearance = appearance\n\nالإيجابيات: كود نظيف، سهل الدمج مع العناوين الكبيرة والبحث.
\nالسلبيات: فقط iOS 13+. إذا كان المشروع يدعم iOS 12 - سيتعين