ios - UIWebView/NSURLProtocol - 离线时不可访问的外部 Assets 的占位符

标签 ios nsurlprotocol

我的应用是一个电子阅读器,用于在 iPhone/iPad 上阅读书籍。用户可以选择下载我们在设备上保存为 .epub 文件(压缩内容)的图书 - 这样可以在离线时查看图书。页面内容为html。

有些 Assets (如视频)不在此 .epub 内容中。当用户导航到这样的页面时,我必须检测不在 .ePub 中的外部 Assets ,并显示一个简单的占位符,其中包含文本“此内容在离线时不可用”。

这些视频可以嵌入到 iFrame html 标签或对象标签中。

现在我们有一个继承自 NSURLProtocol 抽象类的类,我正在使用它来处理这个需求。我有这 3 种方法的实现:

+ (BOOL) canInitWithRequest:(NSURLRequest *)request

- (void)startLoading

- (void) sendResponse:(NSData *)data mimetype:(NSString *)mimetype url:(NSURL *)url

我现在的问题是我有一个简单的 .png 显示“离线时此内容不可用”,但它很难看,因为有时 iFrame 的区域小于图像。我如何缩放它以适应?或者有更好的方法吗?它不一定是图像,只要我可以显示此内容不可用的消息即可。我当前在 startLoading 方法中的代码:

- (void) startLoading
{
    …
    NSString *bundlePath = [NSString stringWithFormat:@"%@/%@",[[NSBundle mainBundle] bundlePath],@"PxeReaderResources.bundle"];
    NSString *pathToPlaceholder = [NSString stringWithFormat:@"%@/%@",bundlePath,@"OfflinePlaceholder.png"]; //my placeholder image
    NSLog(@"Path to placeholder is: %@", pathToPlaceholder);

    data = [[NSFileManager defaultManager] contentsAtPath:pathToPlaceholder];

    … 

    [self sendResponse:data mimetype:@"application/octet-stream" url:self.request.URL];
}

- (void) sendResponse:(NSData *)data mimetype:(NSString *)mimetype url:(NSURL *)url
{
    NSDictionary *headers = @{@"Content-Type" : mimetype, @"Access-Control-Allow-Origin" : @"*", @"Cache-control" : @"no-cache"};
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headers];

    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    [self.client URLProtocol:self didLoadData:data];
    [self.client URLProtocolDidFinishLoading:self];
}

感谢您的任何建议。

最佳答案

我能够发送一个简单的自定义 html div 标签来代替外部 Assets 。这是代码 - 希望这会对某人有所帮助。 注意:所有这些代码都在我继承自 NSURLProtocol 的自定义类中

#define EXTERNAL_REQUEST_KEY @"ExternalRequest"

+ (BOOL) canInitWithRequest:(NSURLRequest *)request
{
     NSString* filePath = [[PxePlayer sharedInstance] getBaseURL]; //gets base path to the epub zipped folder

    if ([Reachability isReachable])
    {
        return filePath != nil && [@"file" caseInsensitiveCompare:request.URL.scheme] == NSOrderedSame;
    }
    else
    {
        if ([request.URL.scheme isEqualToString:@"https"] || [request.URL.scheme isEqualToString:@"http"]) //these schemes won't work if offline
        {
            [NSURLProtocol setProperty:@YES forKey:EXTERNAL_REQUEST_KEY inRequest:(NSMutableURLRequest*)request]; //marking those request so that we will only provide placeholder for these requests
        }
        return filePath != nil && ([@"file" caseInsensitiveCompare:request.URL.scheme] == NSOrderedSame ||
                               [@"https" caseInsensitiveCompare:request.URL.scheme] == NSOrderedSame ||
                               [@"http" caseInsensitiveCompare:request.URL.scheme] == NSOrderedSame);
    }
}

- (void) startLoading
{
    ...

    if ([NSURLProtocol propertyForKey:EXTERNAL_REQUEST_KEY inRequest:self.request])
    {   
        custMimeType = @"text/html";

        data = [self prepareDataForPlaceholderForExternalAsset];
    }

    ...

    if (data)
    {
        //Now ready to send the placeholder as custom response
        [self sendResponse:data mimetype:custMimeType url:self.request.URL];
    }
}

//method to create a simple div tag as NSData
- (NSData*) prepareDataForPlaceholderForExternalAsset
{
    NSString *placeholder =
    @"<div style=\"background-color:#efefef; border:1px solid #999999; text-align:center; width:100%; height:100%\"> \
        <font font-family=\"Helvetica Neue\" font-weight=\"Medium\" size=\"5\" color=\"#b3b3b3\"> \
          <div style=\"display:inline-block; margin-top:5%\"> \
            This content is unavailable when offline or printing \
          </div> \
        </font> \
      </div>";

    return [placeholder dataUsingEncoding:NSUTF8StringEncoding];
}

- (void) sendResponse:(NSData *)data mimetype:(NSString *)mimetype url:(NSURL *)url
{
    NSDictionary *headers = @{@"Content-Type" : mimetype, @"Access-Control-Allow-Origin" : @"*", @"Cache-control" : @"no-cache"};
    NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:url statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headers];

    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
    [self.client URLProtocol:self didLoadData:data];
    [self.client URLProtocolDidFinishLoading:self];
}

关于ios - UIWebView/NSURLProtocol - 离线时不可访问的外部 Assets 的占位符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32635605/

相关文章:

ios - NSURLProtocol 使用 AJAX 超时

android - Xamarin 表格 : iOS Linking

ios - 为什么 Swift4 会转换一个 UIButton 数组!到 [UIButton?] 类型?

ios - 通过 FBSDKShareLinkContent 在 Messenger 上分享内容失败

ios - 在 iPhone 5S 上隐藏 UIImage

ios - NSURLProtocol 不响应 UIWebviews

ios - 如何使用 NSURLProtocol 模拟 AJAX 调用?

ios - 自定义 NSURLProtocol 不会调用 canInitWithRequest :

iphone - 在 Xcode 中使用同名资源

iOS :[NSURLProtocol propertyForKey:inRequest:] return nil