• I still remember that it was June 2 years ago. The first thing I did when I went to work in the morning was to read the latest technical articles on Jane Book. At that time, there were more than 10 iOS technical articles published on average every day. 2016.06.05 When the nine stream students released the use of VTMagic for the first time to download down, after running really feel tall still, I have done the news APP, also encapsulated similar frame level controls, but as nine stream students said in the article: most are relatively rough, not good for subsequent maintenance and expansion.
  • I also looked at a number of third-party libraries of the same type. Libraries are mostly, how many, how many child pages will create memory pressure is very big, the child page lifecycle cannot response, eventually chose VTMagic, core features: page reuse, preload, each slide child pages can response life cycle, the characteristics of really good, study a reconstructed the project directly And stable operation of more than a year

VTMagic has some experience on the use of writing a news class demo to share with you click ZBNews download view code demo interface is the network grab may not be able to use at some point in the future

1. The Pods code is not the latest issue

Because the author has not updated pods for a long time, VTMagic is currently available in 1.2.4 version, which is not compatible with iOS11. So if you are referencing VTMagic with Pods, the following format is recommended. It’s going to have multiple attributes displayCentered and fit iOS11

pod 'VTMagic', :git => 'https://github.com/tianzhuo112/VTMagic.git'
Copy the code

2. Use of new attributes

As mentioned above, the displayCentered attribute indicates whether the selected menuItem is centered. The old version of VTMagic’s selected menuItem is not centered. It’s controlled by the previewItems property

/** * If the selected menuItem is centered, default is NO */ @property (nonatomic, assign) BOOL displayCentered; /** * Default is 1 ** @warning displayCentered: This property is invalid */ @property (nonatomic, assign) NSUInteger previewItems;Copy the code

3. The system returns to the failure of the sliding gesture

If your APP to hide the navigation bar, and also require the system to return slip gestures, don’t use [self. The navigationController setNavigationBarHidden: YES animated: YES]; This method masks the system’s back swipe gesture. To use the self. The navigationController. NavigationBar. Hidden = YES; In to the jump page have a need to display a navigation bar The self in the viewWillAppear method. The navigationController. NavigationBar. Hidden = NO. Can be

//MainViewController - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; / / this method will make the system side return signal failure / / [self. NavigationControllersetNavigationBarHidden:YES animated:YES];
   self.navigationController.navigationBar.hidden = YES;
}
Copy the code

4. Data loading problem

Look at the major news APP if the subview is compared to ABC.. . After browsing A interface and automatically loading data, slide right to B interface or multiple interfaces. When you return to A interface, data will not automatically load data, unless you pull down refresh or return to A interface after A certain period of time. VTMagic adds this judgment before a request to load data in a child view controller. It is also recommended to cancel the network request and end the refresh at viewWillDisappear

