آيفونآيبودآبل

سلسلة دروس برمجة تطبيقات الآيفون (5)

آيفونآيبودآبل

سنتكلم في درس اليوم عن كيف نأخذ الـ Pixelsالموجودة في الشاشة لذا سنتكلم عن View,Text and Image, Drawing and (الكتابة والصور,الرسم والعرض).

في البداية سنتكلم عن الـ View المقصود بالـ UIView  هي المنطقة المستطيلة الموجودة في الشاشة والتي من خلالها سنضع مكونات الشاشة ونستقبل أحداث الشاشة كالمس وغيرها.  UIView هي جزء فرعي من UIResponder وهذه الـ class الأخيرة هي التي تهتم بأحداث الشاشة و تستقبلها.

كل الـ Views مرتبة بشكل هرمي بحيث أن لكل view هناك superview أساسية واحده ومن صفر إلى أكثر من الـ subviews الفرعية. نلاحظ أيضاً أن جميع الـ views موجودة في window وهي النافذة الأساسية وتسمى UIWindow. UIWindow في الواقع هي view وتقع في الرأس الهرمي للـ views.

لكل تطبيق من تطبيقات الآيفون هناك فقط UIWindow واحده وتحوي جميع الـ views  الباقية للتطبيق.

اذا أردنا أن نضيف للـ superview subviews فيمكن أن نعمل ذلك من خلال الـ interface builder (IB)  أو بشكل برمجي كما هو موضح في السطور التالية:

هنا نضيف subview للـ superview الأساسية //

– (void)addSubview:(UIView *)view ;

هنا نعمل على إزالة subview من الـ superview //

-(void)removeFromSuperview;

هذه سطور أخرى تعمل على إعادة التنظيم الهرمي للـ views :

– (void)insertSubview:(UIView *)view atIndex:(int)index;

– (void)insertSubview:(UIView *)view belowSubview:(UIView *)view;

– (void)insertSubview:(UIView *)view aboveSubview:(UIView *)view;

– (void)exchangeSubviewAtIndex:(int)index withSubviewAtIndex:(int)otherIndex;

جاء سؤال مالفرق بأن نعمل مثل هذه الأشياء برمجياً وبين أن نعملها عن طريق IB فكان الجواب:

أنه يعتمد على نوع البرنامج الذي تعمل على برمجته فإذا كان عدد subviews كبير فيفضل عملها بشكل برمجي لكن في حالة أغلب البرامج تعمل عن طريق IB. وأي شيء يمكن عمله عن طريق IB يمكن عمله بشكل برمجي.

الـ superviews تعمل retains للـsubviews التابعة لها وعندما نحذف superview ونريد أن نعيد استخدام subview أو نقلها إلى مكان آخر فلابد أن نعمل للـ subview retian قبل حذف superview.

ويمكن لأي  view أن تكون مخفيه لفترة:

theView.hidden = YES;

ولكن ستبقى موجودة في التنظيم الهرمي للـ views.

تراكيب الـ view

هناك ثلاث أشياء بالنسبة لتركيب الـ view

-CGPoint وهو مايحدد موقع الـ view بالنسبة للـ {x,y} قيمة الـ X وقيمة الـ Y.

-CGSize وهو مايحدد حجم الـ view الطول والعرض {width,height}.

