הסבת אפליקציות לאייפד
רוני רוזן |
אוג 9, 2011
אז סוף סוף קרה לכם מה שכל מפתח מקווה שיקרה לו: כתבתם אפליקציה לאייפון, העלתם אותה לחנות ומהר מאוד היא תפסה תאוצה. כמות האנשים שמורידים אותה רק הולכת וגדלה כל יום, בבלוגים מדברים עליה בלי סוף ובכל מקום שאתם נמצאים בו, אתם שומעים אנשים מדברים על האפליקציה ומשווים תוצאות. בקיצור, הכל מעולה. אבל אחרי שסיימתם לנוח על זרי הדפנה, אתם מתחילים לחשוב מה עכשיו. מה בעצם השלב הבא? שמעתם כבר מכמה אנשים שההמשך המתבקש הוא גרסה לאייפד. המשחק כל כך מהנה על המסך הקטן, אפשר רק לדמיין כמה הוא יהיה מהנה על מסך גדול יותר!
אז למרות שלא תכננתם את גרסת האייפד מראש כשהתחלתם לעבוד על האפליקציה, עדיין לא מאוחר מידי. יותר מזה, אם אתם כמוני ואחד הדברים שאתם יותר נהנים ממנו בתהליך הפיתוח הוא ההתעסקות עם ממשק המשתמש, התהליך הזה אפילו הולך להיות מהנה. אם לא, וממשק משתמש זה אחד הדברים שמרגישים לכם כמו מטלה מעיקה למימוש (אין מה להתבייש, חלק מהחברים הטובים ביותר שלי מרגישים ככה... :-)), גם אז המטלה אינה מאוד קשה. לפחות המעבר הבסיסי...
לא אתמקד במדריך זה במה נכון ומה לא נכון בהכנת גרסה לאייפד. בזה שהמסך יותר גדול, שאופן השימוש במכשיר הוא שונה, ושהמשתמש מצפה לקבל יותר יכולות מאשר היו לו בגרסת האייפון. כל הנושאים הללו מצריכים מדריך ייעודי. במקום זאת, אתמקד בפאן הטכני של המעבר. איך לוקחים פרויקט מוכן באייפון והופכים אותו לפרויקט אוניברסלי שיתאים את עצמו למכשיר עליו הוא רץ. מוכנים? קחו נשימה עמוקה, הנה אנחנו מתחילים.
על מנת להדגים את המעבר הבסיסי, אשתמש בפרויקט מאוד פשוט: יש בו תמונה, כתובית ותיבת טקסט והוא נראה בערך כך:

כל הלוגיקה מאחוריו כבר כתובה. הזנת טקסט בשדה מריצה איזשהו אלגוריתם מסובך שבעצם מנתח את התמונה, מזהה מהי ומדפיס את התוצאה בכתובית שנמצאת בתחתית המסך. גאוני לא? בקיצור, פשוט זרמו איתי בנושא הזה. הפואנטה היא שיש הרבה לוגיקה מאחורה שאני לא רוצה לשכתב אותה. כרגע, בשלב המעבר ההתחלתי, כל מה שאני רוצה זה שהגרסה לאייפד תתנהג בדיוק כמו הגרסה לאייפון - רק שתהיה מותאמת לגודל המסך של האייפד. דבר נוסף שחשוב לחשוב עליו בשלב הזה הוא שבזמן שלאפליקציית אייפון יש את הפריווילגיה לתמוך באוריאנטציה אחת בלבד של המכשיר, אפליקציית אייפד צריכה לתמוך בכל האורינטציות האפשריות (אלא אם כן יש לה סיבה ממש טובה שלא לעשות את זה). נדבר גם על זה בהמשך (בגלל זה לקחנו אפליקציה פשוטה... :-)).
שלב 1: הפיכת האפליקציה לאוניברסלית:
בהנחה הסבירה שאתם משתמשים ב-XCode4, לכו לסיכום מאפייני הפרויקט שלכם (על ידי לחיצה על קובץ הפרויקט בצד השמאלי העליון של סרגל רשימת הקבצים). תחת סעיף iOS Application Target, בו אתם מגדירים את הגרסה הנוכחית של האפליקציה, את ה-Identifier שלה ואת גרסת מערכת ההפעלה המינימלית הדרושה להרצתה, תמצאו גם שדה בשם: Devices בו הערך הבחור הינו iPhone. החליפו את הערך בשדה הזה ל-Universal.
כעת, אם נריץ פשוט את האפליקציה שלנו על האייפד, נקבל את אותו המסך שראינו קודם לכן, רק שהפעם, במקום למקם את עצמו במרכז המסך של האייפד (ברזולוציה המתאימה לאייפון), נוכל לראות אותו על כל המסך. במקרה שלנו, זה ייראה כך:

