יום רביעי, 22 באוקטובר 2014

כפתור שאינו מלבני, בצורה גנרית ויפה

האובייקט UIButton הוא מלבני בהגדרתו.


לעיתים עולה הצורך בצורה שאינה מלבנית במיוחד כאשר משתמשים ברקע לא שקוף

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

נפתור את העניין ב2 שלבים.

1. נצייר את הצורה הלא מלבנית, נניח לשם הפשטות אליפסה. באמצעות drawRect כמו שעשינו בדוגמא של ה EllipseLabel.

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

ואז נדרוס את המתודות הלרוונטיות מ UIControl על מנת לא לנטר נגיעות לא רלוונטיות.

פתרון זה הוא גנרי וניתן לשימוש חוזר, ועדיף בהרבה על פתרונות קלוקלים המדברים על לקבל ב IBAction גם את ה UIEvent ושם להתחיל לנתח איפה הייתה הנגיעה.

כיוון שפתרון זה מונע בכלל את הקריאה ל IBAction, וכמובן הוא גנרי.

נצא לדרך

קוד הציור ב Objective C



קוד הציור ב Swift



ועכשיו נגדיר את הפונקציה המחשבת האם נגיעה הינה בתוך הצורה הגאומטרית
נעזר בתשובה הנמצאת בקישור הבא:
http://math.stackexchange.com/questions/76457/check-if-a-point-is-within-an-ellipse


קוד הפונקציה ב Objective C



קוד הפונקציה ב Swift



ניגש לדריסה של המתודות הרלוונטיות מ UIControl

קוד הדריסה ב Objective C



קוד הדריסה ב Swift



זהו, בזו הסתיימה המלאכה, והמחלקה EllipseButton מוכנה לשימוש חוזר ככל שתצטרכו.

אתם יותר ממוזמנים להוריד את הפרוייקט המלא בשפה הרלוונטית ולנסות בעצמכם את הכפתור.

לחץ כאן להורדת הפרוייקט ב Swift

להתראות בפוסט הבא!

יום שלישי, 21 באוקטובר 2014

לייבל שאינו מלבני, בצורה גנרית ויפה

האובייקט UILabel הוא מלבני בהגדרתו.

לעיתים עולה הצורך בצורה שאינה מלבנית במיוחד כאשר משתמשים ברקע לא שקוף

ישנו פתרון לשים תמונת רקע, אני אישית נרתע מהפתרון הזה מ2 סיבות עיקריות

1. תמונה צורכת לא מעט זיכרון ומוסיפה משקל לאפליקציה.
2. זה לא פתרון גנרי הניתן לשימוש חוזר.

אשר על כן, אני מעדיף פתרון באמצעות ציור.

לשם הפשטות, נגדיר שהצורה המבוקשת היא אליפסה (עיגול הוא מקרה פרטי של אליפסה למקרה הצורך).

הפתרון יהיה באמצעות שימוש ב drawRect.
שימו לב, שהקריאה ל super תעשה בסוף קוד הציור על מנת שציור הטקסט יבוא מעל ציור הרקע.

וניגש למימושים.


Objective C


Swift



ולתוצאה הסופית




זה כמובן הפתרון המינימאלי

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

ניתן לחשוב אולי לצייר את האליפסה על 95% מהשטוח על מנת לשמור על קצוות יפים, ועוד...

וכמובן כדאי ליישר את הטקסט לאמצע.


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



להתראות במדריך הבא!

יום שישי, 17 באוקטובר 2014

עבודה עם xib כ reuse view

לכאורה ניתן היה לחשוב כי xib (קרי:  nib) זה משהו ששייך לעולם עתיק קדם הסטוריבורד
אולי גם נחלתם של טבלאות עתיקות או מתוחכמות.

אמת, בעבר השימוש העיקרי ב xib היה יצירת ממשק משתמש עבור UIViewController
וכיום (החל מ iOS 5) אנו משתמשים ב storyboard.

אבל עדיין שימוש ב xib יכול לפתור 2 אתגרים עיקריים.

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

המקרה השני, שעליו נדבר בפוסט זה, שימוש ב UI אשר נדרש במספר מסכים ושמימושו יכול להעיק על ה ViewController
וכמובן, לכתוב אותו כ reuse יהיה דבר טוב ושימושי.

ניתן דוגמא:

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

אפשר גם להוסיף כל מיני דברים כמו הופעה באנימציה ושאר ירקות.

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

פה למשל, שימוש ב xib יהיה מתבקש.

נראה דוגמא למסך ההרשמה


קונספט:


