ニュヌススタンドアプリ。 iOSマガゞンを䜜成

最近、私は1぀の玙の雑誌のiOSバヌゞョンを開発しおいたした。 実際、これはたさにこのトピックを明らかにする詊みです。



はじめに玹介したす。 ニュヌススタンドずは䜕ですか そのような゚ンティティはどこから来お、䜕に倉わりたしたか 考えおみるず、私は次のこずに気付きたした。iOSプログラムに包たれたこのバヌゞョンの雑誌は、単に無責任なサむズずいう点でpdfずは異なりたす。 その理由の1぀は、膚倧な写真の山です。 ただし、このヒヌプはiOSマガゞンの光沢を生み出したす。 ニュヌススタンドのアむデアが生たれた理由は、私が理解しおいるように、特定のコンテンツの所有暩に関するAppleの立堎でした。 ぀たり タスクは定期的に配垃するために正盎に倚くの堎合、支払われたす、コピヌペヌストが困難でした。 これらの人たちはこの仕事に察凊したした-ニュヌススタンドよりも高い珟金回転率を持぀電子出版瀟は存圚しないず思いたすそう蚀えば。



ナヌザヌレベルでいく぀かの雑誌を確認したら、技術的な解決策を探したす。 たず、ニュヌススタンドキットが登堎したした。



ニュヌススタンドキットは、次のギズモで構成されおいたす。雑誌の個々の号の特別なラむブラリ管理メカニズムNKLibraryNKIssueずそのバックグラりンドダりンロヌドを含むダりンロヌドNKAssetDownload。 かっこいい しかし、その圓時、これらのギズモを雑誌に倉える方法は私には完党に䞍明確でした。



すべお同じです。 明らかに、プログラム雑誌は2぀の郚分で構成されおいたす雑誌の問題の管理ず別の雑誌の衚瀺。 ぀たり ニュヌススタンドキットは、最初のコンポヌネントである管理に焊点を圓おおいたす。 2番目のコンポヌネント-雑誌の1぀の号の衚瀺-Appleはテンプレヌトに負担をかけたせんでした。 2番目に圌女から始めたす。



理論的には、サヌバヌから必芁な情報をすべおダりンロヌドしお衚瀺する必芁がありたす。 ぀たり それはパンフレットの補足に぀いおでした。 ダりンロヌドされた情報は、条件付きで、原材料画像、フィルム、テキスト、html-in、pdfず蚭定に分けられ、それによっおすべおをたずめるこずができたす。 誰もがパンフレットに぀いお読むこずに興味があるずは思わないので、経営に関する郚分にこれらをさらに送りたす。



䞊で述べたように、Appleは特定の雑誌の衚瀺に関しお開発者を制限しおいたせん。 ただし、スワむプで雑誌をペヌゞングしお、おそらく良い圢で受け入れられたす。 このために、UIScrollViewず無限スクロヌルのアむデアを䜿甚したしたdev apple-> WWDC-> ScrollView Techniques-> Infinite scrolling。 簡単に蚀うず、メむンビュヌ党䜓にUIScrollViewを配眮する必芁がありたす。 UIScrollViewの堎合、contentSizeを3぀の画面幅に蚭定し、3぀のUIViewを配眮したすそれぞれ1぀の画面のサむズ。 さらにいく぀かの蚭定があり、スワむプで矎しいペヌゞングがありたす。 フィニッシュラむンでは、UIScrollViewデリゲヌトメ゜ッド-scrollViewDidEndDeceleratingを実装し、それに応じお、内郚UIViewを曎新したす。 無限スクロヌルの耇雑さ-別の目に芋えるUIVeiw、同様のUIScrollViewを埋め蟌むず、氎平および垂盎の反転に぀ながりたす。



わかった 疑問が残りたす珟時点で必芁なUIViewの入手先は

「この瞬間」から始めたしょう。 その特城は、雑誌の開いおいるペヌゞの番号であるず蚀えたす。 アプリケヌションでは、珟圚のペヌゞのむンデックスを栌玍するギズモが必芁であるこずがわかりたした。 そのようなこずはアプリケヌション党䜓に必芁であり、それに簡単にアクセスできるはずです。シングルトンが必芁です。 むンデックスがある堎合、質問は新しいものに芁玄されたす。むンデックスに適切なUIViewはどこで入手できたすか おそらく蚭定はそれを知っおいたす。 さらに、シングルトンに構成の読み取りを䟝頌し、むンデックスを知っお、目的のビュヌを発行しおください。 シングルトンむンタヌフェむスを指定しお、蚭定に移動したす

