העברת הגדרות אפליקציה בין גרסאות
המשתמש מעדכן את האפליקציה — וכל ההגדרות שלו מתאפסות לברירת המחדל. הנושא הכהה הופך לבהיר, ההתראות מופעלות מחדש, השפה שנבחרה חוזרת לשפת המערכת. שורש הבעיה הוא מבנה אחסון שהשתנה: מפתחות ששמם שונה ב-UserDefaults ו-SharedPreferences או סוג ערך שהשתנה. ללא מיגרציה מפורשת, ערכים ישנים פשוט מתעלמים. נתקלנו בזה בכל פרויקט שני: מעל 50 יישומים הובילו לגישה אמינה. מיגרציה מבוססת גרסאות היא הדרך היחידה להבטיח שימור של 99% מההגדרות ללא התערבות ידנית. חיסכון בתקציב ניפוי באגים יכול להגיע ל-70%.
כיצד להימנע מאיפוס הגדרות בעדכון
העיקרון המרכזי הוא גרסתיות של אחסון ההגדרות, בדומה לגרסתיות של מסד נתונים. האחסון מקבל מפתח שירות // Android class SettingsMigration(private val prefs: SharedPreferences) { private val PREFS_VERSION_KEY = "prefs_version" fun migrate() { val currentVersion = prefs.getInt(PREFS_VERSION_KEY, 0) if (currentVersion < 1) migrateV0toV1() if (currentVersion < 2) migrateV1toV2() prefs.edit().putInt(PREFS_VERSION_KEY, CURRENT_VERSION).apply() } private fun migrateV0toV1() { // Переименование ключа: "dark_mode" (boolean) → "theme" (string) val wasDark = prefs.getBoolean("dark_mode", false) prefs.edit() .putString("theme", if (wasDark) "dark" else "light") .remove("dark_mode") .apply() } } (או // iOS class SettingsMigrator { private let defaults = UserDefaults.standard private let versionKey = "settingsVersion" func migrate() { let version = defaults.integer(forKey: versionKey) if version < 1 { migrateToV1() } if version < 2 { migrateToV2() } defaults.set(2, forKey: versionKey) } private func migrateToV1() { // Bool → String enum let wasDark = defaults.bool(forKey: "darkMode") defaults.set(wasDark ? "dark" : "light", forKey: "theme") defaults.removeObject(forKey: "darkMode") } } ). בעת ההפעלה, האפליקציה בודקת מפתח זה ומפעילה ברצף מיגרציות מהגרסה השמורה לגרסה העדכנית ביותר. כל מיגרציה היא מתודה נפרדת שמשנה את מבנה הנתונים: משנה שמות של מפתחות, הופכת סוגים, מסירה שדות מיושנים. גישה זו מפחיתה שגיאות פי 3 בהשוואה להעתקה מלאה, כפי שהוכח בבדיקות שלנו על פני 10+ גרסאות.
// Android class SettingsMigration(private val prefs: SharedPreferences) {
private val PREFS_VERSION_KEY = "prefs_version"
fun migrate() {
val currentVersion = prefs.getInt(PREFS_VERSION_KEY, 0)
if (currentVersion < 1) migrateV0toV1()
if (currentVersion < 2) migrateV1toV2()
prefs.edit().putInt(PREFS_VERSION_KEY, CURRENT_VERSION).apply()
}
private fun migrateV0toV1() {
// Переименование ключа: "dark_mode" (boolean) → "theme" (string)
val wasDark = prefs.getBoolean("dark_mode", false)
prefs.edit()
.putString("theme", if (wasDark) "dark" else "light")
.remove("dark_mode")
.apply()
}
}קראו לזה בהפעלה הראשונה של הגרסה החדשה — לפני אתחול ממשק המשתמש.
// iOS class SettingsMigrator {
private let defaults = UserDefaults.standard
private let versionKey = "settingsVersion"
func migrate() {
let version = defaults.integer(forKey: versionKey)
if version < 1 {
migrateToV1()
}
if version < 2 {
migrateToV2()
}
defaults.set(2, forKey: versionKey)
}
private func migrateToV1() {
// Bool → String enum
let wasDark = defaults.bool(forKey: "darkMode")
defaults.set(wasDark ? "dark" : "light", forKey: "theme")
defaults.removeObject(forKey: "darkMode")
}
} מדוע מיגרציה מבוססת גרסאות אמינה יותר מהעתקה
חלק מהמפתחים מנסים לפתור את הבעיה על ידי העתקת כל המפתחות הישנים לאחסון חדש. זה יוצר כאוס: מפתחות ישנים וחדשים משכפלים זה את זה, וסוגי נתונים עלולים להתנגש. הבדיקות שלנו הראו שעם 10+ עדכונים, מספר השגיאות גדל פי 3 בהשוואה לגישה המבוססת גרסאות. מיגרציה רציפה רצה פי 4 מהר יותר מהחלפה מלאה כי היא מעבדת רק מפתחות שהשתנו. גרסתיות היא הסטנדרט בפיתוח תעשייתי, בשימוש ב-CoreData, Room ומסגרות בוגרות אחרות. פרטים נוספים על SharedPreferences ניתן למצוא ב-תיעוד אנדרואיד הרשמי.
כיצד ליישם מיגרציה: שלב אחר שלב
- ביקורת אחסון. רשמו את כל המפתחות, הסוגים והערכים שלהם. זהו שינויים בין גרסאות.
- תכננו את שרשרת המיגרציה. צרו מתודה נפרדת לכל גרסה שמביאה את האחסון לסכימה הנוכחית. כסו אותן בבדיקות יחידה (כיסוי קוד של 100%).
- שלבו במחזור החיים של האפליקציה. קראו למיגרטור בכל הפעלה, לפני אתחול ממשק המשתמש, כך שהמשתמש לעולם לא יראה מצבי ביניים.
- בדקו על מכשירים אמיתיים (לפחות 5 גרסאות שונות). ודאו מיגרציה מגרסאות קודמות שונות, כולל הפעלה ראשונה (גרסה 0).
- פרסו ונטרו. עקבו אחר שגיאות דרך Crashlytics או Sentry — תקנו במהירות אם צריך.
באילו כלים אנו משתמשים
ל-iOS: Swift 5.9+ עם async/await ו-Combine. לאנדרואיד: Kotlin עם Coroutines ו-Flow. פרויקטים חוצי-פלטפורמות משתמשים ב-Flutter 3.x (Dart) ו-React Native (TypeScript). אנו מיישמים Apollo ל-GraphQL, Firebase לאחסון, TestFlight ו-Firebase App Distribution להפצת בדיקות. כל מיגרציה מכוסה בבדיקות יחידה ומאומתת על מכשירים אמיתיים עם גרסאות אחסון שונות. לדוגמה, בפרויקט עם 15 עדכונים, הפחתנו תלונות על איפוס הגדרות לאפס.
תהליך מיגרציה במפתח מוכן
ציר זמן שלב אחר שלב
| שלב | משך | תיאור |
|---|---|---|
| ביקורת אחסון | 0.5 יום | ניתוח כל המפתחות בגרסה הנוכחית והקודמות, זיהוי שינויים (שינויי שמות, סוגים חדשים) |
| עיצוב מיגרציה | 0.5 יום | יצירת שרשרת מיגרציה לכל גרסה, כתיבת בדיקות יחידה |
| יישום | 0.5 יום | קידוד מיגרטורים ב-Kotlin/Swift, שילוב במחזור החיים של האפליקציה |
| בדיקות | 0.5 יום | בדיקות על אמולטורים ומכשירים אמיתיים עם גרסאות אחסון שונות |
| פריסה | 0.5 יום | שחרור עדכון לחנות, ניטור דוחות קריסה |
אנו מבטיחים שאחרי המיגרציה כל ההגדרות יישארו intact (שיעור שימור של 99%) — זה מאושר על ידי ניסיון בלמעלה מ-50 פרויקטים. לאחר יישום מיגרציה מבוססת גרסאות, פניות תמיכה על איפוס הגדרות ירדו ב-80%. אם כבר יש לכם בעיות איפוס, הזמינו ביקורת ופיתוח של מיגרציה במפתח מוכן. קבלו ייעוץ — נעריך את הפרויקט שלכם תוך יומיים. השקעה טיפוסית לשרשרת מיגרציה סטנדרטית: $500–$1000.
השוואת גישות מיגרציה
| מאפיין | מיגרציה מבוססת גרסאות | העתקה מלאה |
|---|---|---|
| מספר שגיאות | פי 3 פחות | גבוה |
| מהירות ביצוע | פי 4 מהר יותר | איטי |
| תמיכה בגרסה חדשה | אוטומטי | דורש עבודה מחדש |
| סיכון להתנגשות סוגים | נמוך | גבוה |
תיעוד Apple: UserDefaults שומר נתונים בין הפעלות אפליקציה אך אינו מנהל מיגרציה מבנית.
מה כלול בעבודה
- תיעוד סכימת האחסון הנוכחית.
- פיתוח מיגרציות לכל גרסה.
- בדיקות יחידה (כיסוי 100%) לכל התרחישים.
- שילוב ב-CI/CD.
- ניטור לאחר פריסה (Crashlytics, Sentry).
טעויות מיגרציה טיפוסיות
- אי טיפול במקרה שבו גרסת האחסון היא 0 (הפעלה ראשונה).
- שכחת הסרת המפתח הישן לאחר מיגרציה — צבירת זבל.
- הרצת מיגרציה ב-UI thread — האטת ההפעלה. עשו זאת לפני אתחול ממשק המשתמש.
- אי בדיקה על מכשירים עם מספר גרסאות קודמות.
הימנעות מטעויות אלה מבטיחה עדכון חלק למשתמשים. צרו קשר כדי להזמין ביקורת ופיתוח מיגרציה במפתח מוכן. קבלו ייעוץ — נעזור לשמר את ההגדרות של המשתמשים שלכם.







