UIWebView VS WKWebView to load local html - ios

i create a html string with 500 p tag with timestamp in it
i use UIWebView and WKWebView loadHTMLString:baseURL: to load it,and wkWebView is slower about 50% than UIWebVIew. why?
UIWebView:0.1681529879570007
WKWebView:0.3913570046424866

WKWebView is faster for displaying html from Strings. However, there is a bug that makes UIWebView faster by default, which is the phone number detection.
Running a viewController with the following code, webView being respectively a UIWebView and WKWebView instance and keeping everything else identical I found WKWebView to take up to 2 seconds to load, while UIWebView loads almost instantly.
webView.loadHTMLString(HtmlStringInstance, baseURL: nil)
I'm by far not the only one to find this:
when I use wkwebview to load local html,I find it renders slower than uiwebview
UIWebView delay in loading local content
Slow loading UIWebView from string
Delay in loading a HTML string into a UIWebView
Why UIWebView work so slowly when loadHTMLString with UIWebView?
However, the solution is easy: Disable phone number detection for WKWebView and poof. There you go.

For me, creating static variable to avoid creating WKWebView multiple times worked. Objective-C example:
- (WKWebView *)webHeaderView
{
static WKWebView *_webHeaderView = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
if (!_webHeaderView)
{
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
_webHeaderView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
}
});
return _webHeaderView;
}

WKWebView rendering performance is noticeable in WebGL games and something that runs complex JavaScript algorithms which UIWebView lacks.
You check the performance both in the Github.

To make WKWebView faster, disabling WKWebView's data detectors worked for me. Swift version:
let webViewCofig = WKWebViewConfiguration()
webViewCofig.dataDetectorTypes = []
webView = WKWebView(frame: view.frame, configuration: webViewCofig)
To enable specific data detector, pass the specific type as .address,.link etc while setting dataDetectorTypes:
config.dataDetectorTypes = [.address]

Related

iOS WKWebview load local PDF Files some pages become black

I user wkwebview to load a local pdf file and it works fine. But when I scroll up and down to some pages, some pages become black. Have you also come across this problem?
This one works for me.
Assuming you are implementing WKNavigationDelegate (YourWebView.navigationDelegate) in your ViewController.
- (void)webView:(WKWebView *)webView
didFinishNavigation:(WKNavigation *)navigation
{
UIView *v = webView;
while (v) {
v.backgroundColor = [UIColor whiteColor];
v = [v.subviews firstObject];
}
}
For reference: Rendering PDF in UIWebView iOS 8, causes a black border around PDF
For iOS 11.0+ use PDFView (also see PDFKit) to display a PDF. PDFView does not have the issue with black pages.

Swift: UIWebView loading old content

My App has one ViewController, one UIWebView and 4 UIImageView
The control flow in my app:
-> Capture a Image from camera and store into UIImage variable, this happens in didFinishPickingMediaWithInfo function. Do some processing on the Image.
-> From didFinishPickingMediaWithInfo function, load UIWebView with an inline html/css code i.e.
webview.hidden = false
WebView.loadHTMLString(htmlString, baseURL: nil)
-> After the above html is loaded into UIWebView, delegate function webViewDidFinishLoad is called. From webViewDidFinishLoad, take a snapshot of whatever is loaded in UIWebView into a Image with the code below:
var image:UIImage?
autoreleasepool{
UIGraphicsBeginImageContextWithOptions(WebView.frame.size, false, 1.0)
WebView.layer.renderInContext(UIGraphicsGetCurrentContext()!)
image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
-> Store the captured image into a UIImage variable.
-> Load one more different html/css code into the same UIWebView ( I am still in the webViewDidFinishLoad function): the html loading code is same as above i.e.
WebView.loadHTMLString(htmlString1, baseURL: nil)
-> webViewDidFinishLoad is called again because of new html code loaded in above step, and I do the same thing i.e. take a snapshot of the UIWebView content into UIImage variable and load new html pattern
-> I do this 4 times i.e. in the end I have 4 Images captured in 4 UIImage variables. I load all these 4 images into the 4 UIImageView on my storyboard.
-> Then I dismiss imagepicker
imagePicker.dismissViewControllerAnimated(true, completion: nil)
Here is the issue I am seeing in the end:
-> Sometimes, Image1 is same as Image 2, and sometimes all Images are the same. This happens randomly. I know for sure that all these 4 images should be unique. Because I load different html code in each step.
What Am I doing wrong in the sequence above?
A couple things you might try:
1) Don't reload webView in webViewDidFinishLoad. Instead wait until the next run loop on main thread (allowing iOS to fully finish). In objective C, my code would look like
dispatch_async (dispatch_get_main_queue(), ^{
// call method to load new html
});
2) I've had issues with webView not being refreshed by the time webViewDidFinishLoad was called. I solved this by adjusting the webView frame. Goofy, yes. This was back in iOS 6, so I have no idea if it makes any difference anymore or would affect what you are doing.
[webView loadHTMLString: html baseURL: nil];
// Play with frame to fix refresh problem
CGRect frame = webView.frame;
webView.frame = CGRectZero;
webView.frame = frame;