כמובן שזה לא מה שאנחנו רוצים. האריה קצת מעוות, תיבת הטקסט שמעליו לא ממורכזת והכתובית מסתירה אותו. אז בואו נתקן את זה.
שלב 2: שינוי הגדרות ה-autoresize:
נניח שישבנו עם המעצב / מומחה חוויית המשתמש שלנו והחלטנו יחד איתו שמה שאנחנו רוצים לעשות הוא שהאריה יוצג במרכז המסך בגודל זהה לגודל שלו על האייפון, שהכתובית למטה תתרחב לכל רוחב המסך ושתיבת הטקסט תשאר באותו גודל אבל תהיה ממורכזת. נתאים לכל אחד מהאלמנטים את ההגדרה המתאימה עבורו.
נתחיל עם תמונת האריה: מה שאנחנו רוצים שיקרה, זה שהאריה ישמור על הגדולה נוכחי שלו למרות שגודל המסך והפרופורציה שלו השתנו. כל זאת מבלי לעוות את הפרופורציות שלו (כפי שקרה לנו בתמונה הקודמת). על מנת להגדיר זאת נבחר ב-Interface Builder באובייקט שמעניין אותנו (במקרה הזה, התמונה של האריה) ונפתח את ה-Size Inspector שלו. נראה שם את הציור הזה:

מה שהציור הזה אומר לנו, הוא שבמידה ומשנים את הגודל של ה-view שמכיל את האובייקט הזה (מה שקרה במקרה שלנו מאחר והחלפנו את הגודל של המסך מרזולוציה של אייפון לרזולוציה של אייפד), התמונה תשמור על אותו המרחק מהקצה העליון של המסך ועל אותו המרחק מהקצה השמאלי של המסך ולא תשנה את גודלה. כך ניתן לראות למשל, שהכתובית ושדה הטקסט פשוט נשארו באותו המקום על המסך כאילו היו מוצגות על האייפון, למרות שכעת הן מסתירות את תמונת האריה.
על מנת לתקן את המצב הזה, עלינו להתאים את ההגדרות בשדה הזה להגדרות עליהן דיברנו: תמונת האריב בעצם לא צריכה לשמור על מרחק קבוע מאף אחד מהקצוות של המסך. בנוסף, היא לא צריכה להרשות אף שינוי בגודל שלה, באף אחד מהצירים. כך זה נראה לאחר ביצוע השינוי:

כעת, אם נריץ את האפליקציה, הפרופורציות של תמונת האריה כבר לא תהיינה מעוותות.
נעבור לטפל בכתובית. אמרנו שאנחנו רוצים שהיא תשנה את רוחבה כך שתתפוס את כל רוחב המסך, אך שעדיין תהיה באותו הגובה ובאותו מרחק מגבולו התחתון של המסך. כך זה נראה בתמונה:

כעת, האובייקט האחרון שנותר לנו לטפל בו הוא תיבת הטקסט. במקרה של תיבת הטקסט, אנחנו רוצים שהיא תשמור על אותו הגודל אך באותו זמן גם תהיה ממורכזת במסך על פי גודלו החדש. כלומר, הדבר היחיד שאנחנו צריכים זה שהמרחק שלה מהגבול העליון של המסך יהיה זהה למה שהוא עכשיו. כן, כמו שבטח כבר ניחשתם, זה נראה כך:

עכשיו, אם נריץ את האפליקציה, זה מה שנקבל:

יותר מזה, אם הגדרנו את כל ה-autoresizing של כל האובייקטים כמו שצריך, האפליקציה תראה טוב (או לפחות טוב כמו שהיא נראתה במקור) גם במצב landscape באייפון ו/או באייפד:

