欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

记一种页面loading动画实现套路

程序员文章站 2022-03-18 20:17:40
...

一、需求

1. 首次进入这个页面需要有一个loading动画,当首次加载出错时,需要展示一个错误页,点击错误页可以重新加载,重新加载也需要loading动画。

2. 去到下级页面再返回此页面时,需要重新请求数据刷新页面,这次请求数据时不需要loading动画,且请求数据出错时,也不需要展示错误页,页面保持原样。

以上需求,我们如何实现这样的loading动画逻辑呢?

二、实现

直接上代码:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setUpUI];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    //isMovingToParentViewController是iOS 5 之后系统提供的API
    BOOL needLoadingAnimation = self.isMovingToParentViewController;
    [self requestDataAnimated:needLoadingAnimation];
}

- (void)requestDataAnimated:(BOOL)animated
{
    //1.根据animated添加loading动画
    if (animated) {
        [IGPageLoadingView showInPageView:self.view];
    }
    [IGNetworkManager requestWithReq:nil successCallback:^(NSInteger resultCode, NSString *resultMsg, id body) {
        //2.请求成功后移除loading动画
        [IGPageLoadingView removeFromPageView:self.view];
        [self refresh];
    } failedCallback:^(NSInteger resultCode, NSString *resultMsg, id body) {
        //3.请求失败也要移除loading动画
        [IGPageLoadingView removeFromPageView:self.view];
        //4.根据animated添加错误页
        if (animated) {
            [IGPageErrorView showInPageView:self.view tapAction:^{
                [self requestDataAnimated:YES];
            }];
        }
    }];
}

代码解析:

1. 在viewWillAppear中发起请求,这样每一次进入页面都会刷新,再根据isMovingToParentViewController来判断是否为首次进入,首次进入则添加loading动画。

2. 请求数据方法添加animated参数,根据animated来判断是否添加loading动画。

3. 如果是一个简单页面,不需要每次进入都刷新,也不要支持下拉刷新,则loading动画添加方法如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setUpUI];
    [self requestData];
}

- (void)requestData
{
    //1.添加loading动画
    [IGPageLoadingView showInPageView:self.view];
    [IGNetworkManager requestWithReq:nil successCallback:^(NSInteger resultCode, NSString *resultMsg, id body) {
        //2.请求成功后移除loading动画
        [IGPageLoadingView removeFromPageView:self.view];
        [self refresh];
    } failedCallback:^(NSInteger resultCode, NSString *resultMsg, id body) {
        //3.请求失败添加错误页(添加错误页会自动移除loading动画)
        [IGPageErrorView showInPageView:self.view tapAction:^{
            [self requestData];
        }];
    }];
}

 

三、知识扩展

iOS 5 之后,UIViewController新增以下4个方法:

/*
  These four methods can be used in a view controller's appearance callbacks to determine if it is being
  presented, dismissed, or added or removed as a child view controller. For example, a view controller can
  check if it is disappearing because it was dismissed or popped by asking itself in its viewWillDisappear:
  method by checking the expression ([self isBeingDismissed] || [self isMovingFromParentViewController]).
*/

#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly, getter=isBeingPresented) BOOL beingPresented NS_AVAILABLE_IOS(5_0);
@property(nonatomic, readonly, getter=isBeingDismissed) BOOL beingDismissed NS_AVAILABLE_IOS(5_0);

@property(nonatomic, readonly, getter=isMovingToParentViewController) BOOL movingToParentViewController NS_AVAILABLE_IOS(5_0);
@property(nonatomic, readonly, getter=isMovingFromParentViewController) BOOL movingFromParentViewController NS_AVAILABLE_IOS(5_0);
#else
- (BOOL)isBeingPresented NS_AVAILABLE_IOS(5_0);
- (BOOL)isBeingDismissed NS_AVAILABLE_IOS(5_0);

- (BOOL)isMovingToParentViewController NS_AVAILABLE_IOS(5_0);
- (BOOL)isMovingFromParentViewController NS_AVAILABLE_IOS(5_0);
#endif

看接口注释能知道,如果通过presentViewController方法弹出的Modal ViewController,则首次viewWillAppear时isBeingPresented为YES,如果是UITabBarController、UINavigationController等的子视图,则首次viewWillAppear时isMovingToParentViewController为YES,反之为NO。我们通过demo来验证,在此我直接贴上结果:

2019-01-15 15:52:52.996965+0800 test[87924:3898152] 
RootViewController, isBeingPresented = NO isMovingToParentViewController = NO
2019-01-15 15:52:53.011739+0800 test[87924:3898152] 
ModalVC: isBeingPresented = YES isMovingToParentViewController = NO
2019-01-15 15:52:53.017630+0800 test[87924:3898152] 
 TestVC: isBeingPresented = NO isMovingToParentViewController = YES
// 去到下级页面再返回
2019-01-15 15:52:55.875078+0800 test[87924:3898152] 
 TestVC: isBeingPresented = NO isMovingToParentViewController = NO

在对应VC的viewWillAppear方法进行打印,TestVC是导航栈上的vc,可以看到结果和官方注释一致。同时发现window的rootViewController的isBeingPresented和isMovingToParentViewController 都是 NO。isBeingDismissed和isMovingFromParentViewController同理。

最后感谢大家的阅读,欢迎指出问题和提出建议。