Black tile appear in pdf zoom in UIWebview

When loading the pdf in UIWebview it loads properly at first.But when zoomed in and out for sometime, the pdf is not rendered properly. ie in certain zoom level some of the tile area [Rectangular area] appears black and it persist in the same state afterwards.
Please see the image below
Any idea how to make this proper ?
I face same issue like this, i tried to read local pdf using WKWebview and UIWebView. Somehow after I zoom in and zoom out in iPad the view become black like your view and I think its because memory issue and there is problem when rendering the html.
If you want to open pdf better just call UIDocumentInteractionController or PDFKit for above iOS 11
func showPDF(){
let documentController = UIDocumentInteractionController.init(url: localUrl!)
documentController.delegate = self
documentController.presentPreview(animated: true)
}
And you need implement the delegate method
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self
}

Is it possible to play a YouTube video on iOS without revealing/adding a view, while still following YouTube's Terms of Service?

I have a UITableView full of thumbnails of YouTube videos, and when they tap on one I want to start playing the YouTube video full screen automatically without the user seeing a view being added or having to interact any further than tapping the thumbnail.
Basically, I don't want to see the YouTube video player with that red play icon at all.
I was planning to use youtube-ios-player-helper/YTPlayerView to accomplish this, and I understand it just employs a UIWebView but I can't seem to figure out how to get it to work.
If I create an instance variable on my class, set myself as the delegate and select a random video for watching:
let YouTubePlayer = YTPlayerView()
override func viewDidLoad() {
super.viewDidLoad()
YouTubePlayer.delegate = self
YouTubePlayer.loadWithVideoId("apKJikXWU2g")
...
}
and then when the delegate method gets called:
func playerViewDidBecomeReady(playerView: YTPlayerView!) {
YouTubePlayer.playVideo()
}
But most of the time it either crashes in my AppDelegate with this message:
Nov 5 23:34:44 rtcreporting[73827] : logging starts...
Nov 5 23:34:44 rtcreporting[73827] : setMessageLoggingBlock: called
Or it will work if I disable breakpoints but I get a ton of Auto Layout constraint complaint messages before the video plays, indicating something is angry on some level.
Is this because I'm using a UIView subclass without actually adding it to the view hierarchy?
How would I accomplish the behaviour of autoplaying a YouTube video after a certain event without revealing a kludgy intermediary view?
Here you go, you don't have to see the youtube logo.
Define youtube iFrame, You'll need to replace the '%#' part with your youtube Video ID later when you supply to a UIWebView
#define youtubeVideoPlayUrl
#"<html><head><style>body{margin:0px 0px 0px 0px;}</style></head> <body> <div id=\"player\"></div> <script> var tag = document.createElement('script'); tag.src = 'http://www.youtube.com/player_api'; var firstScriptTag = document.getElementsByTagName('script')[0]; firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); var player; function onYouTubePlayerAPIReady() { player = new YT.Player('player', { width:'%f', height:'%f', videoId:'%#', events: { 'onReady': onPlayerReady } }); } function onPlayerReady(event) { event.target.playVideo(); } </script> </body> </html>"
Define a UIWebView object of name videoWebView to display the iFrame. You can set the height and width to be zero so it doesn't block your screen. It's like a hidden iFrame.
self.videoWebview = [UIWebView alloc] init];
I suggest you to use your own default Image and a play button on top of the image to avoid having to show 'Youtube' video logo. Once you've done that, use the following code to play the youtube video full screen
- (void)onPlayYouTubeVideo:(UIButton *)sender
{
NSString *youtubeVideoID = YOUR_YOUTUBE_VIDEO_ID;
NSString *html = [NSString stringWithFormat:youtubeVideoPlayUrl,
_videoWebView.frame.size.width, _videoWebView.frame.size.height, youtubeVideoID];
_videoWebView.mediaPlaybackRequiresUserAction = NO;
_videoWebView.delegate = self;
[_videoWebView loadHTMLString:html baseURL:[[NSBundle mainBundle] resourceURL]];
}
I'm using like this for a hotel booking app.
I've created a demo app for you.
Source code to load webView html taken from: http://iphoneincubator.com/blog/audio-video/how-to-play-youtube-videos-within-an-application
ViewController header file
#interface ViewController : UIViewController
#property (nonatomic, strong) UIWebView *webView;
#end
ViewController implementation file
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
self.webView.layer.borderWidth = 1.0;
self.webView.layer.borderColor = [UIColor redColor].CGColor;
self.webView.backgroundColor = [UIColor blackColor];
self.webView.center = self.view.center;
[self.view addSubview:self.webView];
NSString* embedHTML = #"\
<html><head>\
<style type=\"text/css\">\
body {\
background-color: transparent;\
color: white;\
}\
</style>\
</head><body style=\"margin:0\">\
<embed id=\"yt\" src=\"%#\" type=\"application/x-shockwave-flash\" \
width=\"%0.0f\" height=\"%0.0f\"></embed>\
</body></html>";
NSURL *url = [NSURL URLWithString:#"https://www.youtube.com/watch?v=K14RnTVt194"];
NSString* html = [NSString stringWithFormat:embedHTML, url, self.webView.frame.size.width, self.webView.frame.size.height];
[self.webView loadHTMLString:html baseURL:nil];
}
You should see this:
When you press the play button it goes full screen.
You probably want to create a method that accepts a URL to the youtube video in your custom cell class.
Then in the cellForRowAtIndexPath: method of your View Controller, you can call your custom cell loadYouTubeVideoWithURL: method to load the Youtube video url from your data source.
The YouTube Helper Library is definitely a nice way to embed Youtube in your iOS application while following YouTube's Terms of Service.
Regarding the Auto Layout constraints log warnings,
Is this because I'm using a UIView subclass without actually adding it to the view hierarchy?
These errors have nothing to do with your implementation and are easily reproducible.
You can create an empty iOS 8 project, add a UIWebView in your interface and try to load a Youtube page.
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"YOUTUBE_URL"]]];
You'll get the same Auto Layout constraints log messages that you got when using the YouTube Helper Library.
If you take a closer look at the elements having Auto Layout constraints problems, you'll see AVAudioOnlyIndicatorView, AVUnsupportedContentIndicatorView, AVExternalPlaybackIndicatorView, etc. The constraints with warnings are not related to views you created but are related to Apple's internal views structure. It has nothing to do with the YouTube Helper Library or your implementation.
You should definitely file a report: https://bugreport.apple.com
These warnings won't get your app rejected or lessen your chance to get your app approved until the issue is fixed from Apple, especially if you can get the warnings using an empty project with a UIWebView loading any Youtube page.