תהיה מחלקת Controller שתקרא CutsomPickerController שתנהל את ה UI של הבחירה, אשר יטען מתוך קובץ xib, כך שבצורה נוחה יהיה אפשר להגדיר את ה UI.
המחלקה תאתחל את הממשק עם ארגומנט מסוג enum שיקרא CustomPickerControllerType שיקבע לה מה סוג ההצגה הנוכחי.

כמו כן יהיה פרוטוקול שיקרא CustomPickerControllerDelegate שיידע את המאזין (סביר להניח שיהיה זה ה ViewController) על אירועים שקרו כמו שינוי ערך, בחירה וביטול.

הViewController גם יחזיק את הקצאת הזיכרון של ה CustomPickerController.

נעבור למימוש:


צעד ראשון,ניצור את הפרוטוקול CustomPickerControllerDelegate

Objective C
















Swift



צעד שני, ניצור את הenum בשם CustomPickerControllerType
Objective C



Swift





צעד שלישי, ניצור את המחלקה CustomPickerController עם מתודות חשובות הרלוונטיות לשינוי ערך, בחירה וביטול.
Objective C






Swift








צעד רביעי, בניית קובץ ה xib, חיבור קשרי ה IBAction וה IBOutlet

הקובץ מכיל 2 UIButton, וכן UIDatePicker ו UIPickerView, כאשר ה files owner הוא מהמחלקה CustomPickerController, והוא ה delegate וה data-source של ה UIPickerView



Objective C






Swift




צעד חמישי, סיום המימושים.
Objective C









Swift


צעד שישי, תפעול ה CustomPickerController מתוך ה ViewController.

Objective C

Swift








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



כמובן שכל החתיכות קוד הן חלקיות ביותר ולכן אני ממליץ בחום להוריד את הפרוייקט ולראות את הקוד במלואו

להלן זמינים הפרוייקטים להורדה



נהנתם? ספרו לחבריכם! לא נהנתם? ספרו לי במייל אשלח לכם קופון למסאז׳ במחיר מלא.

יום שלישי, 14 באוקטובר 2014

פתיחת אפליקציית waze מתוך אפליקציה קיימת

בפוסט זה נדון בפתיחת אפליקציית waze בפרט ובאפליקצייה אחרת בכלל מתוך האפליקציה שלנו.

קצת רקע והקדמה:

ניתן לבקש מהאפליקציה לפתוח אפליקציה אחרת הזמינה לפתיחה חיצונית.
על מנת להגדיר אפליקציה לפתיחה חיצונית, יש להגדיר URL Scheme (ב info.plist תחת URL Types, תחת המערך URL Schemes)
המחרוזת שאותה תגדירו, היא זו שתזהה את האפליקציה לפתיחה חיצונית
על כן נסו שמחרוזת הסכמה תהיה ייחודית.

נניח והגדרתם את הסכמה myApp אז ניתן לפתוח את האפליקציה באמצעות הנתיב

myApp://

וכן ניתן להעביר פרמטרים בצורה של GET למשל:
myApp://?key=value&number=5

את הקריאה הזו תוכלו לקבל במימוש המתודות הבאות ב AppDelegate

application:handleOpenURL:
או ב 
application:openURL:sourceApplication:annotation:
בארגומנט url.

אגב, שימו לב, למי מכם שהשתמש ב SDK של פייסבוק, שזה בדיוק מה שעשיתם.
אפליקציית הפייסבוק או הספארי אחרי התחברות של המשתמש פותחת את האפליקציה שלכם בעזרת הסכמה שהגדרתם
שהיא fb + facebookAppID , ואת התשובה מפייסבוק העברתם לSDK של פייסוק באמצעות קריאה ל FBAppCall

אל תאמינו לי, תעשו דיבאג ותראו בעצמכם.

וניגש לעניינים:

ישנן מספר אפליקציות שמאפשרות פתיחה חיצונית, ואף מפרסמות את העניין מכיון שהן מאמינות שיש להן ערך מוסף עבור אפליקציות אחרות.
למשל waze, מי עוד? אפליקציית הטלפון של אפל למשל.
ישנו אתר שמרכז סכמות רבות http://handleopenurl.com/

אם כן, בהינתן נקודה בה יש לנו CLLocation נתון, ונרצה לפתוח את ה waze על מנת לנווט לאותה קוארדינטה.
עלינו לפתוח url כדוגמת:
waze://?ll=37.331689,-122.030731&navigate=yes

בואו נראה מימוש שבו נבדוק אם waze מותקן, אם כן, נפתח 
אחרת, אתם תחליטו מה בא לכם לעשות (למשל להציג הודעת שגיאה למשתמש או מראש לא להציג את הכפתור)








Swift