@interface DataManager : NSObject @property (nonatomic) int articleIndex; @property (nonatomic) int pageIndex; @property (nonatomic, strong) NSArray *articles; + (id) sharedManager; - (UIView *) currentView; - (UIView *) prevView; - (UIView *) nextView; - (UIView *) upperView; - (UIView *) lowerView; - (int) lastArticleIndex; - (int) lastPageIndex; @end
      
      





Objective-Cの構成は、.plistファむルを衚瀺するために受け入れられるか、䟿利です。 実際には、雑誌のペヌゞ、これらのペヌゞの蚭定、および生のペヌゞぞのリンクを衚瀺するplistを䜜成する必芁がありたす。 䟋がより明確になるず思いたす

 <plist version="1.0"> <array> <array> <dict> <key>class</key> <string>SimplePage</string> <key>properties</key> <dict> <key>baseImage</key> <string>1-0.png</string> </dict> </dict> </array> <array> <array> <array>
      
      





  <dict> <dict> <key>class</key> <string>PhotoPage</string> <key>properties</key> <dict> <key>baseImage</key> <string>9-0-4.png</string> <key>photos</key> <array> <dict> <key>photo</key> <string>9-1-f1.png</string> <key>thumbnail</key> <string>9-1-f1m.png</string> </dict> <dict> <dict> <dict>
      
      





各ペヌゞの最初のプロパティであるクラスに気づいたず思いたす。 ええ、なんお䟿利でしょう configにクラス名を曞き、その䞊に目的のペヌゞを䜜成したした。 前述のシングルトンのフラグメント

 - (UIView *) currentView { NSArray *article = [self.articles objectAtIndex:articleIndex]; NSDictionary *page = [article objectAtIndex:pageIndex]; return [self viewWithDictionary:page]; } - (UIView *) viewWithDictionary: (NSDictionary *) dictionary { Class class = NSClassFromString([dictionary valueForKey:@"class"]); NSDictionary *pageProperties = [dictionary valueForKey:@"properties"]; UIView *uiView = [[class alloc] initWithDictionary:pageProperties]; return uiView; }
      
      





蚀及すべきこずは䜕ですか SimplePageむンタヌフェヌスを玹介したす。 残りのペヌゞクラスは、䜕らかの方法でそれを継承したす

 @interface SimplePage : UIView @property (nonatomic, strong) NSString *imageDirectory; - (id) initWithDictionary: (NSDictionary *) pageProperties; @end
      
      





぀たり UIViewから継承するクラスのセットを䜜成し、これらのクラスに埓っお単䞀ログの構成を䜜成したす。



別のimageDirectory倉数を次に瀺したす。 ここでの事実は、埌でパンフレットの写真を収集し、それらにplistを入れお、このものをサヌバヌに送信する必芁があるずいうこずです。 したがっお、プロゞェクトに写真を远加する代わりに、シミュレヌタヌのフォルダヌであるDocumentsDirectoryに写真を収集したした。 そしおここにその初期化がありたす

 #if IS_LOCAL // doc/img dir imageDirectory = [DocumentsDirectory stringByAppendingPathComponent:@"img"]; #else // issue dir NKIssue *nkCurrentlyReadingIssue = [[NKLibrary sharedLibrary] currentlyReadingIssue]; imageDirectory = [nkCurrentlyReadingIssue.contentURL path]; #endif #if DEBUG NSLog(@"imageDirectory %@", imageDirectory); #endif
      
      





単䞀のログを衚瀺するための実装オプションに぀いおお䌝えしたかったのはそれだけです。 続けたしょうか



NKマネゞメント



蚀葉自䜓は、䜕かを管理する必芁があるこずを瀺唆しおいたす。 サヌバヌからダりンロヌドされた䜕かのコレクション。 それで、別の構造になりたす。 これを理解するには、NKLibraryずNKIssueを衚面的に考慮する必芁がありたす。



シンプルで、NKLibraryはNKIssue-sのコレクションです。 NKLibraryには倚くのナヌティリティがありたす。 これはニュヌススタンドによっお磚かれたコレクションです。 これもシングルトンであり、おそらくこの段階ではそれだけです。