How to get a video to play in UIWebView (video is in a ALAsset group)?

Okay maybe the headline is somehow disturbing, I hope to state this so you can understand my problem.
So I have a scrollview which has paging enabled. I want to build something like iOS Photo App.
I load the photos and videos which are on the device via ALAsset and store them in a group.
Now i want to present each object on a separate subview of the scrollview.
For the pictures it is working fine. But for videos I cant make it work.
Here is what i did and what did not work:
First:
UIWebView *webView = [[UIWebView alloc] initWithFrame:frame];
NSString *embedHTML = [NSString stringWithFormat: #"<html><head><style></style></head><body>\
<video id='video_with_controls' width=\"%0.0f\" height=\"%0.0f\" controls>\
<source src='%#' type='video/MOV'/></video><ul>\
</body></html>", self.mainScrollView.frame.size.width, self.mainScrollView.frame.size.height, [assetRepresentation url]];
[webView loadHTMLString:embedHTML baseURL:nil];
then:
UIWebView *webView = [[UIWebView alloc] initWithFrame:frame];
NSString* embedHTML = [NSString stringWithFormat:#"<video controls> <source src=\"%#\"> </video>", [assetRepresentation url];
[webView loadHTMLString:embedHTML baseURL:nil];
Also I tried to store it in NSData first and then load it from there, but that causes memory problems and wont work.
Any help is highly appreciated!
Edit: As I think UIWebView is the thing that matches the iOS App visually at most, I want to use this and not for example the MPMoviePlayer .. if I am wrong there I would be glad to know how / what else looks like the original App
I guess the video url is local thats why its not working in UiWebView
so the solution would be this:
in delegate method webviewdidstartload,set up MPmovieplayer controller to play inside a UiView and yes it will look like original app as you will be playing it in a view
something like this:
Add MPMoviePlayerController's view to a UIView
When you movie file is located locale you must set the baseURL to your MainBundle and put the full path in the "src"-tag.

Resources