כמובן שכל הדברים הללו רלוונטיים גם כאשר אנחנו פשוט מכינים אפליקציה לאייפון בלבד שתומכת במספר אוריאנטציות אך מאחר והרבה יותר מקובל לא לתמוך באורינטציות השונות כאשר אנו כותבים אפליקציות לאייפון בלבד, הרבה פעמים אנחנו יכולים להתקל בנושא הזה רק בעת המעבר לאייפד.
יכול להיות שכל הנושא של מה להגדיר ב-autorisizing ואיך נראה לכם במבט ראשון קצת מבלבל אך אחרי שמשחקים עם זה קצת ובמיוחד אם נעזרים באנימציה הנחמדה שמופיעה מצידו הימני של אזור ההגדרות הזה, כל העניין נהיה הרבה יותר אינטאטיבי ואפילו נחמד.
אז קיבלתם אפליקציה שיודעת להתאים את התצוגה שלה בצורה נכונה למסך הגדול של האייפד. הצעד הראשון מאחורינו, אבל סביר להניח שאתם לא רוצים פשוט גרסה מוגדלת של אפליקציית האייפון שלכם. יכול להיות שאתם רוצים להוסיף יכולות, אולי אתם פשוט רוצים לשנות את הממשק כך שיציע את אותה היכולת אבל בתצוגה המותאמת לאייפד. אולי אתם פשוט רוצים שבאייפד הרקע של הכתובית התחתונה יהיה כחול במקום שחור. אם לפחות אחד מהדברים הללו רלוונטי עבורכם, המשיכו לקרוא.
שלב 3: הוספת תנאים בהתאם לפלטפורמה:
בכל מקום בקוד בו אתם רוצים להגביל לוגיקה מסויימת כך שתרוץ רק על אחד מסוגי המכשירים ולא על כולם, עליכם פשוט להוסיף את התנאי הזה:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
כך למשל, אם אנחנו רוצים להוסיף כתובית שתופיע רק באייפד או אם אנחנו רוצים שלוגיקה מסויימת שהוספנו תרוץ רק על האייפד, נוסיף את התנאי הזה ובתוכו נכתוב את כל הדברים הרלוונטיים. ניתן, כמובן, להשתמש גם בכיוון ההפוך, במידה ואנחנו רוצים שלוגיקה מסויימת תרוץ רק על האייפון:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
דוגמא טובה לשימוש בלוגיקה הזו גם במידה ואתם לא מוסיפים בשלב הזה יכולות חדשות לגרסת האייפד של האפליקציה שלכם, היא שימוש ב-Picker-ים. אם למשל, בגרסת האייפון של האפליקציה היה שדה טקסט, שבלחיצה עליו היה עולה datePicker מתחתית המסך שמאפשר למשתמש לבחור תאריך ומזין את התאריך הנבחר בשדה. בגרסת האייפד, לא נרצה ש-datePicker ייעלה מתחתית המסך. זה יכול להראות לא טוב. מה שכנראה נבחר לעשות במצב הזה זה להציג את ה-datePicker ב-PopOverViewController שמצביע ישירות על השדה הרלוונטי. במצב הזה נשתמש בתנאי המתואר כאן.
שלב 4: קבצי xib נפרדים:
אם קובץ ה-xib שלכם קצת יותר מורכב מזה שתיארתי כאן, או אם אתם רוצים שממשק המשתמש ייראה שונה לגמרי בשני המכשירים, תוכלו להכין קובץ xib ייעודי שמתאים לכל אחד מהמכשירים: אחד לאייפון ואחד לאייפד. בעת טעינת ה-view המתאים, תצטרכו לדאוג לטעון את קובץ ה-xib הרלוונטי למכשיר עליו האפליקציה שלכם רצה באותו רגע.
דרך אחת לבצע זאת, היא על ידי הוספת התנאי שתואר בשלב הקודם. פשוט לטעון קובץ xib מסויים אם התנאים מתקיים וקובץ xib אחר אם התנאי לא מתקיים. את ה-IBOutlet-ים שלכם, אגב, אתם דואגים לחבר לאובייקטים המתאימים בכל אחד מקבצי ה-xib. הרי גם ככה רק אחד מהם ייטען.
דרך נוספת לבצע זאת, היא לדאוג לקרוא לקובץ ה-xib של האייפד עם הסיומת iPad~. כך, אם בקוד שלכם אתם טוענים את קובץ ה-xib בשם MyScreen.xib למשל, המכשיר יידע להריץ את הקובץ המתאים לו: אם האפליקציה רצה כרגע על אייפון, ייטען הקובץ MyScreen.xib. אחרת, ייטען הקובץ MyScreen~iPad.xib, במידה והוא קיים כמובן.
כלומר, במידה ויש לכם בפרויקט שני קבצי xib, אחד בשם myNib והשני בשם myNib~iPad, הרצת השורה הבאה תבצע טעינה של הקובץ הנכון בהתאם למכשיר עליו האפליקציה רצה באותו רגע:
UIViewController *vc = [[UIViewController alloc] initWithNibName:@"myNib" inBundle:nil];
התוספת הזו מאוד נוחה מאחר והיא מאפשרת לכם להוסיף xib-ים ייעודים לאייפד מבלי לשנות קוד טעינה קיים. חשוב לציין רק שהיא נתמכת החל מגרסה 4.0 ומעלה. כלומר, לא תוכלו להשתמש בה בקיצור הזה במידה ואתם רוצים שהאפליקציה שלכם תרוץ גם על אייפדים שמריצים את גרסה 3.2. חשוב לציין גם שהיכולת תומכת גם בסוגי קבצים אחרים. כלומר, אם יש לכם תמונה בשם myImg.png בפרויקט, תוכלו להוסיף תמונה בשם myImg~iPad.png ברזולוציה המתאימה והאפליקציה תדע להשתמש בתמונה הרלוונטית עבורה, בהתאם למכשיר עליו היא רצה באותו רגע.
שלב 5: קובץ Xib ראשי:
במידה ואתם רוצים להוסיף קובץ xib ראשי ייעודי לגרסת האייפד של האפליקציה שלכם, ניתן לבצע זאת בקלות על ידי הוספת קובץ xib מתאים לפרויקט, והוספת הערך Main nib file base name (iPad) לקובץ ה-info.plist של הפרויקט. הערך של המפתח הזה יהיה שם קובץ ה-xib החדש שיצרתם במיוחד עבור האייפד.
שלב 6: The Extra Mile:
זהו, האפליקציה שלכם נראת אחלה על האייפד. עכשיו הגיע הזמן להשקיע קצת (או אפילו הרבה) זמן ומחשבה באיך להפוך את אפליקציית האייפון המוגדלת שלכם לאפליקציית אייפד אמיתית ומוצלחת. יש הרבה דברים שונים בין שתי הפלטפורמות. אסור לנו להתייחס לאייפד כאל אייפון עם מסך גדול. האייפד מאפשר לנו לבצע פעילות שלא נראות לנו הגיוניות או נוחות לביצוע על גבי המסך הקטן של האייפון. הגרסה האייפדית יכולה לאפשר לנו לתת למשתמשים שלנו יותר יכולות. היא יכולה (וצריכה) לשנות דברים בממשק כך שיתאימו לאייפד. לדוגמא: בזמן שבאייפון אנחנו מרבים להשתמש במעברים בין מסכים שלמים, באייפד הדבר הרבה (הרבה) פחות מומלץ. אין לנו צורך בזה. יש לנו הרבה מקום, אנחנו יכולים לחלק את המסך לכמה חלקים ולבצע מעברים רק של חלקים של המסך ובהתאם לשינויים הללו להחליף או לעדכן את התוכן בחלק הנותר. אנחנו לא רוצים לבלבל את המשתמש על ידי החלפת כל תוכן המסך הגדול (באייפון, בדרך כלל אין לנו ברירה). קחו בתור דוגמא את אפליקציית המייל על האייפון ועל האייפד.
הקפידו להשתמש גם באלמנטי ממשק משתמש ייעודיים לאייפד: UISplitViewController, UIPopOverViewControllers ודברים נוספים שהמשתמשים שלכם רגילים אליהם גם מאפליקציות אייפד אחרות. בקיצור, קחו את הבסיס הזה והמשיכו לבנות עליו על מנת לבנות אפליקציית אייפד ייעודית מושכת ומוצלחת ולא סתם אפליקציית אייפון מוגדלת.
המון בהצלחה ואני מקווה שתהנו מהתהליך...

Reader Comments