פיתוח מערכת שיתוף והעברה מחדש באפליקציה ניידת
הלקוח מבקש כפתור "שיתוף", ואנחנו מבלים שבוע בניפוי באגים של push ו-deep link. מצב מוכר: באנדרואיד, התמונה לא נשלחת בגלל FileProvider; ב-iOS, Universal Links לא עובדים — הקישור פותח את Safari. לדוגמה, פרויקט רשת חברתית לצלמים דרש העברה מחדש של עבודות של אחרים לפיד ושליחת קישורים לאפליקציות מסרים. ב-iOS, Universal Links לא הוגדרו בגלל שגיאה ב-apple-app-site-association — הפתרון כלל בדיקת סוג MIME ומבנה JSON נכון. באנדרואיד — הגדרת intent-filter עבור App Links וגיבוי ל-Chrome. התוצאה — מערכת שלמה להעברה מחדש ושיתוף תוך 2-3 ימים מאפס. נכסה את שתי המשימות, נציג פתרונות עובדים, ונשווה בין הגישות.
העברה מחדש פנימית: איזה מודל נתונים לבחור?
שתי גישות:
- העתקת תוכן — פוסט חדש עם שדה
reposted_from_id. פשוט להצגה, אך כשהמקור נערך, ההעתקה הופכת למיושנת. - הפניה למקור — פוסט עם
repost_of_id, ללא העתקת גוף, נטען לפי בקשה. כשהמקור נמחק, ההעברה מחדש מציגה "המקור נמחק". גישה זו משמשת את Telegram ו-Twitter/X. היא מפחיתה כפילות נתונים פי 3 ומסתנכרנת אוטומטית עם המקור.
בפיד, ההעברה מחדש מוצגת ככרטיס מוטבע של המקור בתוך התא של המשתף.
// iOS — ячейка поста с вложенной карточкой
if let repostOf = post.repostOf {
// Рисуем RepostCardView внутри PostCell
let repostCard = RepostCardView(post: repostOf)
contentStack.addArrangedSubview(repostCard)
}הכרטיס הוא // iOS — ячейка поста с вложенной карточкой if let repostOf = post.repostOf { // Рисуем RepostCardView внутри PostCell let repostCard = RepostCardView(post: repostOf) contentStack.addArrangedSubview(repostCard) } עם פינות מעוגלות, קו UIView, אווטאר ושם המחבר של המקור. העברה מחדש של העברה מחדש מציגה רק רמת קינון אחת.
ב-Compose: CALayer.borderColor.
איך להימנע מהעברות מחדש כפולות?
טבלת if (post.repostOf != null) EmbeddedPostCard(post = post.repostOf) — משתמש יכול להעביר מחדש מקור רק פעם אחת. לאחר לחיצה, הכפתור מודגש, לחיצה נוספת מבטלת את ההעברה מחדש (un-repost). מונה reposts (user_id, original_post_id, UNIQUE) בטבלת המקור.
השוואת גישות להעברה מחדש
| מאפיין | העתקת תוכן | הפניה למקור |
|---|---|---|
| כפילות נתונים | כן | לא |
| סנכרון אוטומטי | לא | כן |
| התנהגות כשהמקור נמחק | הפוסט נשאר | מציג "המקור נמחק" |
| משמש את | לעיתים רחוקות | Telegram, Twitter/X |
למה שיתוף חיצוני קשה יותר ממה שזה נראה?
iOS
let items: [Any] = [postText, URL(string: deeplink)!]
let vc = UIActivityViewController(activityItems: items, applicationActivities: nil)
// На iPad нужен popoverPresentationController
vc.popoverPresentationController?.sourceView = shareButton
present(vc, animated: true)לתמונה — המרת UIView ל-UIImage דרך reposts_count. אנדרואיד
val intent = Intent(Intent.ACTION_SEND).apply {
type = "text/plain"
putExtra(Intent.EXTRA_TEXT, "$postText\n$deeplinkUrl")
}
startActivity(Intent.createChooser(intent, "Поделиться"))לתמונות — let items: [Any] = [postText, URL(string: deeplink)!] let vc = UIActivityViewController(activityItems: items, applicationActivities: nil) // На iPad нужен popoverPresentationController vc.popoverPresentationController?.sourceView = shareButton present(vc, animated: true) עם UIGraphicsImageRenderer ו-URI דרך val intent = Intent(Intent.ACTION_SEND).apply { type = "text/plain" putExtra(Intent.EXTRA_TEXT, "$postText\n$deeplinkUrl") } startActivity(Intent.createChooser(intent, "Поделиться")) . URI ישיר של Intent.ACTION_SEND לא עובד באנדרואיד 7+, רק type = "image/*".
Flutter
await Share.shareXFiles([XFile(imagePath)], text: '$postText\n$deeplinkUrl'); איך להגדיר Deep Links לשיתוף?
שיתוף חיצוני ללא deep link מאבד את מטרתו. הקישור חייב לפתוח פוסט ספציפי באפליקציה. ב-iOS — Universal Links (FileProvider בשרת + file://). באנדרואיד — App Links (content:// + await Share.shareXFiles([XFile(imagePath)], text: '$postText\n$deeplinkUrl'); ). אם האפליקציה לא מותקנת — גיבוי לגרסת האינטרנט. מידע נוסף על deep linking.
הנחיות סקירת App Store של Apple (סעיף 4.2) ו-Google Play Console דורשות יישום נכון של deep link כדי להימנע מדחייה.
השוואה: העברה מחדש פנימית מול שיתוף חיצוני
| היבט | העברה מחדש פנימית | שיתוף חיצוני |
|---|---|---|
| מטרה | פרסום בפיד האישי | שליחה לאפליקציה אחרת |
| Deep link | לא נדרש | חובה |
| מונה | כן, הגדלה/הקטנה | לא נדרש |
| iOS | Core Data + SwiftUI | UIActivityViewController |
| אנדרואיד | Room + Jetpack Compose | Intent.ACTION_SEND |
מה כלול בעבודה
- עיצוב מודל נתונים להעברה מחדש (סכמת DB, API).
- פיתוח כרטיס מוטבע לפיד (iOS/Android/Flutter).
- אינטגרציה עם מערכת השיתוף ו-deep linking.
- הגדרת התראות push להעברות מחדש.
- מסירת תיעוד וקוד מקור.
שלבי העבודה
- ניתוח — בחירת מודל הפניה למקור.
- עיצוב — סכמת DB, REST/GraphQL API.
- יישום — backend + ממשק משתמש.
- אינטגרציה — שיתוף חיצוני + deep links.
- בדיקות — ביטול העברה מחדש, מחיקת מקור, מקרי קצה.
- השקה — פרסום ב-App Store / Google Play.
השוואה: פיתוח מותאם אישית מול SDK מוכן
אם משתמשים ב-SDK מוכן (למשל, Branch.io), מקבלים התחלה מהירה אך הופכים לתלויים בספק חיצוני, מה שמגדיל עלויות רישוי וסיכוני חסימה. יישום מותאם אישית נותן שליטה מלאה וחוסך עד 50% בקנה מידה של מעל 10K משתמשים.
לוח זמנים ועלות
העברה מחדש פנימית עם ממשק — 1-2 ימים. שיתוף חיצוני עם deep link — עוד 1-2 ימים. מערכת מלאה עם שני המצבים — 2-3 ימים בפיתוח מקביל של פלטפורמות. העלות מחושבת באופן אישי — צרו קשר להערכה מדויקת.
טעויות נפוצות ביישום
- חוסר טיפול במחיקת מקור — ההעברה מחדש מפנה לאובייקט לא קיים.
- התעלמות מ-
apple-app-site-associationבאנדרואיד — קריסה באנדרואיד 7+ בעת שיתוף תמונות. - שכחת
NSUserActivityTypesב-iPad — האפליקציה קופאת.
הניסיון של הצוות שלנו — 10+ שנים בפיתוח מובייל, מעל 50 פרויקטים מיושמים. אחריות איכות לכל שלב. הזמינו פיתוח מערכת העברה מחדש עוד היום — צרו קשר לייעוץ!