NKIssueは、1぀のゞャヌナルに関する情報を保存したす。 少なくずも、問題には名前ず日付が必芁です。 間違っおいない堎合、名前がキヌになり、日付が゜ヌトされたす。



だから、䜕か、どこかを芋おいるず、issues.plistがありたす。

 <plist version="1.0"> <array> <dict> <key>Name</key> <string>f-2</string> <key>Title</key> <string>/ 2013</string> <key>Date</key> <date>2013-11-28T08:00:00Z</date> <key>Cover</key> <string>http://fo-nt.net/f/f2.png</string> <key>Content</key> <string>http://fo-nt.net/f/f2.zip</string> </dict> <dict> <dict>
      
      





サヌバヌからplistをダりンロヌドし、繰り返し、NKISsueを䜜成しおNKLibraryに远加したす

 NKLibrary *nkLib = [NKLibrary sharedLibrary]; issuesDictionary = [NSArray arrayWithContentsOfFile:issuesPlistFilePath]; for (NSDictionary *issueDictionary in issuesDictionary) { NSString *name = [issueDictionary valueForKey:@"Name"]; NKIssue *nkIssue = [nkLib issueWithName:name]; if(!nkIssue) { [nkLib addIssueWithName:name date:[issueDictionary objectForKey:@"Date"]]; NSString *coverPath = [issueDictionary valueForKey:@"Cover"]; if (IS_RETINA) coverPath = [self retinaURLStringForString:coverPath]; NSString *coverName = [coverPath lastPathComponent];
      
      





説明したす。 圓然、ここではすでにNewsstandKitをむンポヌトしおいたす。 それ以倖の堎合、NKLibraryずNKIssueに぀いおどのように知るこずができたすか 簡単に、NKLibraryのむンスタンス-nkLibを取埗したす。 配列を調べお、特定のログをその名前で提䟛するようにnkLibに䟝頌したす。 ラむブラリに「FIG to you」ず衚瀺されおいる堎合は、蚭定にログがあるこずが明らかになりたすが、ラむブラリにはありたせん->远加する必芁がありたす。



リストには、「ifIS_RETINA」ずいう行がただありたす。 簡単に蚀えば、ここでのポむントは、ゞャヌナルのすべおの写真がサヌバヌ䞊にあるずいうこずです。 ここで、ディスプレむの皮類はすでにわかっおいたす。 さお、他の人のディスプレむ甚に写真をダりンロヌドする理由。 今埌、ダりンロヌドキットは、雑誌ごずにアヌカむブに配眮するこずをお勧めしたす。 最埌に、1぀の雑誌に2぀のアヌカむブを䜜成するこずは論理的ですシンプルず@ 2x。



珟圚のNKLibraryがありたす。 控えめですが、すでに既存のログのUIを衚瀺できたす。



各ゞャヌナルのラむブラリ衚瀺の芖芚化は異なりたす。 ただし、確立されたものがありたす。 プロパティのセットを持぀NKIssueがありたす-それらを衚瀺したす。 その䞭でも、特に興味深いのは、プロパティ '' status ''です。これは、なし、ダりンロヌド䞭、䜿甚可胜です。 これは、衚瀺されたログをダりンロヌドできるずいう事実に぀ながり、ダりンロヌドが完了するのを埅っお、それぞれ読み取りたす。



パンフレット䜜成の段階で準備したキットをダりンロヌドする必芁がありたす。 NKAssetDownloadは3番目のNKのものです-ニュヌススタンド専甚のロヌダヌおそらくそうです。 手順NKIssueおよびNSURLRequestNSURLから取埗、遞択されたログのURL文字列から取埗を䜿甚しお、NKAssetDownloadのむンスタンスを䜜成したす。 downloadWithDelegateメ゜ッドを呌び出す必芁がありたすid <NSURLConnectionDownloadDelegate>デリゲヌト

 NSURLRequest *req = [NSURLRequest requestWithURL:downloadURL]; NKAssetDownload *assetDownload = [nkIssue addAssetWithRequest:req]; [assetDownload downloadWithDelegate:self]; [assetDownload setUserInfo:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithInt:index], @"Index", nil]];
      
      





機胜NKAssetDownloadはバックグラりンドでのダりンロヌドです。 圌女はニュヌススタンドに必芁です。 これは、ダりンロヌドがバックグラりンドで続行されるこずを意味したす。 ただグッズがありたす。 ただし、戻り時にすべおのNKAssetDownloadむンスタンスでdownloadWithDelegateメ゜ッドを呌び出すこずが矩務付けられおいるため、bgロヌドに興味がありたす。

 for (NKAssetDownload *assetDownload in [nkIssue downloadingAssets]) { [assetDownload downloadWithDelegate:self]; }
      
      





それがすべおのようです。 進行状況バヌでダりンロヌドを再開し、完了するのを埅ちたす。 ダりンロヌドの最埌に、アプリケヌションアむコン[[UIApplication sharedApplication] setNewsstandIconImage[publisher coverImageForIssuenkIssue]]を眮き換えるのが適切です。 アヌカむブを䜿甚した堎合は、解凍したす。 ああ、はい、アプリケヌションは、ログを読み蟌んだ埌、プロパティパスNKIssue contentURLに沿っおファむルを曞き蟌む必芁がありたす矩務付けられおいるかどうかはわかりたせん。䜕かが最適化されおいる可胜性がありたす。



さらに、NKIssueは '' available ''のステヌタスを受け入れたす-''パンフレット ''を衚瀺できたす。



次の質問ラむブラリヌの曎新-issues.plistをリロヌドし、既存のメ゜ッドで凊理するこずになりたす。 ここで、ゞャヌナルがラむブラリに远加されたかどうかを確認したした。 確かに、実質的な問題が発生したす。 倚くの雑誌では、ナヌザヌは新しい雑誌がリリヌスされるたでにそれを忘れるこずができたす。 そしお、ここでは、䞍適切なこずに、手近にAPNSがありたす。 これは別のトピックです。 私は認めたす、私はそれを初めお習埗したせんでした。 ずにかく、私は私のゞャヌナルでこれらの通知をしたせんでした。 鍵ずなる障害は蚌明曞であり、むしろその倉換の必芁性でした。



それにもかかわらず、APNSたず、通知送信サヌビスです。 プログラムは、実行䞭のデバむスのIDを取埗しお、サヌバヌに転送できたす。 たず、これらの通知をサブスクラむブする必芁がありたす。

 @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Register device for receiving push notifications [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert)];
      
      





その埌、UIApplicationDelegateプロトコルにはアプリケヌションdidRegisterForRemoteNotificationsWithDeviceTokenメ゜ッドがあり、DeviceTokenidがあり、そこからサヌバヌ情報をマヌゞできたす。 近くにアプリケヌションがありたすdidReceiveRemoteNotificationメ゜ッド。通知を受け取った埌に䜕かを行うこずができたす。



サヌバヌ偎では、DeviceTokenであるリク゚ストHTTPを受け入れお、デヌタベヌスに保存する必芁がありたす。 さらに、賌入したチケットに応じお、たたはサヌバヌに展開されおいるものに応じお、APNSに送信するメッセヌゞを探す必芁がありたす。 APIによれば、蚌明曞ずパスワヌドを添付するこずにより、ペむロヌドずDeviceTokenの䞡方を含むメッセヌゞを接続しお送信したす。 ただ埮劙な違いがありたすが、これは別の問題です。



ずりわけ、iOSマガゞンにはさらに2぀の制限がありたす。 矜-プラむバシヌポリシヌのURL。 技術面から芋るず、非垞に簡単です。 2番目の制限は、iTunesConnect内郚賌入を䜿甚しおコンテンツを配垃する必芁があるこずです。 私が理解しおいるように、これはナヌザヌが私の無料の雑誌を0お金で買わなければならないこずを意味したす。



合蚈するず、iTunesConnectのアプリ内賌入は、ストアキットの䜿甚を意味したす。 UserDefaultsでは、isFreeSubscribedプロパティを取埗したした。 私はタプで確認し、NOの堎合はアラヌトを衚瀺したす。 同意により、眲名する

 SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:@"FreeSubscription"]]; productsRequest.delegate=self; [productsRequest start];
      
      





さらに、デリゲヌトメ゜ッドを実装し、isFreeSubscribedをYESに蚭定しお、In-App Purchaseを忘れる必芁がありたす。 SKProductsRequestのProductIdは、「アプリ内賌入の管理」の䞋のiTunesConnectから取埗する必芁がありたす。



話の終わりに、私はここに雑誌の必芁性の半分さえないず信じおいたす、しかし、私は最も単玔な雑誌のために最も必芁な技術的な質問を抂説するこずができたず信じたいです。






All Articles