├── .gitmodules ├── LTUpdate Demo ├── LTUpdate Demo │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Default.png │ ├── Default@2x.png │ ├── Default-568h@2x.png │ ├── LTAppDelegate.h │ ├── main.m │ ├── LTUpdate Demo-Prefix.pch │ ├── LTUpdate Demo-Info.plist │ └── LTAppDelegate.m ├── LTUpdate DemoTests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── LTUpdate_DemoTests.h │ ├── LTUpdate DemoTests-Info.plist │ └── LTUpdate_DemoTests.m ├── Screenshot_APP_STORE_ID.png ├── Screenshot_Multilingual.jpg ├── Screenshot_Notification.png └── LTUpdate Demo.xcodeproj │ ├── project.xcworkspace │ └── contents.xcworkspacedata │ └── project.pbxproj ├── LTUpdate ├── LTI18N │ ├── zh-Hans.lproj │ │ └── LTUpdate.strings │ ├── zh-Hant.lproj │ │ └── LTUpdate.strings │ ├── zh-Hant-TW.lproj │ │ └── LTUpdate.strings │ ├── ja.lproj │ │ └── LTUpdate.strings │ ├── ko.lproj │ │ └── LTUpdate.strings │ ├── ar.lproj │ │ └── LTUpdate.strings │ ├── da.lproj │ │ └── LTUpdate.strings │ ├── en.lproj │ │ └── LTUpdate.strings │ ├── ro.lproj │ │ └── LTUpdate.strings │ ├── ru.lproj │ │ └── LTUpdate.strings │ ├── es.lproj │ │ └── LTUpdate.strings │ ├── sv.lproj │ │ └── LTUpdate.strings │ ├── nl.lproj │ │ └── LTUpdate.strings │ ├── pt-BR.lproj │ │ └── LTUpdate.strings │ ├── th.lproj │ │ └── LTUpdate.strings │ ├── uk.lproj │ │ └── LTUpdate.strings │ ├── pl.lproj │ │ └── LTUpdate.strings │ ├── sk.lproj │ │ └── LTUpdate.strings │ ├── sl.lproj │ │ └── LTUpdate.strings │ ├── cs.lproj │ │ └── LTUpdate.strings │ ├── pt-PT.lproj │ │ └── LTUpdate.strings │ ├── tr.lproj │ │ └── LTUpdate.strings │ ├── it.lproj │ │ └── LTUpdate.strings │ ├── fr.lproj │ │ └── LTUpdate.strings │ └── de.lproj │ │ └── LTUpdate.strings ├── LTUpdate.h └── LTUpdate.m ├── LICENSE └── README.md /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "JSONKit"] 2 | path = JSONKit 3 | url = git@github.com:johnezang/JSONKit.git 4 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate DemoTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/LTUpdate/master/LTUpdate Demo/LTUpdate Demo/Default.png -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/LTUpdate/master/LTUpdate Demo/LTUpdate Demo/Default@2x.png -------------------------------------------------------------------------------- /LTUpdate Demo/Screenshot_APP_STORE_ID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/LTUpdate/master/LTUpdate Demo/Screenshot_APP_STORE_ID.png -------------------------------------------------------------------------------- /LTUpdate Demo/Screenshot_Multilingual.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/LTUpdate/master/LTUpdate Demo/Screenshot_Multilingual.jpg -------------------------------------------------------------------------------- /LTUpdate Demo/Screenshot_Notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/LTUpdate/master/LTUpdate Demo/Screenshot_Notification.png -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyric/LTUpdate/master/LTUpdate Demo/LTUpdate Demo/Default-568h@2x.png -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate DemoTests/LTUpdate_DemoTests.h: -------------------------------------------------------------------------------- 1 | // 2 | // LTUpdate_DemoTests.h 3 | // LTUpdate DemoTests 4 | // 5 | // Created by Lex on 18/2/13. 6 | // Copyright (c) 2013 Lex Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LTUpdate_DemoTests : SenTestCase 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /LTUpdate/LTI18N/zh-Hans.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "新的版本已经提供下载了!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ 已经提供下载。您现在的版本是 %3$@。您要现在下载(%4$@)它吗?"; 4 | 5 | "Update" = "更新"; 6 | 7 | "Skip This Version" = "跳过这个版本"; 8 | 9 | "Remind Me Later" = "以后再提醒我"; 10 | 11 | "Release Notes" = "更新信息"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/zh-Hant.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "新的版本已經提供下載了!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ 已經提供下載。您現在的版本是 %3$@。您要現在下載(%4$@)它嗎?"; 4 | 5 | "Update" = "更新"; 6 | 7 | "Skip This Version" = "跳過這個版本"; 8 | 9 | "Remind Me Later" = "以後再提醒我"; 10 | 11 | "Release Notes" = "更新信息"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/zh-Hant-TW.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "新的版本已經提供下載了!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ 已經提供下載。您現在的版本是 %3$@。您要現在下載(%4$@)它嗎?"; 4 | 5 | "Update" = "更新"; 6 | 7 | "Skip This Version" = "跳過這個版本"; 8 | 9 | "Remind Me Later" = "以後再提醒我"; 10 | 11 | "Release Notes" = "更新資訊"; -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/LTAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LTAppDelegate.h 3 | // LTUpdate Demo 4 | // 5 | // Created by Lex on 18/2/13. 6 | // Copyright (c) 2013 Lex Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface LTAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /LTUpdate/LTI18N/ja.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "新しいバージョンが入手できます!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ が入手できます(使用中のバージョンは %3$@ です)。今すぐダウンロードしますか(%4$@)?"; 4 | 5 | "Update" = "アップデート"; 6 | 7 | "Skip This Version" = "このバージョンはスキップ"; 8 | 9 | "Remind Me Later" = "後で通知"; 10 | 11 | "Release Notes" = "リリースノート"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/ko.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "새 버전을 사용할 수 있습니다!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ 사용할 수 있습니다. 당신은 %3$@ 수 있습니다. 당신은 지금 (%4$@)를 다운로드 하시겠습니까?"; 4 | 5 | "Update" = "새롭게하다"; 6 | 7 | "Skip This Version" = "이 버전 건너뛰기"; 8 | 9 | "Remind Me Later" = "나중에"; 10 | 11 | "Release Notes" = "배포 정보"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/ar.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "يتوفر إصدار جديد من تطبيق!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ متوفر الآن. لديك %3$@. ترغب تحميل (%4@) الآن؟"; 4 | 5 | "Update" = "Update"; 6 | 7 | "Skip This Version" = "تخطي هذا الإصدار"; 8 | 9 | "Remind Me Later" = "تذكيري لاحقًا"; 10 | 11 | "Release Notes" = "معلومات عن الإصدار:"; -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // LTUpdate Demo 4 | // 5 | // Created by Lex on 18/2/13. 6 | // Copyright (c) 2013 Lex Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "LTAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([LTAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LTUpdate/LTI18N/da.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "En ny version er tilgængelig!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ er nu tilgængelig - du har %3$@. Vil du hente den nu(%4$@)?"; 4 | 5 | "Update" = "Opdatering"; 6 | 7 | "Skip This Version" = "Skip denne version"; 8 | 9 | "Remind Me Later" = "Påmind mig senere"; 10 | 11 | "Release Notes" = "Udgivelsesnoter"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/en.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "A new version is available!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ is now available. You have %3$@. Would you like to download(%4$@) it now?"; 4 | 5 | "Update" = "Update"; 6 | 7 | "Skip This Version" = "Skip This Version"; 8 | 9 | "Remind Me Later" = "Remind Me Later"; 10 | 11 | "Release Notes" = "Release Notes"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/ro.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "O nouă versiune este disponibilă!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ este disponibilă—-tu ai %3$@. Doriți să o descărcați(%4$@) acum?"; 4 | 5 | "Update" = "Actualizare"; 6 | 7 | "Skip This Version" = "Sari peste"; 8 | 9 | "Remind Me Later" = "Amintește-mi mai târziu"; 10 | 11 | "Release Notes" = "Note de ediție"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/ru.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Имеется новая версия!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ теперь доступен – вы имеете %3$@. Хотите загрузить (%4$@) его сейчас?"; 4 | 5 | "Update" = "обновление"; 6 | 7 | "Skip This Version" = "Пропустить эту версию"; 8 | 9 | "Remind Me Later" = "Напоминать позже"; 10 | 11 | "Release Notes" = "Заметки о выпуске"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/es.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "¡Hay una nueva versión!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ está disponible (usted tiene la %3$@). ¿Desea descargarla ahora(%4$@)?"; 4 | 5 | "Update" = "Instalar"; 6 | 7 | "Skip This Version" = "No instalar esta versión"; 8 | 9 | "Remind Me Later" = "Recordármelo"; 10 | 11 | "Release Notes" = "Notas de la versión"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/sv.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "En ny version finns tillgänglig!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ är nu tillgänglig—du har %3$@. Vill du ladda(%4$@) ned nu?"; 4 | 5 | "Update" = "Uppdate"; 6 | 7 | "Skip This Version" = "Hoppa över denna version"; 8 | 9 | "Remind Me Later" = "Påminn mig senare"; 10 | 11 | "Release Notes" = "Versionsinformation"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/nl.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Een nieuwe versie is beschikbaar!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ is nu beschikbaar—u heeft %3$@. Wilt u het nu downloaden(%4$@)?"; 4 | 5 | "Update" = "Update"; 6 | 7 | "Skip This Version" = "Sla deze versie over"; 8 | 9 | "Remind Me Later" = "Herinner mij er later aan"; 10 | 11 | "Release Notes" = "Versiegegevens"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/pt-BR.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Uma nova versão está disponível!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ está disponível--sua versão é %3$@. Gostaria de baixá-lo agora(%4$@)?"; 4 | 5 | "Update" = "Atualização"; 6 | 7 | "Skip This Version" = "Pular Esta Versão"; 8 | 9 | "Remind Me Later" = "Mais Tarde"; 10 | 11 | "Release Notes" = "Sobre a atualização"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/th.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "เวอร์ชั่นใหม่ของพร้อมสำหรับการติดตั้งแล้ว"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ พร้อมให้ดาวน์โหลดแล้ว (คุณมีเวอร์ชั่น %3$@) ดาวน์โหลด(%4$@)หรือไม่"; 4 | 5 | "Update" = "อัพเดท"; 6 | 7 | "Skip This Version" = "ข้ามเวอร์ชั่นนี้"; 8 | 9 | "Remind Me Later" = "เตือนในภายหลัง"; 10 | 11 | "Release Notes" = "หมายเหตุการเผยแพร่"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/uk.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Нова версія готова до встановлення!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ доступна – ви маєте %3$@. Бажаєте завантажити(%4$@) її зараз?"; 4 | 5 | "Update" = "Oновлення"; 6 | 7 | "Skip This Version" = "Пропустити цю версію"; 8 | 9 | "Remind Me Later" = "Нагадати пізніше"; 10 | 11 | "Release Notes" = "Примітки про нову версію"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/pl.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Dostępna jest nowa wersja %@!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ jest już dostępny (aktualnie posiadasz %3$@). Chciałbyś go teraz pobrać(%4$@)?"; 4 | 5 | "Update" = "Zainstaluj"; 6 | 7 | "Skip This Version" = "Pomiń tę wersję"; 8 | 9 | "Remind Me Later" = "Przypomnij później"; 10 | 11 | "Release Notes" = "Szczegóły wydania"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/sk.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Nová verzia je k dispozícii!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ je teraz k dispozícii. Máte %3$@. Chceli by ste na stiahnutie (%4$@) to teraz?"; 4 | 5 | "Update" = "Update"; 6 | 7 | "Skip This Version" = "Vynechať túto verziu"; 8 | 9 | "Remind Me Later" = "Pripomenúť neskôr"; 10 | 11 | "Release Notes" = "Poznámky k vydaniu"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/sl.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Na voljo je nova verzija programa!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "Na voljo je %1$@ %2$@ — vi imate %3$@. Ga želite prenesti s spleta sedaj(%4$@)?"; 4 | 5 | "Update" = "Posodabljanje"; 6 | 7 | "Skip This Version" = "Preskoči to verzijo"; 8 | 9 | "Remind Me Later" = "Spomni me kasneje"; 10 | 11 | "Release Notes" = "Opombe ob izdaji"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/cs.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Je dostupná nová verze aplikace!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "Je k dispozici %1$@ %2$@ - máte %3$@. Přejete si nyní zkopírovat aktualizaci (%4$@)?"; 4 | 5 | "Update" = "Aktualizaci"; 6 | 7 | "Skip This Version" = "Přeskočit tuto verzi"; 8 | 9 | "Remind Me Later" = "Připomenout později"; 10 | 11 | "Release Notes" = "Poznámky k vydání"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/pt-PT.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Uma nova versão está dísponível!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "O %1$@ %2$@ está agora disponível e tem a versão %3$@. Gostaria de o transferir agora(%4$@)?"; 4 | 5 | "Update" = "Actualização"; 6 | 7 | "Skip This Version" = "Saltar esta versão"; 8 | 9 | "Remind Me Later" = "Lembrar mais tarde"; 10 | 11 | "Release Notes" = "Notas de lançamento"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/tr.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Uygulamasının yeni bir sürümü yüklemeye hazır!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ çıktı (Kullandığınız Sürüm: %3$@). Şimdi yeni sürümü indirmek(%4$@) ister misiniz?"; 4 | 5 | "Update" = "Güncellemeyi"; 6 | 7 | "Skip This Version" = "Bu sürümü geç"; 8 | 9 | "Remind Me Later" = "Tekrar Hatırlat"; 10 | 11 | "Release Notes" = "Sürüm Hakkında"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/it.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "E’ disponibile una nuova versione!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ è disponbile; disponi della versione %3$@. Desideri eseguire l’aggiornamento ora(%4$@)?"; 4 | 5 | "Update" = "Installa"; 6 | 7 | "Skip This Version" = "Ignora questa versione"; 8 | 9 | "Remind Me Later" = "Ricordamelo più tardi"; 10 | 11 | "Release Notes" = "Note di rilascio"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/fr.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Une nouvelle version est disponible !"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ est disponible ; vous utilisez la version %3$@. Voulez-vous le télécharger(%4$@) maintenant ?"; 4 | 5 | "Update" = "Mise à jour"; 6 | 7 | "Skip This Version" = "Ignorer cette version"; 8 | 9 | "Remind Me Later" = "Pas maintenant"; 10 | 11 | "Release Notes" = "Notes de version"; -------------------------------------------------------------------------------- /LTUpdate/LTI18N/de.lproj/LTUpdate.strings: -------------------------------------------------------------------------------- 1 | "A new version is available!" = "Eine neue Version ist verfügbar!"; 2 | 3 | "%@ %@ is now available. You have %@. Would you like to download(%@) it now?" = "%1$@ %2$@ ist verfügbar (Sie verwenden Version %3$@). Möchten Sie die neue Version jetzt herunterladen(%4$@)?"; 4 | 5 | "Update" = "Aktualisierung"; 6 | 7 | "Skip This Version" = "Diese Version überspringen"; 8 | 9 | "Remind Me Later" = "Später erinnern"; 10 | 11 | "Release Notes" = "Versionshinweise"; -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/LTUpdate Demo-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'LTUpdate Demo' target in the 'LTUpdate Demo' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_3_0 8 | #warning "This project uses features only available in iOS SDK 3.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | 15 | #if (defined __IPHONE_OS_VERSION_MIN_REQUIRED && \ 16 | __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0) 17 | #import "JSONKit.h" 18 | #endif 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate DemoTests/LTUpdate DemoTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.lextang.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 0.1 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (C) 2013 LexTang.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/LTUpdate Demo-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | APP_STORE_ID 6 | 361309726 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleDisplayName 10 | La vie 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIdentifier 14 | com.lextang.${PRODUCT_NAME:rfc1034identifier} 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleName 18 | ${PRODUCT_NAME} 19 | CFBundlePackageType 20 | APPL 21 | CFBundleShortVersionString 22 | 1.7.0 23 | CFBundleSignature 24 | ???? 25 | CFBundleVersion 26 | 1 27 | LSRequiresIPhoneOS 28 | 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate DemoTests/LTUpdate_DemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // LTUpdate_DemoTests.m 3 | // LTUpdate DemoTests 4 | // 5 | // Created by Lex on 18/2/13. 6 | // Copyright (c) 2013 Lex Tang. All rights reserved. 7 | // 8 | 9 | #import "LTUpdate_DemoTests.h" 10 | #import "LTUpdate.h" 11 | 12 | @implementation LTUpdate_DemoTests 13 | 14 | - (void)setUp { 15 | [super setUp]; 16 | STAssertFalse([kAppVersion() compare:@"0.0" options:NSNumericSearch] == NSOrderedSame, 17 | @"App version MUST be greater then zero."); 18 | 19 | STAssertNotNil(kAppName(), @"App display name should not be nil."); 20 | } 21 | 22 | - (void)tearDown { 23 | // Tear-down code here. 24 | 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testAppStoreID { 29 | long appStoreID = [[LTUpdate shared] appStoreID]; 30 | STAssertTrue(appStoreID - 361309726 == 0, @"AppStoreID must be fill in -Info.plist"); 31 | } 32 | 33 | - (void)testVersionSkip { 34 | [[LTUpdate shared] skipVersion:@"0.1"]; 35 | STAssertTrue([[LTUpdate shared] isVersionSkipped:@"0.1"], @"Version 0.1 must be skipped."); 36 | [[LTUpdate shared] clearSkippedVersion]; 37 | STAssertFalse([[LTUpdate shared] isVersionSkipped:@"0.1"], @"SkippedVersion must be cleared."); 38 | } 39 | 40 | - (void)testUpdateVersion { 41 | dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 42 | 43 | [[LTUpdate shared] update:LTUpdateHourly 44 | complete:^(BOOL isNewVersionAvailable, LTUpdateVersionDetails *versionDetails) { 45 | 46 | if (isNewVersionAvailable) { 47 | 48 | STAssertTrue([versionDetails.version compare:@"0.0" options:NSNumericSearch] == NSOrderedDescending, 49 | @"App Store version should be greater than zero."); 50 | STAssertNotNil(versionDetails.releaseNotes, @"Release notes should not be nil."); 51 | STAssertTrue(versionDetails.fileSizeBytes > 0, @"File size should be greater than zero."); 52 | 53 | NSString *readableFileSize = humanReadableFileSize(versionDetails.fileSizeBytes); 54 | STAssertTrue(readableFileSize && readableFileSize.length > 2, @"Human readable file size should not be empty."); 55 | STAssertTrue(versionDetails.releaseDate.timeIntervalSince1970 > 0, @"Release date should be valid."); 56 | 57 | } else { 58 | 59 | STAssertNil(versionDetails, @"Version details must be nil while there is no new version."); 60 | 61 | } 62 | 63 | dispatch_semaphore_signal(semaphore); 64 | }]; 65 | 66 | while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) 67 | [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 68 | beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; 69 | dispatch_release(semaphore); 70 | } 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo/LTAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // LTAppDelegate.m 3 | // LTUpdate Demo 4 | // 5 | // Created by Lex on 18/2/13. 6 | // Copyright (c) 2013 Lex Tang. All rights reserved. 7 | // 8 | 9 | #import "LTAppDelegate.h" 10 | #import "LTUpdate.h" 11 | //#import "MBAlertView.h" 12 | 13 | @implementation LTAppDelegate 14 | 15 | - (void)dealloc 16 | { 17 | [_window release]; 18 | [super dealloc]; 19 | } 20 | 21 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 22 | { 23 | self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; 24 | UIViewController *rootViewController = [[UIViewController alloc] init]; 25 | rootViewController.view.backgroundColor = [UIColor colorWithWhite:0.298 alpha:1.000]; 26 | self.window.rootViewController = rootViewController; 27 | [self.window makeKeyAndVisible]; 28 | return YES; 29 | } 30 | 31 | - (void)applicationDidBecomeActive:(UIApplication *)application 32 | { 33 | // [[LTUpdate shared] updateAndPush:LTUpdateDaily]; return; 34 | 35 | [[LTUpdate shared] update:LTUpdateHourly 36 | complete:^(BOOL isNewVersionAvailable, LTUpdateVersionDetails *versionDetails) { 37 | 38 | //*// [TIP] Remove the first slash to toggle block comments if you'd like to use MBAlertView. 39 | if (isNewVersionAvailable) { 40 | NSLog(@"New version %@ released on %@.", versionDetails.version, versionDetails.releaseDate); 41 | NSLog(@"The app is about %@", humanReadableFileSize(versionDetails.fileSizeBytes)); 42 | NSLog(@"Release notes:\n%@", versionDetails.releaseNotes); 43 | [[LTUpdate shared] alertLatestVersion:LTUpdateOption | LTUpdateSkip]; 44 | } else { 45 | NSLog(@"You App is up to date."); 46 | } 47 | /*/ 48 | if (isNewVersionAvailable) { 49 | NSString *text = [NSString stringWithFormat:@"%@\n\n%@", LTI18N(@"A new version is available!"), versionDetails.releaseNotes]; 50 | MBAlertView *alertView = [MBAlertView alertWithBody:text 51 | cancelTitle:LTI18N(@"Remind Me Later") cancelBlock:nil]; 52 | [alertView addButtonWithText:LTI18N(@"Update") type:MBAlertViewItemTypeDefault block:^{ 53 | [[LTUpdate shared] openAppStore]; 54 | }]; 55 | alertView.bodyFont = [UIFont systemFontOfSize:11]; 56 | [alertView addToDisplayQueue]; 57 | } else { 58 | NSLog(@"You App is up to date."); 59 | } 60 | //*/ 61 | }]; 62 | } 63 | 64 | - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification 65 | { 66 | // [[LTUpdate shared] reduceNotification:notification then:LTUpdateNotifyThenAlert]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /LTUpdate/LTUpdate.h: -------------------------------------------------------------------------------- 1 | // 2 | // LTUpdate.h 3 | // LTUpdate 4 | // 5 | // Created by Lex Tang on 18/2/13. 6 | // 7 | // The MIT License (MIT) 8 | // Copyright © 2013 Lex Tang, http://LexTang.com 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the “Software”), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | #import 30 | #import 31 | 32 | #ifndef lt_retain 33 | #if __has_feature(objc_arc) 34 | #define lt_retain self 35 | #define lt_dealloc self 36 | #define release self 37 | #define autorelease self 38 | #else 39 | #define lt_retain retain 40 | #define lt_dealloc dealloc 41 | #define __bridge 42 | #endif 43 | #endif 44 | 45 | #if (!__has_feature(objc_arc)) || \ 46 | (defined __IPHONE_OS_VERSION_MIN_REQUIRED && \ 47 | __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_5_0) 48 | #undef weak 49 | #define weak unsafe_unretained 50 | #undef __weak 51 | #define __weak __unsafe_unretained 52 | #endif 53 | 54 | 55 | static NSString *kAppVersion() { 56 | static NSString *appVersion; 57 | static dispatch_once_t versionToken; 58 | dispatch_once(&versionToken, ^{ 59 | appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"]; 60 | }); 61 | return appVersion; 62 | } 63 | 64 | static NSString *kAppName() { 65 | static NSString *appName; 66 | static dispatch_once_t nameToken; 67 | dispatch_once(&nameToken, ^{ 68 | appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"]; 69 | }); 70 | return appName; 71 | } 72 | 73 | static NSString *humanReadableFileSize(unsigned long long int size) { 74 | NSString *sizeTypeW = @"bytes"; 75 | float working = 0; 76 | 77 | if (size < 1) { 78 | return @"0KB"; 79 | } else { 80 | if (size > 1024) { 81 | working = size / 1024.; 82 | sizeTypeW = @"KB"; 83 | } 84 | if (working > 1024) { 85 | working = working / 1024.; 86 | sizeTypeW = @"MB"; 87 | } 88 | } 89 | return [NSString stringWithFormat:@"%.2f%@", working, sizeTypeW]; 90 | } 91 | 92 | static NSString *LTI18N(NSString *key) { 93 | NSString *localizedString = NSLocalizedStringFromTable(key, @"LTUpdate", nil); 94 | return localizedString ? localizedString : @""; 95 | } 96 | 97 | 98 | @interface LTUpdateVersionDetails : NSObject 99 | 100 | @property(nonatomic, strong) NSString *version; 101 | @property(nonatomic, strong) NSString *releaseNotes; 102 | @property(nonatomic, strong) NSDate *releaseDate; 103 | @property(nonatomic, assign) long long fileSizeBytes; 104 | 105 | @end 106 | 107 | 108 | typedef NS_ENUM(uint, LTUpdateOptions) 109 | { 110 | LTUpdateOption, 111 | LTUpdateForce, 112 | LTUpdateSkip 113 | }; 114 | 115 | typedef NS_ENUM(uint, LTUpdateNotifyActions) 116 | { 117 | LTUpdateNotifyOpenAppStore, 118 | LTUpdateNotifyThenAlert, 119 | LTUpdateNotifyDoNothing 120 | }; 121 | 122 | typedef NS_ENUM(uint, LTUpdatePeroid) 123 | { 124 | LTUpdateHourly, 125 | LTUpdateDaily, 126 | LTUpdateWeekly, 127 | LTUpdateMonthly 128 | }; 129 | 130 | #ifndef LTUpdateBlocks 131 | #define LTUpdateBlocks 132 | typedef void(^LTUpdateCallback)(BOOL isNewVersionAvailable, LTUpdateVersionDetails *versionDetails); 133 | #endif 134 | 135 | 136 | @interface LTUpdate : NSObject 137 | 138 | @property(nonatomic, strong) LTUpdateVersionDetails *latestVersion; 139 | @property(nonatomic, assign, readonly) long appStoreID; 140 | @property(nonatomic, strong) LTUpdateCallback completionBlock; 141 | 142 | + (id)shared; 143 | 144 | - (void)__attribute__((unused)) update; 145 | - (void)__attribute__((unused)) update:(LTUpdateCallback)callback; 146 | - (void)update:(LTUpdatePeroid)peroid complete:(LTUpdateCallback)callback; 147 | 148 | - (BOOL)isVersionSkipped:(NSString *)version; 149 | - (void)skipVersion:(NSString *)version; 150 | - (void)clearSkippedVersion; 151 | 152 | - (void)__attribute__((unused)) alertLatestVersion:(LTUpdateOptions)alertOptions; 153 | 154 | - (void)__attribute__((unused)) updateAndPush; 155 | - (void)updateAndPush:(LTUpdatePeroid)peroid; 156 | - (void)__attribute__((unused)) pushLatestVersion; 157 | - (void)pushLatestVersion:(UILocalNotification*)localNotification; 158 | - (void)__attribute__((unused)) reduceNotification:(UILocalNotification*)notification; 159 | - (void)reduceNotification:(UILocalNotification*)notification then:(LTUpdateNotifyActions)action; 160 | 161 | - (void)openAppStore; 162 | 163 | @end 164 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LTUpdate 2 | LeT's Update to the new version available in the AppStore! 3 | 4 | [使用方法-简体中文](https://github.com/lexrus/LTUpdate/wiki/LTUpdate-使用方法) 5 | 6 | ![Screenshot](https://raw.github.com/lexrus/LTUpdate/master/LTUpdate%20Demo/Screenshot_Multilingual.jpg) 7 | 8 | ## Features 9 | * Local Notifications — from 0.0.2. 10 | * Customizable callback. You can prompt the new version with your favorite view class. 11 | * Multilingual. 25 languages included in version 0.0.1. 12 | * Update period control. Daily/Weekly/Monthly 13 | * “Skip This Version” 14 | * Version details (release date, file size in bytes, release notes...) 15 | * ARC/MRC compatible 16 | * Block based interfaces 17 | * GCD 18 | 19 | ## Requirements 20 | LTUpdate requires iOS 4.3 or newer. 21 | 22 | It's compatible with both ARC and MRC. But MRC mode is not well tested yet. 23 | 24 | [JSONKit](https://github.com/johnezang/JSONKit) is required while you are building for iOS 4.3. 25 | 26 | 27 | ## Usage 28 | 29 | ### DnD or pod install 30 | - Download the zip file and unzip it. Drag & drop LTUpdate/LTUpdate folder to your project. 31 | - But I prefer [CocoaPods](https://github.com/CocoaPods/CocoaPods): ```pod 'LTUpdate', '~>0.0.2'``` 32 | 33 | ### Define the App ID 34 | - Add a NSNumber field to {{YourProjectName}}-Info.plist with key “APP_STORE_ID” and your App ID as value: 35 | ![Screenshot](https://raw.github.com/lexrus/LTUpdate/master/LTUpdate%20Demo/Screenshot_APP_STORE_ID.png) 36 | 37 | ### Import the header 38 | - After that, add ```#import "LTUpdate.h"``` to AppDelegate.m or {{YourProjectName}}-Prefix.pch. 39 | 40 | ### Prompt with UIAlertView 41 | - Invoke the update method in applicationDidBecomeActive: ```[[LTUpdate shared] update];``` 42 | LTUpdate will check new verison from iTunes API. And prompt the user to update if there is a new version available. 43 | 44 | ### Prompt with Notification 45 | Users may be disturbed by UIAlertView while they supposed to use the app. Some of them installed your app but never open it till the new version has been promoted. Notifications is a better choice. Here is the simple way: 46 | 47 | ``` 48 | - (void)applicationDidBecomeActive:(UIApplication *)application 49 | { 50 | [[LTUpdate shared] updateAndPush:LTUpdateDaily]; 51 | } 52 | 53 | - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification 54 | { 55 | [[LTUpdate shared] reduceNotification:notification then:LTUpdateNotifyThenAlert]; 56 | } 57 | ``` 58 | While your app become inactived, it would send a notification to notify the user to update. 59 | 60 | ![Screenshot](https://raw.github.com/lexrus/LTUpdate/master/LTUpdate%20Demo/Screenshot_Notification.png) 61 | 62 | If the user tap/swiped this notification, the action would be invoked. In this case, the app will show a alert to make confirm of update. Or it’s quite nifty to open AppStore directly with 63 | ```[[LTUpdate shared] reduceNotification:notification];``` 64 | 65 | ### Customize 66 | If you need more control: 67 | 68 | ``` 69 | [[LTUpdate shared] update:LTUpdateDaily 70 | complete:^(BOOL isNewVersionAvailable, LTUpdateVersionDetails *versionDetails) { 71 | 72 | if (isNewVersionAvailable) { 73 | NSLog(@"New version %@ published on %@.", versionDetails.version, versionDetails.releaseDate); 74 | NSLog(@"The app is about %@", humanReadableFileSize(versionDetails.fileSizeBytes)); 75 | NSLog(@"Release notes:\n%@", versionDetails.releaseNotes); 76 | // Your alert view here 77 | [[LTUpdate shared] alertLatestVersion:LTUpdateOption | LTUpdateSkip]; 78 | } else { 79 | NSLog(@"You App is up to date."); 80 | } 81 | 82 | }]; 83 | ``` 84 | 85 | Outputs: 86 | 87 | ``` 88 | > New version 1.7.1 published on 2010-04-01 08:36:57 +0000. 89 | > The app is about 245.31MB 90 | > Release notes: 91 | In this release Pages for iOS is updated for improved compatibility with Microsoft Word and Pages for Mac. 92 | ... 93 | Pages 1.7.1 resolves issues related to Accessibility settings. 94 | ``` 95 | 96 | A customized example shows you how to replace the alert view with other open source alternatives(MBAlertView for example): 97 | 98 | ``` 99 | NSString *text = [NSString stringWithFormat:@"%@\n\n%@", LTI18N(@"A new version is available!"), versionDetails.releaseNotes]; 100 | MBAlertView *alertView = [MBAlertView alertWithBody:text 101 | cancelTitle:LTI18N(@"Remind Me Later") cancelBlock:nil]; 102 | [alertView addButtonWithText:LTI18N(@"Update") type:MBAlertViewItemTypeDefault block:^{ 103 | [[LTUpdate shared] openAppStore]; 104 | }]; 105 | alertView.bodyFont = [UIFont systemFontOfSize:11]; 106 | [alertView addToDisplayQueue]; 107 | ``` 108 | 109 | ### Clear SkippedVersion in UserDefaults 110 | 111 | ```[[LTUpdate shared] clearSkippedVersion];``` 112 | 113 | ### Shortcuts 114 | 115 | * ```NSString *humanReadableFileSize(unsigned long long int size);``` formats file size to "123.45MB" style; 116 | * ```static NSString *kAppName();``` is the display name of current App; 117 | * ```static NSString *kAppVersion();``` the version of current App. 118 | * ```static NSString *LTI18N(NSString *key);``` return localized string in LTUpdate.strings. 119 | 120 | Learn more in [LTUpdate.h](https://github.com/lexrus/LTUpdate/blob/master/LTUpdate/LTUpdate.h). 121 | 122 | 123 | ## AppStore Submissions 124 | 125 | The AppStore reviewer will not see the alert. Because the submitted version is always greater than the online version in AppStore. 126 | 127 | 128 | ## Testing & Building the demo 129 | 130 | Testing coverage is about 70% exclude UI functions. 131 | 132 | Install [JSONKit](https://github.com/johnezang/JSONKit) before build. 133 | ``` 134 | git submodule init 135 | git submodule update 136 | ``` 137 | 138 | ## License 139 | This code is distributed under the terms and conditions of the MIT license. See LTUpdate.h for details. 140 | -------------------------------------------------------------------------------- /LTUpdate/LTUpdate.m: -------------------------------------------------------------------------------- 1 | // 2 | // LTUpdate.h 3 | // LTUpdate 4 | // 5 | // Created by Lex Tang on 18/2/13. 6 | // 7 | // The MIT License (MIT) 8 | // Copyright © 2013 Lex Tang, http://LexTang.com 9 | // 10 | // Permission is hereby granted, free of charge, to any person obtaining a copy 11 | // of this software and associated documentation files (the “Software”), to deal 12 | // in the Software without restriction, including without limitation the rights 13 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | // copies of the Software, and to permit persons to whom the Software is 15 | // furnished to do so, subject to the following conditions: 16 | // 17 | // The above copyright notice and this permission notice shall be included in 18 | // all copies or substantial portions of the Software. 19 | // 20 | // THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | // THE SOFTWARE. 27 | // 28 | 29 | #import "LTUpdate.h" 30 | 31 | #define kAppStoreFormat @"http://itunes.apple.com/app/id%ld" 32 | #define kiTunesAPILookUpFormat @"http://itunes.apple.com/lookup?id=%ld" 33 | // Alternative URL: 34 | // @define kiTunesLookUpFormat @"http://ax.itunes.apple.com/WebObjects/MZStoreServices.woa/wa/wsLookup?id=%ld" 35 | 36 | 37 | static int kHourlyDuration = 3600; 38 | static int kDailyDuration = 86400; 39 | static int kWeeklyDuration = 604800; 40 | static int kMonthlyDuration = 2592000; 41 | 42 | static dispatch_queue_t get_update_queue() { 43 | static dispatch_once_t updateQueueToken; 44 | static dispatch_queue_t _updateQueue; 45 | 46 | dispatch_once(&updateQueueToken, ^{ 47 | _updateQueue = dispatch_queue_create("com.lextang.update", NULL); 48 | }); 49 | return _updateQueue; 50 | }; 51 | 52 | NSDate *parseRFC3339Date(NSString *dateString) { 53 | NSDateFormatter *rfc3339TimestampFormatterWithTimeZone = [[NSDateFormatter alloc] init]; 54 | NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]; 55 | [rfc3339TimestampFormatterWithTimeZone setLocale:locale]; 56 | [rfc3339TimestampFormatterWithTimeZone setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZ"]; 57 | 58 | NSDate *theDate = nil; 59 | NSError *error = nil; 60 | if (![rfc3339TimestampFormatterWithTimeZone getObjectValue:&theDate forString:dateString range:nil error:&error]) { 61 | } 62 | 63 | [locale release]; 64 | locale = nil; 65 | [rfc3339TimestampFormatterWithTimeZone release]; 66 | rfc3339TimestampFormatterWithTimeZone = nil; 67 | return theDate; 68 | } 69 | 70 | @implementation LTUpdateVersionDetails 71 | 72 | - (id)copyWithZone:(NSZone *)zone 73 | { 74 | LTUpdateVersionDetails *copy = [[[self class] allocWithZone:zone] init]; 75 | copy.version = [[self.version copyWithZone:zone] autorelease]; 76 | copy.releaseNotes = [[self.releaseNotes copyWithZone:zone] autorelease]; 77 | copy.releaseDate = [[self.releaseDate copyWithZone:zone] autorelease]; 78 | copy.fileSizeBytes = self.fileSizeBytes; 79 | return copy; 80 | } 81 | 82 | @end 83 | 84 | 85 | @interface LTUpdate () 86 | 87 | @end 88 | 89 | 90 | @implementation LTUpdate 91 | 92 | @synthesize latestVersion = _latestVersion; 93 | @synthesize completionBlock = _completionBlock; 94 | 95 | static long _appStoreID; 96 | 97 | + (id)shared { 98 | static LTUpdate *instance; 99 | static dispatch_once_t onceToken; 100 | dispatch_once(&onceToken, ^{ 101 | instance = [[LTUpdate alloc] init]; 102 | _appStoreID = [[[NSBundle mainBundle] objectForInfoDictionaryKey:@"APP_STORE_ID"] longValue]; 103 | }); 104 | return instance; 105 | } 106 | 107 | - (long)appStoreID { 108 | return _appStoreID; 109 | } 110 | 111 | - (void)update { 112 | [self update:^(BOOL isNewVersionAvailable, LTUpdateVersionDetails *versionDetails) { 113 | if (isNewVersionAvailable) { 114 | [self alertLatestVersion:LTUpdateOption | LTUpdateSkip]; 115 | } 116 | }]; 117 | } 118 | 119 | - (void)update:(LTUpdateCallback)callback { 120 | [self update:LTUpdateDaily complete:callback]; 121 | } 122 | 123 | - (void)update:(LTUpdatePeroid)peroid complete:(LTUpdateCallback)callback { 124 | NSAssert(self.appStoreID > 0, 125 | @"Please add a Number field in {{}}-Info.plist named APP_STORE_ID and your App ID as value."); 126 | #pragma clang diagnostic push 127 | #pragma clang diagnostic ignored "-Warc-retain-cycles" 128 | if (callback) 129 | self.completionBlock = callback; 130 | #pragma clang diagnostic pop 131 | 132 | double lastUpdateInterval = [self lastUpdateInterval]; 133 | double timestamp = [[NSDate date] timeIntervalSince1970]; 134 | 135 | if ((peroid == LTUpdateHourly && timestamp - lastUpdateInterval < kHourlyDuration) || 136 | (peroid == LTUpdateDaily && timestamp - lastUpdateInterval < kDailyDuration) || 137 | (peroid == LTUpdateWeekly && timestamp - lastUpdateInterval < kWeeklyDuration) || 138 | (peroid == LTUpdateMonthly && timestamp - lastUpdateInterval < kMonthlyDuration)) { 139 | if (self.completionBlock) 140 | self.completionBlock(NO, nil); 141 | return; 142 | } 143 | 144 | __weak __typeof (&*self) weakSelf = self; 145 | dispatch_async(get_update_queue(), ^{ 146 | __strong __typeof (&*weakSelf) strongSelf = weakSelf; 147 | 148 | [strongSelf parseJSON:[strongSelf fetchJSON]]; 149 | 150 | if (!strongSelf.completionBlock) return; 151 | 152 | if ([strongSelf latestVersion]) { 153 | if (strongSelf.completionBlock) { 154 | dispatch_sync(dispatch_get_main_queue(), ^{ 155 | strongSelf.completionBlock(YES, [strongSelf latestVersion]); 156 | }); 157 | } 158 | } else { 159 | dispatch_sync(dispatch_get_main_queue(), ^{ 160 | strongSelf.completionBlock(NO, nil); 161 | }); 162 | } 163 | }); 164 | } 165 | 166 | #pragma mark - JSON 167 | 168 | - (NSData *)fetchJSON { 169 | NSString *urlString = [NSString stringWithFormat:kiTunesAPILookUpFormat, [self appStoreID]]; 170 | NSURL *url = [NSURL URLWithString:urlString]; 171 | NSURLRequest *request = [NSURLRequest requestWithURL:url 172 | cachePolicy:NSURLRequestReloadRevalidatingCacheData 173 | timeoutInterval:30]; 174 | NSError *error = nil; 175 | NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:NULL error:&error]; 176 | if (!error) { 177 | [self setLastUpdateInterval]; 178 | return responseData; 179 | } 180 | return nil; 181 | } 182 | 183 | - (id)decodeJSON:(NSData *)data { 184 | if (!data) return nil; 185 | id _targetClass = data; 186 | SEL _targetSelector = NSSelectorFromString(@"objectFromJSONDataWithParseOptions:error"); 187 | BOOL hasJSONKit = YES; 188 | 189 | if (!(_targetSelector && [data respondsToSelector:_targetSelector])) { 190 | _targetSelector = NSSelectorFromString(@"JSONObjectWithData:options:error:"); 191 | _targetClass = NSClassFromString(@"NSJSONSerialization"); 192 | hasJSONKit = NO; 193 | if (!_targetClass) return nil; 194 | } 195 | 196 | NSInvocation *invocation = [NSInvocation 197 | invocationWithMethodSignature:[_targetClass methodSignatureForSelector:_targetSelector]]; 198 | invocation.target = _targetClass; 199 | invocation.selector = _targetSelector; 200 | 201 | if (!hasJSONKit) 202 | [invocation setArgument:&data atIndex:2]; 203 | NSUInteger optionFlags = 0; 204 | [invocation setArgument:&optionFlags atIndex:hasJSONKit ? 2 : 3]; 205 | // NSError *error = nil; 206 | // [invocation setArgument:&error atIndex:hasJSONKit ? 3 : 4]; 207 | 208 | [invocation invoke]; 209 | __unsafe_unretained id JSON = nil; 210 | [invocation getReturnValue:&JSON]; 211 | return JSON; 212 | } 213 | 214 | - (void)parseJSON:(NSData *)jsonData { 215 | id json = [self decodeJSON:jsonData]; 216 | if (json && [json isKindOfClass:[NSDictionary class]]) { 217 | NSArray *results = [json objectForKey:@"results"]; 218 | if (results && [results isKindOfClass:[NSArray class]] && [results count] > 0) { 219 | NSDictionary *versionDetail = [results[0] copy]; 220 | if (versionDetail && [versionDetail isKindOfClass:[NSDictionary class]]) { 221 | NSString *newVersion = [versionDetail objectForKey:@"version"]; 222 | NSString *releaseNotes = [versionDetail objectForKey:@"releaseNotes"]; 223 | NSString *releaseDate = [versionDetail objectForKey:@"releaseDate"]; 224 | NSString *fileSizeBytes = [versionDetail objectForKey:@"fileSizeBytes"]; 225 | if (newVersion && 226 | [newVersion isKindOfClass:[NSString class]] && 227 | [newVersion compare:kAppVersion() options:NSNumericSearch] == NSOrderedDescending && 228 | ![self isVersionSkipped:newVersion]) { 229 | _latestVersion = [[LTUpdateVersionDetails alloc] init]; 230 | _latestVersion.version = [newVersion copy]; 231 | if (releaseNotes && [releaseNotes length] > 0) { 232 | _latestVersion.releaseNotes = [releaseNotes copy]; 233 | } 234 | if (releaseDate) { 235 | _latestVersion.releaseDate = parseRFC3339Date(releaseDate); 236 | } 237 | if (fileSizeBytes && [fileSizeBytes longLongValue] > 0) { 238 | _latestVersion.fileSizeBytes = [fileSizeBytes longLongValue]; 239 | } 240 | } else { 241 | _latestVersion = nil; 242 | } 243 | } 244 | } 245 | } 246 | } 247 | 248 | #pragma mark - Update message 249 | 250 | - (NSString*)updateMessage { 251 | return [NSString stringWithFormat: 252 | LTI18N(@"%@ %@ is now available. You have %@. Would you like to download(%@) it now?"), 253 | kAppName(), 254 | self.latestVersion.version, 255 | kAppVersion(), 256 | humanReadableFileSize(self.latestVersion.fileSizeBytes)]; 257 | } 258 | 259 | #pragma mark - Update interval 260 | 261 | - (double)lastUpdateInterval { 262 | return [[NSUserDefaults standardUserDefaults] doubleForKey:@"LTLastUpdateDate"]; 263 | } 264 | 265 | - (void)setLastUpdateInterval { 266 | double timestamp = [[NSDate date] timeIntervalSince1970]; 267 | [[NSUserDefaults standardUserDefaults] setDouble:timestamp forKey:@"LTLastUpdateDate"]; 268 | [[NSUserDefaults standardUserDefaults] synchronize]; 269 | } 270 | 271 | #pragma mark - Skipped version 272 | 273 | - (NSString *)versionSkipped { 274 | return [[NSUserDefaults standardUserDefaults] stringForKey:@"LTSkippedVersion"]; 275 | } 276 | 277 | - (void)setVersionSkipped:(NSString *)version { 278 | [[NSUserDefaults standardUserDefaults] setObject:version forKey:@"LTSkippedVersion"]; 279 | [[NSUserDefaults standardUserDefaults] synchronize]; 280 | } 281 | 282 | - (BOOL)isVersionSkipped:(NSString *)version { 283 | return [version compare:[self versionSkipped] options:NSNumericSearch] == NSOrderedSame; 284 | } 285 | 286 | - (void)skipVersion:(NSString *)version { 287 | [self setVersionSkipped:version]; 288 | } 289 | 290 | - (void)clearSkippedVersion { 291 | [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"LTSkippedVersion"]; 292 | [[NSUserDefaults standardUserDefaults] synchronize]; 293 | } 294 | 295 | #pragma mark - Default Alert 296 | 297 | - (void)__attribute__((unused)) alertLatestVersion:(LTUpdateOptions)alertOptions { 298 | UIAlertView *alertView = [[UIAlertView alloc] init]; 299 | [alertView setTitle:LTI18N(@"A new version is available!")]; 300 | [alertView setMessage:[self updateMessage]]; 301 | 302 | [alertView addButtonWithTitle:LTI18N(@"Update")]; 303 | 304 | if (alertOptions & LTUpdateForce) { 305 | 306 | } else { 307 | if (alertOptions & LTUpdateSkip) { 308 | [alertView addButtonWithTitle:LTI18N(@"Skip This Version")]; 309 | } 310 | [alertView addButtonWithTitle:LTI18N(@"Remind Me Later")]; 311 | } 312 | 313 | [alertView setDelegate:self]; 314 | [alertView show]; 315 | [alertView release]; 316 | alertView = nil; 317 | } 318 | 319 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 320 | if (buttonIndex == 0) { 321 | NSString *appStoreURL = [NSString stringWithFormat:kAppStoreFormat, [self appStoreID]]; 322 | NSURL *url = [NSURL URLWithString:appStoreURL]; 323 | [[UIApplication sharedApplication] openURL:url]; 324 | } else if ([[alertView buttonTitleAtIndex:buttonIndex] 325 | isEqualToString:LTI18N(@"Skip This Version")]) { 326 | [self skipVersion:[[self latestVersion] version]]; 327 | } 328 | } 329 | 330 | #pragma mark - Notification 331 | 332 | - (void)updateAndPush 333 | { 334 | [self updateAndPush:LTUpdateDaily]; 335 | } 336 | 337 | - (void)updateAndPush:(LTUpdatePeroid)peroid 338 | { 339 | static dispatch_once_t observerToken; 340 | dispatch_once(&observerToken, ^{ 341 | [[NSNotificationCenter defaultCenter] addObserver:self 342 | selector:@selector(pushLatestVersion) 343 | name:UIApplicationDidEnterBackgroundNotification 344 | object:nil]; 345 | }); 346 | [self update:peroid complete:nil]; 347 | } 348 | 349 | - (void)__attribute__((unused)) pushLatestVersion 350 | { 351 | [self pushLatestVersion:nil]; 352 | } 353 | 354 | - (void)pushLatestVersion:(UILocalNotification *)notification 355 | { 356 | if (!self.latestVersion) return; 357 | if (!notification) { 358 | notification = [[UILocalNotification alloc] init]; 359 | notification.timeZone = [NSTimeZone defaultTimeZone]; 360 | notification.fireDate = [[NSDate date] dateByAddingTimeInterval:1.5f]; 361 | notification.alertBody = [self updateMessage]; 362 | notification.alertAction = LTI18N(@"Update"); 363 | } 364 | [[UIApplication sharedApplication] scheduleLocalNotification:notification]; 365 | [[NSNotificationCenter defaultCenter] removeObserver:self 366 | name:UIApplicationDidEnterBackgroundNotification 367 | object:nil]; 368 | } 369 | 370 | - (void)__attribute__((unused)) reduceNotification:(UILocalNotification*)notification 371 | { 372 | [self reduceNotification:notification then:LTUpdateNotifyOpenAppStore]; 373 | } 374 | 375 | - (void)reduceNotification:(UILocalNotification *)notification then:(LTUpdateNotifyActions)action 376 | { 377 | if ([notification.alertAction isEqualToString:LTI18N(@"Update")]) { 378 | [[UIApplication sharedApplication] cancelLocalNotification:notification]; 379 | if (action == LTUpdateNotifyOpenAppStore) { 380 | [self openAppStore]; 381 | } else if (action == LTUpdateNotifyThenAlert) { 382 | [self alertLatestVersion:LTUpdateSkip|LTUpdateOption]; 383 | } 384 | } 385 | } 386 | 387 | #pragma mark - Open AppStore 388 | 389 | - (void)openAppStore 390 | { 391 | NSString *appStoreURL = [NSString stringWithFormat:kAppStoreFormat, [self appStoreID]]; 392 | NSURL *url = [NSURL URLWithString:appStoreURL]; 393 | [[UIApplication sharedApplication] openURL:url]; 394 | } 395 | 396 | 397 | @end 398 | -------------------------------------------------------------------------------- /LTUpdate Demo/LTUpdate Demo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D71AFD9316DDF2170099121A /* LTUpdate.strings in Resources */ = {isa = PBXBuildFile; fileRef = D71AFD7A16DDF2170099121A /* LTUpdate.strings */; }; 11 | D71AFD9416DDF2170099121A /* LTUpdate.strings in Resources */ = {isa = PBXBuildFile; fileRef = D71AFD7A16DDF2170099121A /* LTUpdate.strings */; }; 12 | D779146116D23BB600BDF086 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D779146016D23BB600BDF086 /* UIKit.framework */; }; 13 | D779146316D23BB600BDF086 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D779146216D23BB600BDF086 /* Foundation.framework */; }; 14 | D779146516D23BB600BDF086 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D779146416D23BB600BDF086 /* CoreGraphics.framework */; }; 15 | D779146B16D23BB600BDF086 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D779146916D23BB600BDF086 /* InfoPlist.strings */; }; 16 | D779146D16D23BB600BDF086 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D779146C16D23BB600BDF086 /* main.m */; }; 17 | D779147116D23BB700BDF086 /* LTAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D779147016D23BB700BDF086 /* LTAppDelegate.m */; }; 18 | D779147316D23BB700BDF086 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = D779147216D23BB700BDF086 /* Default.png */; }; 19 | D779147516D23BB700BDF086 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D779147416D23BB700BDF086 /* Default@2x.png */; }; 20 | D779147716D23BB700BDF086 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D779147616D23BB700BDF086 /* Default-568h@2x.png */; }; 21 | D779147F16D23BB700BDF086 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D779147E16D23BB700BDF086 /* SenTestingKit.framework */; }; 22 | D779148016D23BB700BDF086 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D779146016D23BB600BDF086 /* UIKit.framework */; }; 23 | D779148116D23BB700BDF086 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D779146216D23BB600BDF086 /* Foundation.framework */; }; 24 | D779148916D23BB700BDF086 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = D779148716D23BB700BDF086 /* InfoPlist.strings */; }; 25 | D779148C16D23BB700BDF086 /* LTUpdate_DemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D779148B16D23BB700BDF086 /* LTUpdate_DemoTests.m */; }; 26 | D779149816D23C3100BDF086 /* LTUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = D779149716D23C3100BDF086 /* LTUpdate.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; 27 | D779149916D23C3100BDF086 /* LTUpdate.m in Sources */ = {isa = PBXBuildFile; fileRef = D779149716D23C3100BDF086 /* LTUpdate.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; }; 28 | D7953BA716DB410600700B2F /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = D7953BA316DB410600700B2F /* JSONKit.m */; }; 29 | D7953BA816DB410600700B2F /* JSONKit.m in Sources */ = {isa = PBXBuildFile; fileRef = D7953BA316DB410600700B2F /* JSONKit.m */; }; 30 | /* End PBXBuildFile section */ 31 | 32 | /* Begin PBXContainerItemProxy section */ 33 | D779148216D23BB700BDF086 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = D779145516D23BB600BDF086 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = D779145C16D23BB600BDF086; 38 | remoteInfo = "LTUpdate Demo"; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | D71AFD7B16DDF2170099121A /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/LTUpdate.strings; sourceTree = ""; }; 44 | D71AFD7C16DDF2170099121A /* cs */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = cs; path = cs.lproj/LTUpdate.strings; sourceTree = ""; }; 45 | D71AFD7D16DDF2170099121A /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/LTUpdate.strings; sourceTree = ""; }; 46 | D71AFD7E16DDF2170099121A /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/LTUpdate.strings; sourceTree = ""; }; 47 | D71AFD7F16DDF2170099121A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/LTUpdate.strings; sourceTree = ""; }; 48 | D71AFD8016DDF2170099121A /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/LTUpdate.strings; sourceTree = ""; }; 49 | D71AFD8116DDF2170099121A /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/LTUpdate.strings; sourceTree = ""; }; 50 | D71AFD8216DDF2170099121A /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/LTUpdate.strings; sourceTree = ""; }; 51 | D71AFD8316DDF2170099121A /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/LTUpdate.strings; sourceTree = ""; }; 52 | D71AFD8416DDF2170099121A /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/LTUpdate.strings; sourceTree = ""; }; 53 | D71AFD8516DDF2170099121A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/LTUpdate.strings; sourceTree = ""; }; 54 | D71AFD8616DDF2170099121A /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/LTUpdate.strings; sourceTree = ""; }; 55 | D71AFD8716DDF2170099121A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/LTUpdate.strings"; sourceTree = ""; }; 56 | D71AFD8816DDF2170099121A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/LTUpdate.strings"; sourceTree = ""; }; 57 | D71AFD8916DDF2170099121A /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/LTUpdate.strings; sourceTree = ""; }; 58 | D71AFD8A16DDF2170099121A /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/LTUpdate.strings; sourceTree = ""; }; 59 | D71AFD8B16DDF2170099121A /* sk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sk; path = sk.lproj/LTUpdate.strings; sourceTree = ""; }; 60 | D71AFD8C16DDF2170099121A /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/LTUpdate.strings; sourceTree = ""; }; 61 | D71AFD8D16DDF2170099121A /* th */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = th; path = th.lproj/LTUpdate.strings; sourceTree = ""; }; 62 | D71AFD8E16DDF2170099121A /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/LTUpdate.strings; sourceTree = ""; }; 63 | D71AFD8F16DDF2170099121A /* uk */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/LTUpdate.strings; sourceTree = ""; }; 64 | D71AFD9016DDF2170099121A /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/LTUpdate.strings"; sourceTree = ""; }; 65 | D71AFD9216DDF2170099121A /* zh-Hant-TW */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant-TW"; path = "zh-Hant-TW.lproj/LTUpdate.strings"; sourceTree = ""; }; 66 | D71AFD9516DE01A20099121A /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = sl.lproj/LTUpdate.strings; sourceTree = ""; }; 67 | D73EFAD016DE475E008C2CD8 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/LTUpdate.strings"; sourceTree = ""; }; 68 | D779145D16D23BB600BDF086 /* LTUpdate Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "LTUpdate Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 69 | D779146016D23BB600BDF086 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 70 | D779146216D23BB600BDF086 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 71 | D779146416D23BB600BDF086 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 72 | D779146816D23BB600BDF086 /* LTUpdate Demo-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LTUpdate Demo-Info.plist"; sourceTree = ""; }; 73 | D779146A16D23BB600BDF086 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 74 | D779146C16D23BB600BDF086 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 75 | D779146E16D23BB700BDF086 /* LTUpdate Demo-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "LTUpdate Demo-Prefix.pch"; sourceTree = ""; }; 76 | D779146F16D23BB700BDF086 /* LTAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LTAppDelegate.h; sourceTree = ""; }; 77 | D779147016D23BB700BDF086 /* LTAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LTAppDelegate.m; sourceTree = ""; }; 78 | D779147216D23BB700BDF086 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 79 | D779147416D23BB700BDF086 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 80 | D779147616D23BB700BDF086 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 81 | D779147D16D23BB700BDF086 /* LTUpdate DemoTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "LTUpdate DemoTests.octest"; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | D779147E16D23BB700BDF086 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; 83 | D779148616D23BB700BDF086 /* LTUpdate DemoTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LTUpdate DemoTests-Info.plist"; sourceTree = ""; }; 84 | D779148816D23BB700BDF086 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 85 | D779148A16D23BB700BDF086 /* LTUpdate_DemoTests.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LTUpdate_DemoTests.h; sourceTree = ""; }; 86 | D779148B16D23BB700BDF086 /* LTUpdate_DemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LTUpdate_DemoTests.m; sourceTree = ""; }; 87 | D779149616D23C3100BDF086 /* LTUpdate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LTUpdate.h; sourceTree = ""; }; 88 | D779149716D23C3100BDF086 /* LTUpdate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LTUpdate.m; sourceTree = ""; }; 89 | D7953BA216DB410600700B2F /* JSONKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSONKit.h; sourceTree = ""; }; 90 | D7953BA316DB410600700B2F /* JSONKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = JSONKit.m; sourceTree = ""; }; 91 | /* End PBXFileReference section */ 92 | 93 | /* Begin PBXFrameworksBuildPhase section */ 94 | D779145A16D23BB600BDF086 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | D779146116D23BB600BDF086 /* UIKit.framework in Frameworks */, 99 | D779146316D23BB600BDF086 /* Foundation.framework in Frameworks */, 100 | D779146516D23BB600BDF086 /* CoreGraphics.framework in Frameworks */, 101 | ); 102 | runOnlyForDeploymentPostprocessing = 0; 103 | }; 104 | D779147916D23BB700BDF086 /* Frameworks */ = { 105 | isa = PBXFrameworksBuildPhase; 106 | buildActionMask = 2147483647; 107 | files = ( 108 | D779147F16D23BB700BDF086 /* SenTestingKit.framework in Frameworks */, 109 | D779148016D23BB700BDF086 /* UIKit.framework in Frameworks */, 110 | D779148116D23BB700BDF086 /* Foundation.framework in Frameworks */, 111 | ); 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | /* End PBXFrameworksBuildPhase section */ 115 | 116 | /* Begin PBXGroup section */ 117 | D71AFD7916DDF2170099121A /* LTI18N */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | D71AFD7A16DDF2170099121A /* LTUpdate.strings */, 121 | ); 122 | path = LTI18N; 123 | sourceTree = ""; 124 | }; 125 | D779145416D23BB600BDF086 = { 126 | isa = PBXGroup; 127 | children = ( 128 | D7953BA016DB410600700B2F /* JSONKit */, 129 | D779149516D23C1700BDF086 /* LTUpdate */, 130 | D779146616D23BB600BDF086 /* LTUpdate Demo */, 131 | D779148416D23BB700BDF086 /* LTUpdate DemoTests */, 132 | D779145F16D23BB600BDF086 /* Frameworks */, 133 | D779145E16D23BB600BDF086 /* Products */, 134 | ); 135 | sourceTree = ""; 136 | }; 137 | D779145E16D23BB600BDF086 /* Products */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | D779145D16D23BB600BDF086 /* LTUpdate Demo.app */, 141 | D779147D16D23BB700BDF086 /* LTUpdate DemoTests.octest */, 142 | ); 143 | name = Products; 144 | sourceTree = ""; 145 | }; 146 | D779145F16D23BB600BDF086 /* Frameworks */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | D779146016D23BB600BDF086 /* UIKit.framework */, 150 | D779146216D23BB600BDF086 /* Foundation.framework */, 151 | D779146416D23BB600BDF086 /* CoreGraphics.framework */, 152 | D779147E16D23BB700BDF086 /* SenTestingKit.framework */, 153 | ); 154 | name = Frameworks; 155 | sourceTree = ""; 156 | }; 157 | D779146616D23BB600BDF086 /* LTUpdate Demo */ = { 158 | isa = PBXGroup; 159 | children = ( 160 | D779146F16D23BB700BDF086 /* LTAppDelegate.h */, 161 | D779147016D23BB700BDF086 /* LTAppDelegate.m */, 162 | D779146716D23BB600BDF086 /* Supporting Files */, 163 | ); 164 | path = "LTUpdate Demo"; 165 | sourceTree = ""; 166 | }; 167 | D779146716D23BB600BDF086 /* Supporting Files */ = { 168 | isa = PBXGroup; 169 | children = ( 170 | D779146816D23BB600BDF086 /* LTUpdate Demo-Info.plist */, 171 | D779146916D23BB600BDF086 /* InfoPlist.strings */, 172 | D779146C16D23BB600BDF086 /* main.m */, 173 | D779146E16D23BB700BDF086 /* LTUpdate Demo-Prefix.pch */, 174 | D779147216D23BB700BDF086 /* Default.png */, 175 | D779147416D23BB700BDF086 /* Default@2x.png */, 176 | D779147616D23BB700BDF086 /* Default-568h@2x.png */, 177 | ); 178 | name = "Supporting Files"; 179 | sourceTree = ""; 180 | }; 181 | D779148416D23BB700BDF086 /* LTUpdate DemoTests */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | D779148A16D23BB700BDF086 /* LTUpdate_DemoTests.h */, 185 | D779148B16D23BB700BDF086 /* LTUpdate_DemoTests.m */, 186 | D779148516D23BB700BDF086 /* Supporting Files */, 187 | ); 188 | path = "LTUpdate DemoTests"; 189 | sourceTree = ""; 190 | }; 191 | D779148516D23BB700BDF086 /* Supporting Files */ = { 192 | isa = PBXGroup; 193 | children = ( 194 | D779148616D23BB700BDF086 /* LTUpdate DemoTests-Info.plist */, 195 | D779148716D23BB700BDF086 /* InfoPlist.strings */, 196 | ); 197 | name = "Supporting Files"; 198 | sourceTree = ""; 199 | }; 200 | D779149516D23C1700BDF086 /* LTUpdate */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | D71AFD7916DDF2170099121A /* LTI18N */, 204 | D779149616D23C3100BDF086 /* LTUpdate.h */, 205 | D779149716D23C3100BDF086 /* LTUpdate.m */, 206 | ); 207 | name = LTUpdate; 208 | path = ../LTUpdate; 209 | sourceTree = ""; 210 | }; 211 | D7953BA016DB410600700B2F /* JSONKit */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | D7953BA216DB410600700B2F /* JSONKit.h */, 215 | D7953BA316DB410600700B2F /* JSONKit.m */, 216 | ); 217 | name = JSONKit; 218 | path = ../JSONKit; 219 | sourceTree = ""; 220 | }; 221 | /* End PBXGroup section */ 222 | 223 | /* Begin PBXNativeTarget section */ 224 | D779145C16D23BB600BDF086 /* LTUpdate Demo */ = { 225 | isa = PBXNativeTarget; 226 | buildConfigurationList = D779148F16D23BB700BDF086 /* Build configuration list for PBXNativeTarget "LTUpdate Demo" */; 227 | buildPhases = ( 228 | D779145916D23BB600BDF086 /* Sources */, 229 | D779145A16D23BB600BDF086 /* Frameworks */, 230 | D779145B16D23BB600BDF086 /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | ); 236 | name = "LTUpdate Demo"; 237 | productName = "LTUpdate Demo"; 238 | productReference = D779145D16D23BB600BDF086 /* LTUpdate Demo.app */; 239 | productType = "com.apple.product-type.application"; 240 | }; 241 | D779147C16D23BB700BDF086 /* LTUpdate DemoTests */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = D779149216D23BB700BDF086 /* Build configuration list for PBXNativeTarget "LTUpdate DemoTests" */; 244 | buildPhases = ( 245 | D779147816D23BB700BDF086 /* Sources */, 246 | D779147916D23BB700BDF086 /* Frameworks */, 247 | D779147A16D23BB700BDF086 /* Resources */, 248 | D779147B16D23BB700BDF086 /* ShellScript */, 249 | ); 250 | buildRules = ( 251 | ); 252 | dependencies = ( 253 | D779148316D23BB700BDF086 /* PBXTargetDependency */, 254 | ); 255 | name = "LTUpdate DemoTests"; 256 | productName = "LTUpdate DemoTests"; 257 | productReference = D779147D16D23BB700BDF086 /* LTUpdate DemoTests.octest */; 258 | productType = "com.apple.product-type.bundle"; 259 | }; 260 | /* End PBXNativeTarget section */ 261 | 262 | /* Begin PBXProject section */ 263 | D779145516D23BB600BDF086 /* Project object */ = { 264 | isa = PBXProject; 265 | attributes = { 266 | CLASSPREFIX = LT; 267 | LastUpgradeCheck = 0460; 268 | ORGANIZATIONNAME = "Lex Tang"; 269 | }; 270 | buildConfigurationList = D779145816D23BB600BDF086 /* Build configuration list for PBXProject "LTUpdate Demo" */; 271 | compatibilityVersion = "Xcode 3.2"; 272 | developmentRegion = English; 273 | hasScannedForEncodings = 0; 274 | knownRegions = ( 275 | en, 276 | "zh-Hans", 277 | "zh-Hant", 278 | fr, 279 | ja, 280 | de, 281 | es, 282 | it, 283 | pt, 284 | "pt-PT", 285 | nl, 286 | sv, 287 | da, 288 | ru, 289 | pl, 290 | "pt-BR", 291 | ko, 292 | ar, 293 | cs, 294 | tr, 295 | th, 296 | ro, 297 | sk, 298 | uk, 299 | "zh-Hant-TW", 300 | "zh-Hant-HK", 301 | sl, 302 | ); 303 | mainGroup = D779145416D23BB600BDF086; 304 | productRefGroup = D779145E16D23BB600BDF086 /* Products */; 305 | projectDirPath = ""; 306 | projectRoot = ""; 307 | targets = ( 308 | D779145C16D23BB600BDF086 /* LTUpdate Demo */, 309 | D779147C16D23BB700BDF086 /* LTUpdate DemoTests */, 310 | ); 311 | }; 312 | /* End PBXProject section */ 313 | 314 | /* Begin PBXResourcesBuildPhase section */ 315 | D779145B16D23BB600BDF086 /* Resources */ = { 316 | isa = PBXResourcesBuildPhase; 317 | buildActionMask = 2147483647; 318 | files = ( 319 | D779146B16D23BB600BDF086 /* InfoPlist.strings in Resources */, 320 | D779147316D23BB700BDF086 /* Default.png in Resources */, 321 | D779147516D23BB700BDF086 /* Default@2x.png in Resources */, 322 | D779147716D23BB700BDF086 /* Default-568h@2x.png in Resources */, 323 | D71AFD9316DDF2170099121A /* LTUpdate.strings in Resources */, 324 | ); 325 | runOnlyForDeploymentPostprocessing = 0; 326 | }; 327 | D779147A16D23BB700BDF086 /* Resources */ = { 328 | isa = PBXResourcesBuildPhase; 329 | buildActionMask = 2147483647; 330 | files = ( 331 | D779148916D23BB700BDF086 /* InfoPlist.strings in Resources */, 332 | D71AFD9416DDF2170099121A /* LTUpdate.strings in Resources */, 333 | ); 334 | runOnlyForDeploymentPostprocessing = 0; 335 | }; 336 | /* End PBXResourcesBuildPhase section */ 337 | 338 | /* Begin PBXShellScriptBuildPhase section */ 339 | D779147B16D23BB700BDF086 /* ShellScript */ = { 340 | isa = PBXShellScriptBuildPhase; 341 | buildActionMask = 2147483647; 342 | files = ( 343 | ); 344 | inputPaths = ( 345 | ); 346 | outputPaths = ( 347 | ); 348 | runOnlyForDeploymentPostprocessing = 0; 349 | shellPath = /bin/sh; 350 | shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n"; 351 | }; 352 | /* End PBXShellScriptBuildPhase section */ 353 | 354 | /* Begin PBXSourcesBuildPhase section */ 355 | D779145916D23BB600BDF086 /* Sources */ = { 356 | isa = PBXSourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | D779146D16D23BB600BDF086 /* main.m in Sources */, 360 | D779147116D23BB700BDF086 /* LTAppDelegate.m in Sources */, 361 | D779149816D23C3100BDF086 /* LTUpdate.m in Sources */, 362 | D7953BA716DB410600700B2F /* JSONKit.m in Sources */, 363 | ); 364 | runOnlyForDeploymentPostprocessing = 0; 365 | }; 366 | D779147816D23BB700BDF086 /* Sources */ = { 367 | isa = PBXSourcesBuildPhase; 368 | buildActionMask = 2147483647; 369 | files = ( 370 | D779148C16D23BB700BDF086 /* LTUpdate_DemoTests.m in Sources */, 371 | D779149916D23C3100BDF086 /* LTUpdate.m in Sources */, 372 | D7953BA816DB410600700B2F /* JSONKit.m in Sources */, 373 | ); 374 | runOnlyForDeploymentPostprocessing = 0; 375 | }; 376 | /* End PBXSourcesBuildPhase section */ 377 | 378 | /* Begin PBXTargetDependency section */ 379 | D779148316D23BB700BDF086 /* PBXTargetDependency */ = { 380 | isa = PBXTargetDependency; 381 | target = D779145C16D23BB600BDF086 /* LTUpdate Demo */; 382 | targetProxy = D779148216D23BB700BDF086 /* PBXContainerItemProxy */; 383 | }; 384 | /* End PBXTargetDependency section */ 385 | 386 | /* Begin PBXVariantGroup section */ 387 | D71AFD7A16DDF2170099121A /* LTUpdate.strings */ = { 388 | isa = PBXVariantGroup; 389 | children = ( 390 | D71AFD7B16DDF2170099121A /* ar */, 391 | D71AFD7C16DDF2170099121A /* cs */, 392 | D71AFD7D16DDF2170099121A /* da */, 393 | D71AFD7E16DDF2170099121A /* de */, 394 | D71AFD7F16DDF2170099121A /* en */, 395 | D71AFD8016DDF2170099121A /* es */, 396 | D71AFD8116DDF2170099121A /* fr */, 397 | D71AFD8216DDF2170099121A /* it */, 398 | D71AFD8316DDF2170099121A /* ja */, 399 | D71AFD8416DDF2170099121A /* ko */, 400 | D71AFD8516DDF2170099121A /* nl */, 401 | D71AFD8616DDF2170099121A /* pl */, 402 | D71AFD8716DDF2170099121A /* pt-BR */, 403 | D71AFD8816DDF2170099121A /* pt-PT */, 404 | D71AFD8916DDF2170099121A /* ro */, 405 | D71AFD8A16DDF2170099121A /* ru */, 406 | D71AFD8B16DDF2170099121A /* sk */, 407 | D71AFD8C16DDF2170099121A /* sv */, 408 | D71AFD8D16DDF2170099121A /* th */, 409 | D71AFD8E16DDF2170099121A /* tr */, 410 | D71AFD8F16DDF2170099121A /* uk */, 411 | D71AFD9016DDF2170099121A /* zh-Hans */, 412 | D71AFD9216DDF2170099121A /* zh-Hant-TW */, 413 | D71AFD9516DE01A20099121A /* sl */, 414 | D73EFAD016DE475E008C2CD8 /* zh-Hant */, 415 | ); 416 | name = LTUpdate.strings; 417 | sourceTree = ""; 418 | }; 419 | D779146916D23BB600BDF086 /* InfoPlist.strings */ = { 420 | isa = PBXVariantGroup; 421 | children = ( 422 | D779146A16D23BB600BDF086 /* en */, 423 | ); 424 | name = InfoPlist.strings; 425 | sourceTree = ""; 426 | }; 427 | D779148716D23BB700BDF086 /* InfoPlist.strings */ = { 428 | isa = PBXVariantGroup; 429 | children = ( 430 | D779148816D23BB700BDF086 /* en */, 431 | ); 432 | name = InfoPlist.strings; 433 | sourceTree = ""; 434 | }; 435 | /* End PBXVariantGroup section */ 436 | 437 | /* Begin XCBuildConfiguration section */ 438 | D779148D16D23BB700BDF086 /* Debug */ = { 439 | isa = XCBuildConfiguration; 440 | buildSettings = { 441 | ALWAYS_SEARCH_USER_PATHS = NO; 442 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 443 | CLANG_CXX_LIBRARY = "libc++"; 444 | CLANG_WARN_CONSTANT_CONVERSION = YES; 445 | CLANG_WARN_EMPTY_BODY = YES; 446 | CLANG_WARN_ENUM_CONVERSION = YES; 447 | CLANG_WARN_INT_CONVERSION = YES; 448 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 449 | CODE_SIGN_IDENTITY = ""; 450 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 451 | COPY_PHASE_STRIP = NO; 452 | GCC_C_LANGUAGE_STANDARD = gnu99; 453 | GCC_DYNAMIC_NO_PIC = NO; 454 | GCC_OPTIMIZATION_LEVEL = 0; 455 | GCC_PREPROCESSOR_DEFINITIONS = ( 456 | "DEBUG=1", 457 | "$(inherited)", 458 | ); 459 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 460 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 461 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 462 | GCC_WARN_UNUSED_VARIABLE = YES; 463 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 464 | ONLY_ACTIVE_ARCH = YES; 465 | "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; 466 | SDKROOT = iphoneos; 467 | }; 468 | name = Debug; 469 | }; 470 | D779148E16D23BB700BDF086 /* Release */ = { 471 | isa = XCBuildConfiguration; 472 | buildSettings = { 473 | ALWAYS_SEARCH_USER_PATHS = NO; 474 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 475 | CLANG_CXX_LIBRARY = "libc++"; 476 | CLANG_WARN_CONSTANT_CONVERSION = YES; 477 | CLANG_WARN_EMPTY_BODY = YES; 478 | CLANG_WARN_ENUM_CONVERSION = YES; 479 | CLANG_WARN_INT_CONVERSION = YES; 480 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 481 | CODE_SIGN_IDENTITY = ""; 482 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 483 | COPY_PHASE_STRIP = YES; 484 | GCC_C_LANGUAGE_STANDARD = gnu99; 485 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 486 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 487 | GCC_WARN_UNUSED_VARIABLE = YES; 488 | IPHONEOS_DEPLOYMENT_TARGET = 4.3; 489 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 490 | SDKROOT = iphoneos; 491 | VALIDATE_PRODUCT = YES; 492 | }; 493 | name = Release; 494 | }; 495 | D779149016D23BB700BDF086 /* Debug */ = { 496 | isa = XCBuildConfiguration; 497 | buildSettings = { 498 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 499 | GCC_PREFIX_HEADER = "LTUpdate Demo/LTUpdate Demo-Prefix.pch"; 500 | INFOPLIST_FILE = "LTUpdate Demo/LTUpdate Demo-Info.plist"; 501 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | TARGETED_DEVICE_FAMILY = "1,2"; 504 | WRAPPER_EXTENSION = app; 505 | }; 506 | name = Debug; 507 | }; 508 | D779149116D23BB700BDF086 /* Release */ = { 509 | isa = XCBuildConfiguration; 510 | buildSettings = { 511 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 512 | GCC_PREFIX_HEADER = "LTUpdate Demo/LTUpdate Demo-Prefix.pch"; 513 | INFOPLIST_FILE = "LTUpdate Demo/LTUpdate Demo-Info.plist"; 514 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 515 | PRODUCT_NAME = "$(TARGET_NAME)"; 516 | TARGETED_DEVICE_FAMILY = "1,2"; 517 | WRAPPER_EXTENSION = app; 518 | }; 519 | name = Release; 520 | }; 521 | D779149316D23BB700BDF086 /* Debug */ = { 522 | isa = XCBuildConfiguration; 523 | buildSettings = { 524 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/LTUpdate Demo.app/LTUpdate Demo"; 525 | FRAMEWORK_SEARCH_PATHS = ( 526 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 527 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 528 | ); 529 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 530 | GCC_PREFIX_HEADER = "LTUpdate Demo/LTUpdate Demo-Prefix.pch"; 531 | INFOPLIST_FILE = "LTUpdate DemoTests/LTUpdate DemoTests-Info.plist"; 532 | PRODUCT_NAME = "$(TARGET_NAME)"; 533 | TEST_HOST = "$(BUNDLE_LOADER)"; 534 | WRAPPER_EXTENSION = octest; 535 | }; 536 | name = Debug; 537 | }; 538 | D779149416D23BB700BDF086 /* Release */ = { 539 | isa = XCBuildConfiguration; 540 | buildSettings = { 541 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/LTUpdate Demo.app/LTUpdate Demo"; 542 | FRAMEWORK_SEARCH_PATHS = ( 543 | "\"$(SDKROOT)/Developer/Library/Frameworks\"", 544 | "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", 545 | ); 546 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 547 | GCC_PREFIX_HEADER = "LTUpdate Demo/LTUpdate Demo-Prefix.pch"; 548 | INFOPLIST_FILE = "LTUpdate DemoTests/LTUpdate DemoTests-Info.plist"; 549 | PRODUCT_NAME = "$(TARGET_NAME)"; 550 | TEST_HOST = "$(BUNDLE_LOADER)"; 551 | WRAPPER_EXTENSION = octest; 552 | }; 553 | name = Release; 554 | }; 555 | /* End XCBuildConfiguration section */ 556 | 557 | /* Begin XCConfigurationList section */ 558 | D779145816D23BB600BDF086 /* Build configuration list for PBXProject "LTUpdate Demo" */ = { 559 | isa = XCConfigurationList; 560 | buildConfigurations = ( 561 | D779148D16D23BB700BDF086 /* Debug */, 562 | D779148E16D23BB700BDF086 /* Release */, 563 | ); 564 | defaultConfigurationIsVisible = 0; 565 | defaultConfigurationName = Release; 566 | }; 567 | D779148F16D23BB700BDF086 /* Build configuration list for PBXNativeTarget "LTUpdate Demo" */ = { 568 | isa = XCConfigurationList; 569 | buildConfigurations = ( 570 | D779149016D23BB700BDF086 /* Debug */, 571 | D779149116D23BB700BDF086 /* Release */, 572 | ); 573 | defaultConfigurationIsVisible = 0; 574 | defaultConfigurationName = Release; 575 | }; 576 | D779149216D23BB700BDF086 /* Build configuration list for PBXNativeTarget "LTUpdate DemoTests" */ = { 577 | isa = XCConfigurationList; 578 | buildConfigurations = ( 579 | D779149316D23BB700BDF086 /* Debug */, 580 | D779149416D23BB700BDF086 /* Release */, 581 | ); 582 | defaultConfigurationIsVisible = 0; 583 | defaultConfigurationName = Release; 584 | }; 585 | /* End XCConfigurationList section */ 586 | }; 587 | rootObject = D779145516D23BB600BDF086 /* Project object */; 588 | } 589 | --------------------------------------------------------------------------------