مقدمة: "سحر" UIScrollView الذي يتوقف عن العمل
هل سبق لك أن واجهت موقفًا: تضيف UIScrollView إلى مشروعك في Swift، وتضبط Auto Layout، وتشغل التطبيق - ولا شيء يتم التمرير؟ أو الأسوأ من ذلك، أن Xcode يعطي خطأ غامضًا: "UIScrollView scrollable content size ambiguity"؟ إذا كان الأمر كذلك - فأنت لست وحدك. هذا السؤال حصد آلاف المشاهدات على Stack Overflow، واليوم سنفهم الأمر نهائيًا.
تخيل: تقوم بإنشاء شاشة تحتوي على نموذج تسجيل طويل أو مقال لا يتسع لشاشة واحدة. تضيف UIScrollView، وتضع فيه جميع العناصر، وتوزع القيود - ثم... صمت. التمرير لا يعمل. مألوف؟ مرحبًا بك في نادي المطورين الذين لعنوا Auto Layout لـ "عدم فهمه".
في الحقيقة، مشكلة Content Size Ambiguity ليست خطأ في iOS، بل فخ منطقي. النظام ببساطة لا يعرف كم يجب أن يكون حجم المحتوى الخاص بك. في هذا الدليل التعليمي، سنستعرض السبب، وثلاث طرق للحل، ونكتب كودًا عمليًا حقيقيًا. هيا بنا!
ما هو Content Size Ambiguity ولماذا يحدث؟
UIScrollView هو كائن خاص في عالم UIKit. على عكس المشاهدات العادية، فهو لا يحدد حجمه بناءً على قيود العناصر الفرعية. بدلاً من ذلك، يستخدم الخاصية contentSize (من نوع CGSize)، والتي تشير إلى حجم "اللوحة" الداخلية. إذا كان contentSize أصغر أو مساويًا لحجم UIScrollView نفسه، فإن التمرير... غير ضروري.
يحدث خطأ Scrollable Content Size Ambiguity عندما لا يستطيع Auto Layout حساب contentSize بشكل قاطع بناءً على القيود داخل عرض التمرير. السيناريوهات النموذجية:
- لم تقم بتعيين قيود للارتفاع أو العرض للمحتوى الداخلي.
- القيود "عائمة" (مثلاً، لا يوجد اتصال بأعلى وأسفل عرض التمرير).
- تستخدم
UIStackViewداخلUIScrollViewولكنك لم تضبط أحجامه. - نسيت أن
UIScrollViewيتطلب سلسلة كاملة من القيود من الحافة إلى الحافة.
في وحدة تحكم Xcode، سترى شيئًا مثل:
Unable to simultaneously satisfy constraints.Will attempt to recover by breaking constraint....UIScrollView scrollable content size ambiguityيبدو مخيفًا، لكن الحل بسيط. دعنا نكتب الكود.
الخطوة 1: إنشاء مشروع وإضافة UIScrollView
افتح Xcode، وأنشئ مشروعًا جديدًا باستخدام قالب App (iOS, Swift). سمِّه مثلاً ScrollFixDemo. انتقل إلى ViewController.swift واستبدل كل الكود بما يلي:
import UIKit
class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() setupScrollView() } private func setupScrollView() { // 1. إنشاء UIScrollView let scrollView = UIScrollView() scrollView.translatesAutoresizingMaskIntoConstraints = false scrollView.backgroundColor = .systemGray6 view.addSubview(scrollView) // 2. قيود scrollView (ملء الشاشة بالكامل) NSLayoutConstraint.activate([ scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor), scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor), scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor), scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) // 3. إنشاء contentView - حاوية لكل المحتوى let contentView = UIView() contentView.translatesAutoresizingMaskIntoConstraints = false contentView.backgroundColor = .white