- (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
  NSTimeInterval currentStamp = [[NSDate date] timeIntervalSince1970];
   if (self.dataArray.count&& currentStamp - _mainModel.lastTime < timeOut) {
       return; } _mainModel.lastTime = currentStamp;} _mainModel.lastTime = currentStamp; / / network request methods into a state or refresh} - (void) viewWillDisappear: (BOOL) animated {[super viewWillDisappear: animated]; [self.viewModel cancelRequestWithMenuInfo:_menuInfo]; // Cancel unnecessary network requests [self endRefresh]; }Copy the code

5. Preloading

Preloading this is particularly prominent VTMagic function, but some people will not use this function, including the author’s VTMagic Demo did not fully play this function. I’m talking about needPreloading=YES; // The preloading switch is on. If the preloading switch is not used, skip this section. If you know about VTMagic you know that VTMagic’s subview, if it’s just a ViewController, is doing network requests in viewDidAppear, However, when we slide the page left or right, we do not feel the visual preloading. We still feel that B will load the data after sliding from A to B, and the PAGE B will display the UI and data for A long time if the animation that automatically triggers the pull-down refresh is added. This is not ideal.

  • So let’s do a web request with auto-refresh in viewDidAppear
- (void)viewDidAppear:(BOOL)animated {
   [super viewDidAppear:animated];
   self.collectionView.scrollsToTop = YES;
   NSInteger pageIndex = [self vtm_pageIndex];
   SLog(@"Current page index: %ld", (long)pageIndex); [self requestListData]; // Load data}Copy the code

Health column slide to numerology column numerology column has all come out after loading. Is this preloading? Do you see the preloading? Definitely not.

  • Now I’m going to do real preloading if those of you who use VTMagic know that every subview is going to reference MenuInfo
.h @class MenuInfo; @interface RACChannelViewController : BaseViewController /** * MenuInfo */ @property (nonatomic, strong) MenuInfo; @endCopy the code

I’m going to override.m and you saw in VTMagic Demo that setMenuInfo is all about reading cache logic and actually this method is the entry point for preloading and when we load A, this method for B is going to fire and fire. You’re ready to preload. We can look at the log first

.m
#pragma mark - accessor methods
- (void)setMenuInfo:(MenuInfo *)menuInfo {
   _menuInfo = menuInfo;
    NSLog(@"Preload: %@",_menuInfo.title); //VTMagic official Dome load list cache method [self loadLocalData]; }Copy the code

Log shows that when we move to a column the next column of the current column is preloaded

– (void)setMenuInfo:(MenuInfo *) add the network request to MenuInfo and refresh the list after the request succeeds

#pragma mark - accessor methods
- (void)setMenuInfo:(MenuInfo *)menuInfo {
   _menuInfo = menuInfo;
   _page=1;
   [self.viewModel requestListDataWithPage:_page menuInfo:_menuInfo requestType:ZBRequestTypeRefresh];
   SLog(@"Preload: %@",_menuInfo.title); //VTMagic official Dome load list cache method [self loadLocalData]; }Copy the code

You can see that in setMenuInfo because it preloads the next column, when we are in the current column, the next column makes a network request and after the request succeeds, we refresh the list and slide to see that the next column has been preloaded

6. Page reuse cache

This reuse mechanism has been made clear by the author. See the figure below

However, this author also provides a solution to the problem of page data confusion caused by the reuse mechanism when the page slides left and right between two subview pages

- (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; [self savePageInfo]; // // Save page data VTMagic official Dome method}#pragma mark - accessor methods
- (void)setMenuInfo:(MenuInfo *)menuInfo {
   _menuInfo = menuInfo;
   _page=1;
   SLog(@"Preload: %@",_menuInfo.title); [self loadLocalData]; SavePageInfo {[[DataManager sharedInstance]} savePageInfo {[DataManager sharedInstance] savePageInfo:self.dataArray menuId:_menuInfo.menu_id]; } - (void)loadLocalData { NSArray *cacheList = [[DataManager sharedInstance] pageInfoWithMenuId:_menuInfo.menu_id]; [self.dataArray addObjectsFromArray:cacheList]; [self.tableView reloadData]; }Copy the code

SetMenuInfo is triggered in advance when the user slides back to page A to retrieve the list array and refresh the list. Although this method works fine, it is not the optimal solution

Here is my solution, which the author may not have done

- (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.tableView.scrollsToTop = YES; _page=1; [self request:_page requestType:ZBRequestTypeRefresh]; // reset data}#pragma mark - accessor methods
- (void)setMenuInfo:(MenuInfo *)menuInfo { _menuInfo = menuInfo; /* / pseudo-codeif{// Read the cache refresh list}else{// rerequest to refresh the list storage cache} */ SLog(@"Preload: %@",_menuInfo.title); _page=1; [self request:_page requestType:ZBRequestTypeCache]; // Use cache if there is cache, reload without cache}Copy the code

Rerequest in viewDidAppear or call the dropdown refresh in the setMenuInfo method (if there is cache, use cache, no cache reload) strategy which satisfies both preloading and caching.

Further explain the steps: When column A is in column B, column B has executed setMenuInfo. If B has no cache and rerequests and stores cache, column A browses for A while and slides to column B, and column B executes viewDidAppear for A refresh request and updates cache, while column C executes setMenuInfo, A->B->C->D->E->F, the same steps. When the user network slides back A< -b < -c < -d < -e < -f is also the first to execute the setMenuInfo method, because all browsing has been successful and there is A cache, setMenuInfo will perform the cache step.

In addition, you can clear the cache in the Settings page, and then go back to the main page for repeated debugging

ZBNetworking has this policy in it. If there is caching, use caching and reload without caching. It’s a perfect match

7. Nested scrolling problem

For now the more popular nested scroll VTMagic framework itself does not support its headerView and the bottom container is loaded on a UIView and there is no way to do nested scroll there is only a method to hide the headerView called in the subview

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
   CGFloat yOffset = scrollView.contentOffset.y;
   if (yOffset>0) {
       self.magicController.magicView.againstStatusBar = YES;
       [self.magicController.magicView setHeaderHidden: YES duration: 0.35]; }else{
       self.magicController.magicView.againstStatusBar = NO;
       [self.magicController.magicView setHeaderHidden: NO duration: 0.35]; }}Copy the code

Updated 2019.6.28

There is another framework that can be used with VTMagic to achieve nested scrolling effect, and there is no performance problem, click GKPageScrollView, check, I have contacted the author, please add VTMagic example. This has nested scrolling effects and can continue to use VTMagic. Note that GKPageScrollView Demo is not perfect. Forget about [the self addChildViewController: self. MagicController]; . Can be found in the code lazy loading pageView added.

- (UIView *)pageView {
   if(! _pageView) { [self addChildViewController:self.magicController]; / / add this line _pageView = self. MagicController. View; }return _pageView;
}
Copy the code

8. MeunButton added vertical lines

The menu button in VTMagic is created in the proxy method in the VTMagicViewDataSource protocol as follows

- (UIButton *)magicView:(VTMagicView *)magicView menuItemAtIndex:(NSUInteger)itemIndex{
   static NSString *itemIdentifier = @"itemIdentifier";
   MenuButton *menuItem = [magicView dequeueReusableItemWithIdentifier:itemIdentifier];
   if(! menuItem) { menuItem = [MenuButton buttonWithType:UIButtonTypeCustom]; menuItem.titleLabel.font = [UIFont fontWithName:@"Helvetica" size:16.f];
       [menuItem setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
       [menuItem setTitleColor:[UIColor greenColor] forState:UIControlStateSelected]; } menuItem.verticalLineHidden=(_menuList.count-1==itemIndex)? YES:NO;return menuItem;
}
Copy the code

You can add a vertical line to create a class that inherits FROM UIButton, add a vertical line view inside, and replace the UIButton returned by your own class in the proxy.

9. Slide to the first page and continue sliding in response to the full screen gesture pop out of the page

When the UIScrollView slides horizontally to the first one, by default it doesn’t return with a full-screen swipe, notice that it’s full-screen, the system swipe is triggered by the swipe edge, and I integrated FDFullscreenPopGesture to swipe full-screen, But sliding to the first page does not respond to a full-screen gesture pop out of the page. The solution is to write a classification of UIScrollView and rewrite the gesture proxy method. This solution is useful for all full screen sliding gesture pop functions based on UIScrollView and its subclasses, so it is not limited to use in VTMagic. Other similar libraries can also be specific code download demo to see UIScrollView+ZBKit class

So much for now, and more insights will be added later. In addition, ZBNews also realizes the functions of reading calendar, collecting and offline downloading. Of course, there is no detailed UI production, but only the display of functions. Finally, click ZBNews to download

I have been studying hard, please forgive me.