Develop Hybrid apps using UIWebView (1)

In view of the current performance improvement of iOS mobile phones, the effect of apps developed using the webview method has been Ideally, the team used the hybrid development model in the project, accumulated certain experience, and shared it for everyone’s reference and learned from each other.

Okay, don’t talk nonsense, let’s start with the goal , Technical principles, and code demonstrations are explained in three parts.

I. Goal

uses the combination of native and HTML, and uses native development for pages with small changes, such as personal information; while pages use movie, theater information, etc. HTML (this application is for buying movie tickets~). In order to make the effect of the HTML page better, even close to the original effect, a series of optimizations need to be made to the webview, so the hard work is coming.··


Second, optimization methods p>

In fact, many popular applications, especially applications with huge data (such as Taobao, JD.com, etc.) will adopt the hybrid method, and you can see some clues by looking at their mobile pages. When the page is loaded, the effect is almost the same as that of app loading. First, the overall frame is loaded, and then the data in the page is filled. After loading, it will become an app.


Having said so much, I just want to show the key to optimization On the front page. If you load a link from Taobao in the webview page, the experience will be great; however, after a few seconds have passed after loading your own app, it is still blank~, there is a feeling of tears running.

Since the optimization requirements are put forward above, my iOS programmer can’t rewrite the HTML page frame, so I have to do it on the webview Make a fuss:

1, support the right swipe back function

2. When dragging up and down, the navigationBar will hide and show correspondingly

3. Caching

These methods are introduced below.

3. Swipe right back function

This is a ready-made example seen from CocoaChina. It is used directly. For details, please refer to Imitation WeChat embedded webpage

There is a flaw in the demo. The page will be reloaded after sliding right and back. Think of the solution.

The right swipe back function uses screenshots, gesture recognition, and custom view conversion. After the page is loaded, a screenshot will be taken and saved in the image queue. After entering the subpage, if there is a right swipe operation, the corresponding method will be called back to make the webview shift to the right and gradually hide, while the screenshots of the previous page appear randomly. The specific principle can be seen in the demo.

4. The effect of dragging up and down

When the webview page is displayed, the navigation bar at the top occupies a certain area and cannot provide any valuable information. Hiding it will make the page Look bigger (biger than biger).

If you add up and down drag recognition to the webview, you will find that you cannot receive the callback message during dragging. I thought for a long time and didn’t know what to do, so I understood the principle of webview,

NS_CLASS_AVAILABLE_IOS(2_0) __TVOS_PROHIBITED @interface UIWebView: UIView  

The scrollView protocol was used in the original webview, and dragging up and down will be intercepted by the scrollview to display page information. Cannot trigger gesture recognition. At this point, use UIScrollViewDelegate in the custom class to receive the information when dragging, and the program will display and hide the navigationBar according to the callback information.

Using UIScrollViewDelegate needs to override scrollViewWillBeginDragging, There are three methods of scrollViewDidScroll and scrollViewDidEndDragging. When starting to drag, record the scrollView offset (scrollView.contentOffset); during the drag process, it will return to the current According to the current value and initial value, determine the offset value. The navigationBar is shifted up and down according to the offset. When it is hidden upwards, the alpha value is set to gradually decrease until it is transparent. When the navigationBar is shifted downward to display, the alpha will increase, and finally it will be completely opaque; after the dragging ends, the final state of the navigationBar will be determined according to the offset, which is completely hidden or completely displayed. This is the principle, the following is the implementation code.

#pragma mark scrollView Delegate- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{ scrollOffset = scrollView.contentOffset;}- ( void)scrollViewDidScroll:(UIScrollView *)scrollView{ if (self.tabBarController.tabBar.hidden) {//Drag up, offset.y is positive; CGPoint offset = scrollView.contentOffset; if (scrollView.contentSize.height <= webView .frame.size.height + defHeight) {return;} //During the drag process, after the distance of NAVIGATION_BAR_HEIGHT is exceeded, the default is 44 if (fabs(offset.y-scrollOffset.y)> defHeight) {if (offset. y> scrollOffset.y) {offset.y = defHeight + scrollOffset.y; }else if (offset.y  scrollOffset.y)) {return; //nav After the Bar is displayed, dragging down will not respond}else if (navBarState == NavBarStateShow && offset.y = scrollView.contentSize.height-webView.frame.size.height-defHeight/2 && navBarState == NavBarStateShow) {return;} [self setNavigationBarFrame:(offset.y-scrollOffset.y)]; })- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (!self.tabBarController.tabBar.hidden) {return;} CGPoint offset = scrollView.contentOffset; //After navBar is hidden, the web page is hidden on it When the height is less than the height of nav, the dragging distance is greater than 5, then navBar is displayed if (navBarState == NavBarStateHide && offset.y  scrollOffset.y)) {return; //After navBar is displayed, dragging down will not respond}else if (navBarState == NavBarStateShow && offset.y  defHeight/2) {switch (navBarState) {case NavBarStateShow: [self navBarHideState]; navBarState = NavBarStateHide; break; case NavBarStateHide: [self navBarShowState]; navBarState = NavBarStateShow; break; default: break;} }else{ switch (navBarState) {case NavBarStateShow: [self navBarShowState]; navBarState = NavBarStateShow; break; case NavBarStateHide: [self navBarHideState]; navBarState = NavBarStateHide; break; default: break;}} }/** * During dragging, change the page* * @param y Drag distance, drag upwards to be positive, drag downwards to be negative*/- (void) setNavigationBarFrame:(CGFloat) y{ CGRect webViewRect; CGRect navBarRect; switch (navBarState) {case NavBarStateShow: self.navigationController.navigationBar.alpha = 1-y/44; webViewRect = initWebViewRect; navBarRect = initNavBarRect; break; .navigationController setNavigationBarHidden:NO animated:NO]; self.navigationController.navigationBar.alpha = fabs(y/44); webViewRect = hidedWebViewRect; navBarRect = hidedNavBarRect; break; default: break;} webViewRect.size.height += y; webView .frame = CGRectOffset(webViewRect, 0, -y); self.navigationController.navigationBar.frame = CGRectOffse t(navBarRect, 0, -y);}- (void)navBarShowState{ webView.frame = initWebViewRect; [self.navigationController setNavigationBarHidden:NO animated:NO]; self.navigationController.navigationBar.frame = initNavBarRect; self.navigationController.navigationBar .alpha = 1.0;}- (void)navBarHideState{ webView.frame = hidedWebViewRect; [self.navigationController setNavigationBarHidden:YES animated:NO]; self.navigationController.navigationBar.frame = hidedNavBarRect;}

5. Cache

At present, the code of the cache part has been completed, but it is still being improved, and the code will be posted after it is written.

Let me briefly explain the principle.

The original idea is to save the picture locally, but if you want to use the local cached picture, you must put the picture address in the HTML file Make it local. After thinking about it, I decided to load all files such as HTML, css, js, etc., to save locally, parse the HTML files, find out the files that need to be downloaded, and asynchronously cache them locally. Use CoreData to save the information of each page, such as the URL address of the page, the path saved in the file, whether the image, css and other files have been downloaded. This part of the code has been troublesome for more than a week. At the first load, the webview refreshes every time a page is downloaded, which makes it feel inconsistent. And when there are too many files to be downloaded in a page, it takes much longer than using webview directly.

Writing so much in this section, I will add the next sister if there is progress.

Leave a Comment

Your email address will not be published.