-CGRect وهي ماتجمع بين حجم وموقع الـ {view {origin, size .

وجميع القيم الموجودة هنا هي floating.

هذه رسم توضحي للعلاقة بين التراكيب الثلاث السابقة:

وهذا جدول توضيحي للكود البرمجي لكل النقاط الثلاث مع مثال لكل منها:

كما رأينا لكل view يوجد موقع هذا الـview مايسمى Location وحجم الـ view وهو Size ويمكن لهاتين النقطتين تفسيران مختلفان فكما ذكرنا سابقاً أن لكل subview هناك superview ففي هذه الحالة يجب أن نعرف موقع وحجم view بالنسبة لنفسه بشكل  محلي local وموقع وحجم الـ view بالنسبة للـ superview. ففي الأولى سنستخدم مايسمى بالـ bounds وفي الثانية سنستخدم الـ frame.

هذا مثال لـ views اثنين الأول A  والثاني هو  B ويعتبر B جزء من الـ superview A.

السؤال هنا متى نستخدم الـ frame ومتى نستخدم الـ bounds ؟

في حالة أننا نعمل على الـ view فإننا نستخدم الـ frame أما في حالة أننا نعدل على الـ view أي مابداخل الـ view فإننا نستخدم الـ bounds أي من الداخل نستخدم bounds ومن الخارج نستخدم frame.

مثال اذا كنت أريد تعديل مكان view بالنسبة للـ superview فإننا نستخدم الـ frame أما في حالة استقبال أحداث الشاشة أو رسم المحتويات فإننا نستخدم الـ bounds.

مثل ماقلنا سابقاً بأننا نستطيع أن نبني الـ views من خلال IB وذلك أن النافذة الأساسية window هي عبارة عن view ويمكن وضع فيها أي view object  كالأزرة والكلام buttons and labels or texts  وغيرها. ويمكن أيضاً وضع view جديدة من خلال سحب UIView ووضعه في الـ window  كما هو موضح في الصور التالية:

ونستطيع من خلال الخصائص تغيير اسم الـ view من خلال اسم الـ class.

الطريقة الثانية والتي تكون بشكل برمجي أو مانسميه يدوي بحيث لا نستخدم الـ IB كما في السطور التالية:

CGRect frame = CGRectMake(0, 0, 200, 150);

UIView *myView = [[UIView alloc] initWithFrame:frame];

ولنضع في الحسبان أن UIView يمكن أن تكون label  أو button أو غيرها كما في المثال التالي:

CGRect frame = CGRectMake(20, 45, 140, 21);

UILabel *label = [[UILabel alloc] initWithFrame:frame];

وحتى نضيف هذا الـ view أو الـ label إلى الـ superview الرئيسية أو view التي ستحوي هذا الـ Object فعلينا كتابة هذه السطر:

[window addSubview:label];

ويمكن أن نعدل على خصائص الـ object view كإضافة نص أو تعديل النص كالتالي:

[label setText:@”Number of sides:”];

ولا ننسى أن نعمل release للهذا الـ Object لأنه عندما أضفناه للـ window فإنها عملت retain لهذا الـ Object فحتى لاندخل في مشاكل مع الذاكرة فعلينا تحريره:

[label release];

رسم الـ views

في حالة انه أريد رسم views مخصصة أي غير موجودة سأستخدم (void)drawRect:(CGRect)rect  ننتبه أنه في حاله أنني عملت هذه الدالة فإنني لا أناديها ستنادى بشكل تلقائي كما هي الـ main  الموجودة في الـ c++ .

لكن في حالة أنني أريد إعادة رسم الـ view بطريقة أخرى فإنني أنادي الدالة:

-(void)setNeedsDisplay;

بحيث أعدل على خصائص الـ view ثم أنادي الدالة السابقة كما المثال التالي:

– (void)setNumberOfSides:(int)sides {

numberOfSides = sides;

[polygonView setNeedsDisplay];}

في هذا المثال عدلنا على عدد أضلاع المضلع الذي سنرسمه ثم فقط نادينا الدالة setNeedsDisplay .

CoreGraphics

واختصارها CG وهي مكتبة الرسم للواجهة وهي ترسم في اتجاهين أي 2D وتحوي على:

–          محتوى الرسومات (graphics context)

–          التحولات (Transformations)

–          المسارات (Paths)

–          الألوان (Colors)

–          الخطوط (Fonts)

–          الطلاء (Painting operations)

ستكون جميع الرسومات موجودة في محتوى أي في graphic context وهذا المحتوى سيتكون بشكل تلقائي فدالته لا تحتاج إلى نداء فهي تنادى قبل مناداة drawRect.

ومن المعلوم أن مكتبة CG محاطة بمكتبة UIKit بحيث يمكن أن نجمع بين دوال هاتين المكتبتين. فـ UIColor وهي ماتعطي قيم للون  و UIFont وهي ماتعطي قيم للخط كلها تابعة للمكتبة UIKit ودمجنا مابينهم وبين CG في المثال التالي:

– (void)drawRect:(CGRect)rect {

CGRect bounds = [self bounds];

[[UIColor grayColor] set];

UIRectFill (bounds);

CGRect square = CGRectMake (10, 10, 50, 100);

[[UIColor redColor] set];

UIRectFill (square);

[[UIColor blackColor] set];

UIRectFrame (square);

}

وناتج هذا المثال هو هذا الشكل حيث لون الخلفية للمحتوى الأساسي هي الرمادي وللشكل المستطيل الأحمر:

رسم أكثر تعقيد (draw complex shapes)

في حالة الرسومات الأكثر تعقيد فيجب أن نعلم في أي graphic context  سنعمل وتعريف مسار الرسم path تحديد لون الشكل ولون الحدود وتكرار هذه العملية على حسب الحاجة لها.

فالـ path أو مسار الرسم يحتوي على خطوط ومنحينات وأقواس ومتسطيلات وغيرها. ويمر الـ path في مرحلتين مرحلة التعريف ومرحلة الرسم.

في حالة رسم الـ path فلدي طريقتين إما عن طريق استخدام الـ CGContext أو عن طريق CGPath  ففي الحالة الأولى نستخدمها في حالة الرسم المباشر أما في الحالة الثانية فهي فقط تضيف قيم إلى path object ولا ترسم إلا في حالة طلب منها الرسم.

هذا مثال توضحي لإستخدام CGContext في رسم مثلث:

– (void)drawRect:(CGRect)rect {

CGContextRef context = UIGraphicsGetCurrentContext();

[[UIColor grayColor] set];

UIRectFill ([self bounds]);

CGContextBeginPath (context);

CGContextMoveToPoint (context, 75, 10);

CGContextAddLineToPoint (context, 10, 150);

CGContextAddLineToPoint (context, 160, 150);

CGContextClosePath (context);

[[UIColor redColor] setFill];

[[UIColor blackColor] setStroke];

CGContextDrawPath (context, kCGPathFillStroke);}

وناتج هذا المثال مثلث أحمر:

الصور والكتابة (Images and Text)

UIkit هي المكتبة التي تقوم بإظهار الصور. في البداية عندما نريد إنشاء صورة بإستخدام UIImages فعلينا القيام بالخطوات التالية:

– إحضار الصورة إلى حزمة التطبيق  Application bundle وذلك بإستخدام [UIImage imageNamed:(NSString *)name] ويجب أن نضيف اليه صيغة الصورة.

– في حالة أن الصورة ملف موجود في القرص  فنقرأ ملف الصورة من القرص بإستخدام [UIImage initWithContentsOfFile:(NSString *)path]

– في حالة أن الصورة معلومات رسمها موجودة في الذاكرة [UIImage initWithData:(NSData *)data]

وبالنسبة للنصوص Text فيفضل استخدام UILabel.

انتهى الدرس هناك جزئيات لم اتطرق لها افضل شرحها مع الأمثلة التطبيقية ستكون أسهل في الفهم بإذن الله…

دمتم بود 🙂

الوسوم

6 آراء على “سلسلة دروس برمجة تطبيقات الآيفون (5)”

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *