{"id":249605,"date":"2015-02-03T22:19:02","date_gmt":"2015-02-03T18:19:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=249605"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=249605","title":{"rendered":"<span class=\"post_title\">\u0421\u0442\u0440\u0438\u043c\u0438\u043d\u0433 \u0430\u0443\u0434\u0438\u043e \u0432 iOS \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a<\/span>"},"content":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u043f\u043e \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u0443 \u0430\u0443\u0434\u0438\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043d\u043e\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a. \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0430\u0443\u0434\u0438\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 AVPlayer, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u043f\u043e url \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0441\u0445\u0435\u043c\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a file, http, https. \u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u043e\u043a\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 url \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 DropBox, Box, Google Drive. \u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043a\u0430\u043a \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a, \u0442\u043e\u043a\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043a \u043d\u0435\u043c\u0443 AVPlayer \u0434\u043e\u0441\u0442\u0443\u043f \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442. <\/p>\n<p>  \u041f\u043e\u0438\u0441\u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441\u0440\u0435\u0434\u0438 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f API \u043f\u0440\u0438\u0432\u0435\u043b\u0438 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 resourceLoader \u0432 AVURLAsset. \u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0443, \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u043d\u043e\u043c\u0443 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435, \u0434\u043b\u044f AVPlayer. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u044d\u0442\u043e \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTP \u043f\u0440\u043e\u043a\u0441\u0438 \u043d\u043e \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<br \/>  <a name=\"habracut\"><\/a><br \/>  \u041d\u0443\u0436\u043d\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0442\u044c \u0447\u0442\u043e AVPlayer \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 resourceLoader \u0432 \u0442\u0435\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u043a\u043e\u0433\u0434\u0430 \u0441\u0430\u043c \u043d\u0435 \u0437\u043d\u0430\u0435\u0442 \u043a\u0430\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0444\u0430\u0439\u043b. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c url c \u043a\u0430\u0441\u0442\u0443\u043c\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u043f\u043b\u0435\u0435\u0440 \u0441 \u044d\u0442\u0438\u043c url. AVPlayer \u043d\u0435 \u0437\u043d\u0430\u044f \u043a\u0430\u043a \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u0440\u0435\u0441\u0443\u0440\u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 resourceLoader`y. <\/p>\n<p>  AVAssetResourceLoader \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0447\u0435\u0440\u0435\u0437 AVAssetResourceLoaderDelegate \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043d\u0443\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0430 \u043c\u0435\u0442\u043e\u0434\u0430:<\/p>\n<pre><code class=\"objectivec\">- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest;  - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest; <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0432\u044b\u0439 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a\u043e\u0433\u0434\u0430 AVAssetResourceLoader \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u043d\u0430\u043c AVAssetResourceLoadingRequest. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u0443\u0436\u0435 \u043d\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u0442\u043e AVAssetResourceLoader \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442 \u0432\u0442\u043e\u0440\u043e\u0439 \u043c\u0435\u0442\u043e\u0434 \u0438 \u043c\u044b \u043e\u0442\u043c\u0435\u043d\u044f\u0435\u043c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>  \u0414\u043b\u044f \u043d\u0430\u0447\u0430\u043b\u0430 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c AVPlayer, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f url \u0441 \u043a\u0430\u0441\u0442\u0443\u043c\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u043e\u0439, \u043d\u0430\u0437\u043d\u0430\u0447\u0438\u043c AVAssetResourceLoaderDelegate \u0438 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0431\u0443\u0434\u0443\u0442 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430:<\/p>\n<pre><code class=\"objectivec\">AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:@&quot;customscheme:\/\/host\/myfile.mp3&quot;] options:nil]; [asset.resourceLoader setDelegate:self queue:dispatch_get_main_queue()];  AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:asset]; [self addObserversForPlayerItem:item];  self.player = [AVPlayer playerWithPlayerItem:playerItem]; [self addObserversForPlayer]; <\/code><\/pre>\n<p>  \u0417\u0430\u043d\u0438\u043c\u0430\u0442\u044c\u0441\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u043e\u0439 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043a\u0438\u0439 \u043a\u043b\u0430\u0441\u0441 LSFilePlayerResourceLoader. \u041e\u043d \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0441 url \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0433\u043e \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0438 \u0441\u0435\u0441\u0441\u0438\u0435\u0439 YDSession, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0444\u0430\u0439\u043b \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430. \u0425\u0440\u0430\u043d\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442\u044b LSFilePlayerResourceLoader \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0432 NSDictionary, \u0430 \u043a\u043b\u044e\u0447\u0435\u043c \u0431\u0443\u0434\u0435\u0442 url \u0440\u0435\u0441\u0443\u0440\u0441\u0430. <\/p>\n<p>  \u041f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430 \u0441 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 AVAssetResourceLoader \u0432\u044b\u0437\u043e\u0432\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u0435\u043b\u0435\u0433\u0430\u0442\u0430.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">AVAssetResourceLoaderDelegate<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (BOOL)resourceLoader:(AVAssetResourceLoader *)resourceLoader shouldWaitForLoadingOfRequestedResource:(AVAssetResourceLoadingRequest *)loadingRequest{     NSURL *resourceURL = [loadingRequest.request URL];     if([resourceURL.scheme isEqualToString:@&quot;customscheme&quot;]){         LSFilePlayerResourceLoader *loader = [self resourceLoaderForRequest:loadingRequest];         if(loader==nil){             loader = [[LSFilePlayerResourceLoader alloc] initWithResourceURL:resourceURL session:self.session];             loader.delegate = self;             [self.resourceLoaders setObject:loader forKey:[self keyForResourceLoaderWithURL:resourceURL]];         }         [loader addRequest:loadingRequest];         return YES;     }     return NO; }  - (void)resourceLoader:(AVAssetResourceLoader *)resourceLoader didCancelLoadingRequest:(AVAssetResourceLoadingRequest *)loadingRequest{     LSFilePlayerResourceLoader *loader = [self resourceLoaderForRequest:loadingRequest];     [loader removeRequest:loadingRequest]; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u043c\u0435\u0442\u043e\u0434\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u043c\u044b \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u0447\u0442\u043e \u0441\u0445\u0435\u043c\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043d\u0430\u0448\u0435\u0439. \u0414\u0430\u043b\u0435\u0435 \u0431\u0435\u0440\u0435\u043c LSFilePlayerResourceLoader \u0438\u0437 \u043a\u0435\u0448\u0430 \u0438\u043b\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043a \u043d\u0435\u043c\u0443 \u0437\u0430\u043f\u0440\u043e\u0441 \u043d\u0430 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0440\u0435\u0441\u0443\u0440\u0441\u0430.<\/p>\n<p>  \u0418\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043d\u0430\u0448\u0435\u0433\u043e LSFilePlayerResourceLoader \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">LSFilePlayerResourceLoader<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\"> @interface LSFilePlayerResourceLoader : NSObject  @property (nonatomic,readonly,strong)NSURL *resourceURL; @property (nonatomic,readonly)NSArray *requests; @property (nonatomic,readonly,strong)YDSession *session; @property (nonatomic,readonly,assign)BOOL isCancelled; @property (nonatomic,weak)id&lt;LSFilePlayerResourceLoaderDelegate&gt; delegate;  - (instancetype)initWithResourceURL:(NSURL *)url session:(YDSession *)session; - (void)addRequest:(AVAssetResourceLoadingRequest *)loadingRequest; - (void)removeRequest:(AVAssetResourceLoadingRequest *)loadingRequest; - (void)cancel;  @end  @protocol LSFilePlayerResourceLoaderDelegate &lt;NSObject&gt;  @optional - (void)filePlayerResourceLoader:(LSFilePlayerResourceLoader *)resourceLoader didFailWithError:(NSError *)error; - (void)filePlayerResourceLoader:(LSFilePlayerResourceLoader *)resourceLoader didLoadResource:(NSURL *)resourceURL;  @end <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041e\u043d \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043c\u0435\u0442\u043e\u0434\u044b \u0434\u043b\u044f \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u044f\/\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0438 \u043c\u0435\u0442\u043e\u0434 \u0434\u043b\u044f \u043e\u0442\u043c\u0435\u043d\u044b \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432. LSFilePlayerResourceLoaderDelegate \u0441\u043e\u043e\u0431\u0449\u0438\u0442 \u043a\u043e\u0433\u0434\u0430 \u0440\u0435\u0441\u0443\u0440\u0441 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u0438\u043b\u0438 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u0440\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0435.<\/p>\n<p>  \u041f\u0440\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0432\u044b\u0437\u043e\u0432\u043e\u043c addRequest, \u043c\u044b \u0437\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u043c \u0435\u0433\u043e \u0432 pendingRequests \u0438 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0414\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)addRequest:(AVAssetResourceLoadingRequest *)loadingRequest{     if(self.isCancelled==NO){         NSURL *interceptedURL = [loadingRequest.request URL];         [self startOperationFromOffset:loadingRequest.dataRequest.requestedOffset length:loadingRequest.dataRequest.requestedLength];         [self.pendingRequests addObject:loadingRequest];     }     else{         if(loadingRequest.isFinished==NO){             [loadingRequest finishLoadingWithError:[self loaderCancelledError]];         }     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412 \u043d\u0430\u0447\u0430\u043b\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u0438 \u043d\u043e\u0432\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043f\u043e\u0441\u0442\u0443\u043f\u0430\u044e\u0449\u0435\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u0412 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u043b\u043e\u0441\u044c \u0447\u0442\u043e \u0444\u0430\u0439\u043b \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u043b\u0441\u044f \u0432 \u0442\u0440\u0438-\u0447\u0435\u0442\u044b\u0440\u0435 \u043f\u043e\u0442\u043e\u043a\u0430 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u0441\u0435\u043a\u0430\u043b\u0438\u0441\u044c. \u041d\u043e \u043f\u043e\u0442\u043e\u043c \u0432\u044b\u044f\u0441\u043d\u0438\u043b\u0438, \u0447\u0442\u043e \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e AVAssetResourceLoader \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u0442 \u043d\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0443\u0436\u0435 \u043d\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b. \u042d\u0442\u043e \u0434\u0430\u0435\u0442 \u043d\u0430\u043c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043c\u0435\u043b\u043e \u043e\u0442\u043c\u0435\u043d\u044f\u0442\u044c \u0432\u0441\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043a\u0430\u043a \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u044b \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u043c \u043d\u043e\u0432\u0443\u044e, \u0447\u0442\u043e \u044d\u043a\u043e\u043d\u043e\u043c\u0438\u0442 \u0442\u0440\u0430\u0444\u0438\u043a.<\/p>\n<p>  \u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441 \u0441\u0435\u0440\u0432\u0435\u0440\u0430 \u0440\u0430\u0437\u0431\u0438\u0442\u0430 \u043d\u0430 \u0434\u0432\u0435. \u041f\u0435\u0440\u0432\u0430\u044f (contentInfoOperation) \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u0440\u0430\u0437\u043c\u0435\u0440\u0435 \u0438 \u0442\u0438\u043f\u0435 \u0444\u0430\u0439\u043b\u0430. \u0412\u0442\u043e\u0440\u0430\u044f (dataOperation) \u2014 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u0430 \u0441\u043e \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c. \u0421\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0438 \u0440\u0430\u0437\u043c\u0435\u0440 \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u0432\u044b\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0437 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u043a\u043b\u0430\u0441\u0441\u0430 AVAssetResourceLoadingDataRequest. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)startOperationFromOffset:(unsigned long long)requestedOffset                           length:(unsigned long long)requestedLength{          [self cancelAllPendingRequests];     [self cancelOperations];          __weak typeof (self) weakSelf = self;          void(^failureBlock)(NSError *error) = ^(NSError *error) {         [weakSelf performBlockOnMainThreadSync:^{             if(weakSelf && weakSelf.isCancelled==NO){                 [weakSelf completeWithError:error];             }         }];     };          void(^loadDataBlock)(unsigned long long off, unsigned long long len) = ^(unsigned long long offset,unsigned long long length){         [weakSelf performBlockOnMainThreadSync:^{             NSString *bytesString = [NSString stringWithFormat:@&quot;bytes=%lld-%lld&quot;,offset,(offset+length-1)];             NSDictionary *params = @{@&quot;Range&quot;:bytesString};             id&lt;YDSessionRequest&gt; req =             [weakSelf.session partialContentForFileAtPath:weakSelf.path withParams:params response:nil                 data:^(UInt64 recDataLength, UInt64 totDataLength, NSData *recData) {                      [weakSelf performBlockOnMainThreadSync:^{                          if(weakSelf && weakSelf.isCancelled==NO){                              LSDataResonse *dataResponse = [LSDataResonse responseWithRequestedOffset:offset                                                                                       requestedLength:length                                                                                    receivedDataLength:recDataLength                                                                                                  data:recData];                              [weakSelf didReceiveDataResponse:dataResponse];                          }                      }];                  }                 completion:^(NSError *err) {                    if(err){                        failureBlock(err);                    }                 }];            weakSelf.dataOperation = req;         }];     };          if(self.contentInformation==nil){         self.contentInfoOperation = [self.session fetchStatusForPath:self.path completion:^(NSError *err, YDItemStat *item) {             if(weakSelf && weakSelf.isCancelled==NO){                 if(err==nil){                     NSString *mimeType = item.path.mimeTypeForPathExtension;                     CFStringRef contentType = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,(__bridge CFStringRef)(mimeType),NULL);                     unsigned long long contentLength = item.size;                     weakSelf.contentInformation = [[LSContentInformation alloc] init];                     weakSelf.contentInformation.byteRangeAccessSupported = YES;                     weakSelf.contentInformation.contentType = CFBridgingRelease(contentType);                     weakSelf.contentInformation.contentLength = contentLength;                     [weakSelf prepareDataCache];                     loadDataBlock(requestedOffset,requestedLength);                     weakSelf.contentInfoOperation = nil;                  }                 else{                     failureBlock(err);                 }             }         }];     }     else{         loadDataBlock(requestedOffset,requestedLength);     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u0444\u0430\u0439\u043b\u0435 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435 \u043c\u044b \u0441\u043e\u0437\u0434\u0430\u0435\u043c \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0439 \u0444\u0430\u0439\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u0441\u0435\u0442\u0438 \u0438 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0438\u0445 \u043f\u043e \u043c\u0435\u0440\u0435 \u043d\u0430\u0434\u043e\u0431\u043d\u043e\u0441\u0442\u0438. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0434\u0438\u0441\u043a\u043e\u0432\u043e\u0433\u043e \u043a\u0435\u0448\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)prepareDataCache{          self.cachedFilePath = [[self class] pathForTemporaryFile];      NSError *error = nil;     if ([[NSFileManager defaultManager] fileExistsAtPath:self.cachedFilePath] == YES){         [[NSFileManager defaultManager] removeItemAtPath:self.cachedFilePath error:&error];     }          if (error == nil && [[NSFileManager defaultManager] fileExistsAtPath:self.cachedFilePath] == NO) {         NSString *dirPath = [self.cachedFilePath stringByDeletingLastPathComponent];         [[NSFileManager defaultManager] createDirectoryAtPath:dirPath                                   withIntermediateDirectories:YES                                                    attributes:nil                                                         error:&error];                  if (error == nil) {             [[NSFileManager defaultManager] createFileAtPath:self.cachedFilePath                                                     contents:nil                                                   attributes:nil];                          self.writingFileHandle = [NSFileHandle fileHandleForWritingAtPath:self.cachedFilePath];                          @try {                 [self.writingFileHandle truncateFileAtOffset:self.contentInformation.contentLength];                 [self.writingFileHandle synchronizeFile];             }             @catch (NSException *exception) {                 NSError *error = [[NSError alloc] initWithDomain:LSFilePlayerResourceLoaderErrorDomain                                                             code:-1                                                         userInfo:@{NSLocalizedDescriptionKey:@&quot;can not write to file&quot;}];                 [self completeWithError:error];                 return;             }             self.readingFileHandle = [NSFileHandle fileHandleForReadingAtPath:self.cachedFilePath];         }     }          if (error != nil) {         [self completeWithError:error];     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041f\u043e\u0441\u043b\u0435 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u043a\u0435\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u043a\u0435\u0448\u0438\u0440\u0443\u0435\u043c \u0435\u0433\u043e \u043d\u0430 \u0434\u0438\u0441\u043a \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0439 \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0439 receivedDataLength. \u0412 \u043a\u043e\u043d\u0446\u0435 \u043e\u043f\u043e\u0432\u0435\u0449\u0430\u0435\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0435\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043e \u043d\u043e\u0432\u043e\u0439 \u043f\u043e\u0440\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u043f\u0430\u043a\u0435\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)didReceiveDataResponse:(LSDataResonse *)dataResponse{     [self cacheDataResponse:dataResponse];     self.receivedDataLength=dataResponse.currentOffset;     [self processPendingRequests]; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041c\u0435\u0442\u043e\u0434 \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0444\u0430\u0439\u043b \u0441 \u043d\u0443\u0436\u043d\u044b\u043c \u0441\u043c\u0435\u0449\u0435\u043d\u0438\u0435\u043c. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)cacheDataResponse:(LSDataResonse *)dataResponse{     unsigned long long offset = dataResponse.dataOffset;     @try {         [self.writingFileHandle seekToFileOffset:offset];         [self.writingFileHandle writeData:dataResponse.data];         [self.writingFileHandle synchronizeFile];     }     @catch (NSException *exception) {         NSError *error = [[NSError alloc] initWithDomain:LSFilePlayerResourceLoaderErrorDomain                                                     code:-1                                                 userInfo:@{NSLocalizedDescriptionKey:@&quot;can not write to file&quot;}];         [self completeWithError:error];     } } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041c\u0435\u0442\u043e\u0434 \u0447\u0442\u0435\u043d\u0438\u044f \u0434\u0435\u043b\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044e. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0427\u0442\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u043a\u0435\u0448\u0430<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (NSData *)readCachedData:(unsigned long long)startOffset length:(unsigned long long)numberOfBytesToRespondWith{     @try {         [self.readingFileHandle seekToFileOffset:startOffset];         NSData *data = [self.readingFileHandle readDataOfLength:numberOfBytesToRespondWith];         return data;     }     @catch (NSException *exception) {}     return nil; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0414\u043b\u044f \u043e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430\u0445\u043e\u0434\u044f\u0449\u0438\u0445\u0441\u044f \u0432 \u043e\u0447\u0435\u0440\u0435\u0434\u0438 \u043e \u043d\u043e\u0432\u043e\u0439 \u043f\u043e\u0440\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043c\u044b \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0435, \u0430 \u0437\u0430\u0442\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043a\u0435\u0448\u0430. \u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0431\u044b\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u044b, \u0442\u043e \u043c\u044b \u0443\u0434\u0430\u043b\u044f\u0435\u043c \u0435\u0433\u043e \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u041e\u043f\u043e\u0432\u0435\u0449\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)processPendingRequests{     NSMutableArray *requestsCompleted = [[NSMutableArray alloc] init];     for (AVAssetResourceLoadingRequest *loadingRequest in self.pendingRequests){         [self fillInContentInformation:loadingRequest.contentInformationRequest];         BOOL didRespondCompletely = [self respondWithDataForRequest:loadingRequest.dataRequest];         if (didRespondCompletely){             [loadingRequest finishLoading];             [requestsCompleted addObject:loadingRequest];         }     }     [self.pendingRequests removeObjectsInArray:requestsCompleted]; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412 \u043c\u0435\u0442\u043e\u0434\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0435 \u043c\u044b \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440, \u0442\u0438\u043f, \u0444\u043b\u0430\u0433 \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u043c\u0443 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043e \u043a\u043e\u043d\u0442\u0435\u043d\u0442\u0435<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (void)fillInContentInformation:(AVAssetResourceLoadingContentInformationRequest *)contentInformationRequest{     if (contentInformationRequest == nil || self.contentInformation == nil){         return;     }     contentInformationRequest.byteRangeAccessSupported = self.contentInformation.byteRangeAccessSupported;     contentInformationRequest.contentType = self.contentInformation.contentType;     contentInformationRequest.contentLength = self.contentInformation.contentLength; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043c\u0435\u0442\u043e\u0434, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0437 \u043a\u0435\u0448\u0430 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u043c \u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c \u0438\u0437 \u043e\u0447\u0435\u0440\u0435\u0434\u0438. <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0417\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"objectivec\">- (BOOL)respondWithDataForRequest:(AVAssetResourceLoadingDataRequest *)dataRequest{          long long startOffset = dataRequest.requestedOffset;     if (dataRequest.currentOffset != 0){         startOffset = dataRequest.currentOffset;     }          \/\/ Don't have any data at all for this request     if (self.receivedDataLength &lt; startOffset){         return NO;     }          \/\/ This is the total data we have from startOffset to whatever has been downloaded so far     NSUInteger unreadBytes = self.receivedDataLength - startOffset;          \/\/ Respond with whatever is available if we can't satisfy the request fully yet     NSUInteger numberOfBytesToRespondWith = MIN(dataRequest.requestedLength, unreadBytes);          BOOL didRespondFully = NO;      NSData *data = [self readCachedData:startOffset length:numberOfBytesToRespondWith];      if(data){         [dataRequest respondWithData:data];         long long endOffset = startOffset + dataRequest.requestedLength;         didRespondFully = self.receivedDataLength &gt;= endOffset;     }      return didRespondFully; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0430 \u044d\u0442\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u0437\u0430\u0433\u0440\u0443\u0437\u0447\u0438\u043a\u043e\u043c \u0437\u0430\u043a\u043e\u043d\u0447\u0435\u043d\u0430. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c SDK \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a\u0430, \u0434\u043b\u044f \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u043c\u044b \u043c\u043e\u0433\u043b\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435. \u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439 \u0432\u0441\u0435\u0433\u043e \u0442\u0440\u0438. <\/p>\n<p>  \u041f\u0435\u0440\u0432\u043e\u0435 \u2014 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0432 YDSession \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u0442\u043c\u0435\u043d\u044b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043d\u043e\u0432\u044b\u0439 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b YDSessionRequest \u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c \u0435\u0433\u043e \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u0445.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">YDSession.h<\/b><\/p>\n<div class=\"spoiler_text\">  <\/p>\n<pre><code class=\"objectivec\">@protocol YDSessionRequest &lt;NSObject&gt; - (void)cancel; @end  - (id&lt;YDSessionRequest&gt;)fetchDirectoryContentsAtPath:(NSString *)path completion:(YDFetchDirectoryHandler)block; - (id&lt;YDSessionRequest&gt;)fetchStatusForPath:(NSString *)path completion:(YDFetchStatusHandler)block; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0412\u0442\u043e\u0440\u043e\u0435 \u2014 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043c\u0435\u0442\u043e\u0434 \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u0438\u0437 \u0444\u0430\u0439\u043b\u0430 \u043d\u0430 \u0441\u0435\u0440\u0432\u0435\u0440\u0435.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">YDSession.h<\/b><\/p>\n<div class=\"spoiler_text\">  <\/p>\n<pre><code class=\"objectivec\">- (id&lt;YDSessionRequest&gt;)partialContentForFileAtPath:(NSString *)srcRemotePath                                          withParams:(NSDictionary *)params                                            response:(YDDidReceiveResponseHandler)response                                                data:(YDPartialDataHandler)data                                          completion:(YDHandler)completion; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">YDSession.m<\/b><\/p>\n<div class=\"spoiler_text\">  <\/p>\n<pre><code class=\"objectivec\">- (id&lt;YDSessionRequest&gt;)partialContentForFileAtPath:(NSString *)srcRemotePath                                          withParams:(NSDictionary *)params                                            response:(YDDidReceiveResponseHandler)response                                                data:(YDPartialDataHandler)data                                          completion:(YDHandler)completion{     return [self downloadFileFromPath:srcRemotePath toFile:nil withParams:params response:response data:data progress:nil completion:completion]; }  - (id&lt;YDSessionRequest&gt;)downloadFileFromPath:(NSString *)path                                       toFile:(NSString *)aFilePath                                   withParams:(NSDictionary *)params                                     response:(YDDidReceiveResponseHandler)responseBlock                                         data:(YDPartialDataHandler)dataBlock                                     progress:(YDProgressHandler)progressBlock                                   completion:(YDHandler)completionBlock{          NSURL *url = [YDSession urlForDiskPath:path];     if (!url) {         completionBlock([NSError errorWithDomain:kYDSessionBadArgumentErrorDomain                                   code:0                               userInfo:@{@&quot;getPath&quot;: path}]);         return nil;     }          BOOL skipReceivedData = NO;          if(aFilePath==nil){         aFilePath = [[self class] pathForTemporaryFile];         skipReceivedData = YES;     }          NSURL *filePath = [YDSession urlForLocalPath:aFilePath];     if (!filePath) {         completionBlock([NSError errorWithDomain:kYDSessionBadArgumentErrorDomain                                   code:1                               userInfo:@{@&quot;toFile&quot;: aFilePath}]);         return nil;     }          YDDiskRequest *request = [[YDDiskRequest alloc] initWithURL:url];     request.fileURL = filePath;     request.params = params;     request.skipReceivedData = skipReceivedData;     [self prepareRequest:request];          NSURL *requestURL = [request.URL copy];          request.callbackQueue = _callBackQueue;          request.didReceiveResponseBlock = ^(NSURLResponse *response, BOOL *accept) {         if(responseBlock){             responseBlock(response);         }     };          request.didGetPartialDataBlock = ^(UInt64 receivedDataLength, UInt64 expectedDataLength, NSData *data){         if(progressBlock){             progressBlock(receivedDataLength,expectedDataLength);         }         if(dataBlock){             dataBlock(receivedDataLength,expectedDataLength,data);         }     };          request.didFinishLoadingBlock = ^(NSData *receivedData) {                  if(skipReceivedData){             [[self class] removeTemporaryFileAtPath:aFilePath];         }                  NSDictionary *userInfo = @{@&quot;URL&quot;: requestURL,                                    @&quot;receivedDataLength&quot;: @(receivedData.length)};         [[NSNotificationCenter defaultCenter] postNotificationInMainQueueWithName:kYDSessionDidDownloadFileNotification                                                                            object:self                                                                          userInfo:userInfo];         completionBlock(nil);     };          request.didFailBlock = ^(NSError *error) {                  if(skipReceivedData){             [[self class] removeTemporaryFileAtPath:aFilePath];         }                  NSDictionary *userInfo = @{@&quot;URL&quot;: requestURL};         [[NSNotificationCenter defaultCenter] postNotificationInMainQueueWithName:kYDSessionDidFailToDownloadFileNotification                                                                            object:self                                                                          userInfo:userInfo];                  completionBlock([NSError errorWithDomain:error.domain code:error.code userInfo:userInfo]);     };          [request start];          NSDictionary *userInfo = @{@&quot;URL&quot;: request.URL};     [[NSNotificationCenter defaultCenter] postNotificationInMainQueueWithName:kYDSessionDidStartDownloadFileNotification                                                                        object:self                                                                      userInfo:userInfo];     return (id&lt;YDSessionRequest&gt;)request; }  <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418 \u0442\u0440\u0435\u0442\u044c\u0435, \u0447\u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u0442\u044c \u2014 \u044d\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043a\u043e\u043b\u0431\u0435\u043a\u043e\u0432 \u0441 \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e\u0439 \u043d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u0443\u044e, \u0438\u043d\u0430\u0447\u0435 \u0431\u043b\u043e\u043a\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u0443\u0434\u0443\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u044c \u043d\u0435 \u0432 \u0442\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u044b \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043b\u0438, \u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u0431\u0443\u0434\u0435\u0442 \u0441\u043b\u044b\u0448\u0430\u0442\u044c \u0440\u044b\u0432\u043a\u0438 \u043f\u0440\u0438 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u043d\u0438\u0438 \u043c\u0443\u0437\u044b\u043a\u0438.<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">YDSession.m<\/b><\/p>\n<div class=\"spoiler_text\">  <\/p>\n<pre><code class=\"objectivec\">- (instancetype)initWithDelegate:(id&lt;YDSessionDelegate&gt;)delegate callBackQueue:(dispatch_queue_t)queue{     self = [super init];     if (self) {         _delegate = delegate;         _callBackQueue = queue;     }     return self; }   YDDiskRequest *request = [[YDDiskRequest alloc] initWithURL:url];  request.fileURL = filePath;  request.params = params;  [self prepareRequest:request];  request.callbackQueue = _callBackQueue; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043a\u043e\u0434 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0430 <a href=\"https:\/\/github.com\/leshkoapps\/AVAssetResourceLoader\"> GitHub<\/a>. \t\t\t<\/p>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/249605\/\"> http:\/\/habrahabr.ru\/post\/249605\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\"> \t\t\t\u0412\u043e \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u043d\u0430\u0434 \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u043c \u043f\u043e \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u0443 \u0430\u0443\u0434\u0438\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 \u043d\u043e\u0432\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0442\u0430\u043a\u0438\u0445 \u043a\u0430\u043a \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a. \u0420\u0430\u0431\u043e\u0442\u0430 \u0441 \u0430\u0443\u0434\u0438\u043e \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0447\u0435\u0440\u0435\u0437 AVPlayer, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u043e\u0438\u0433\u0440\u044b\u0432\u0430\u0435\u0442 \u0444\u0430\u0439\u043b\u044b \u043f\u043e url \u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0441\u0445\u0435\u043c\u044b, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a file, http, https. \u0412\u0441\u0435 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u043e\u0442\u043b\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0442\u043e\u043a\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 url \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0441\u0440\u0435\u0434\u0438 \u043d\u0438\u0445 DropBox, Box, Google Drive. \u0414\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432, \u043a\u0430\u043a \u042f\u043d\u0434\u0435\u043a\u0441.\u0414\u0438\u0441\u043a, \u0442\u043e\u043a\u0435\u043d \u0430\u0432\u0442\u043e\u0440\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u043a \u043d\u0435\u043c\u0443 AVPlayer \u0434\u043e\u0441\u0442\u0443\u043f \u043d\u0435 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442. <\/p>\n<p>  \u041f\u043e\u0438\u0441\u043a \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441\u0440\u0435\u0434\u0438 \u0438\u043c\u0435\u044e\u0449\u0435\u0433\u043e\u0441\u044f API \u043f\u0440\u0438\u0432\u0435\u043b\u0438 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e \u043e\u0431\u044a\u0435\u043a\u0442\u0430 resourceLoader \u0432 AVURLAsset. \u0421 \u0435\u0433\u043e \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u044b \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0444\u0430\u0439\u043b\u0443, \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u043d\u043e\u043c\u0443 \u043d\u0430 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u043c \u0440\u0435\u0441\u0443\u0440\u0441\u0435, \u0434\u043b\u044f AVPlayer. \u0420\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u044d\u0442\u043e \u043f\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0443 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e HTTP \u043f\u0440\u043e\u043a\u0441\u0438 \u043d\u043e \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u0435\u043c \u0434\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-249605","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/249605","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=249605"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/249605\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=249605"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=249605"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=249605"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}