页面的循环引用与监听事件的添加与删除,页面逻辑管理

简介: 页面的循环引用与监听事件的添加与删除,页面逻辑管理

页面的逻辑管理是衡量ios程序猿的重要标准,尽量避免页面的循环引用,若实在避免不了,要注意不能循环产生相同的页面,注意监听事件的添加与删除。

若你不你不小心产生了两个相同的页面,并且离开页面时,没有移除监听事件。对不起你将产生很多意向不到的问题,若你发送一个通知,你的那个重复的页面会产生两个通知,点击一个按钮,你可能两个按钮响应。

这些监听事件,通常包括广播通知,按钮事件。

当你的应用有被别人在其它设备踢出的逻辑处理,对不起,你肯定会出现页面的循环应用。还是关注下循环引用页面的会出现的问题。他不单会出现内存泄露,每循环引用引用一次你就会多申请一个相同的页面,虽然苹果的arc不会傻的看到你申请一大堆相同的页面,但是他会给保留两个相同的页面也算对得起你了,虽然内存不暴涨到崩溃得地步,但是让你出一些抓框得怪异现象也是很正常。所以要保证你相同页面的唯一性,特别是带监听的页面(这样的页面一定要离开页面时移除监听事件)。

解决办法一是:

在要PUSH到你想要的页面时,先在self.navigationController.viewControllers找下,看是否有,若你找到了就别申请了,直接跳到对应页面去吧,注意页面数据的初始化,不然你跳到的页面是原来的数据。找不到你再alloc不迟。

当页面出现时增加监听事件,当页面消失时移除监听事件。

注意当你的应用有侧边栏时,你的页面navigationController有两个,一个是侧边栏的,另一个是费侧边栏了。这样乱跳,就要设计侧边栏根控制器,侧边栏根控制器收到踢出的通知,调用dismissViewControllerAnimated回侧边栏根控制器。

来点实际的代码片段吧!

[GlobalShare getGlobalShare].user.servicingOrderId = -1;

NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithDictionary: result[@”body”]];

// NSLog(@”detailDict = %@”,_detailDict);

for (UIViewController *viewController in self.navigationController.viewControllers) {

if ([viewController isKindOfClass:[OrderDetailViewController class]]) {

OrderDetailViewController orderVC = (OrderDetailViewController )viewController;

orderVC.isCheckout = YES;

orderVC.orderId = self.orderId;

                orderVC.currentData = [OrderDataList GetOrderDataListWithDictionary:dict];

                [GlobalShare getGlobalShare].user.processingOrderStat = PROCESSING_ORDER_STATE_WAIT_NEW_ORDER;
                // 保存在本地
                [[GlobalShare getGlobalShare] saveinfo:[GlobalShare getGlobalShare].user];
                [SingleObject sharedInstance].noConnectPage = NO_CONNECT_PAGE_IS;


                [self.navigationController pushViewController:viewController animated:YES];
                return;
            }
        }

        OrderDetailViewController *orderVC = [[OrderDetailViewController alloc] initWithNibName:NSStringFromClass([OrderDetailViewController class]) bundle:nil];//[OrderDetailViewController new];
        orderVC.isCheckout = YES;
        orderVC.orderId = self.orderId;

        orderVC.currentData = [OrderDataList GetOrderDataListWithDictionary:dict];

         [GlobalShare getGlobalShare].user.processingOrderStat = PROCESSING_ORDER_STATE_WAIT_NEW_ORDER;
        // 保存在本地
        [[GlobalShare getGlobalShare] saveinfo:[GlobalShare getGlobalShare].user];
        [SingleObject sharedInstance].noConnectPage = NO_CONNECT_PAGE_IS;            

[self.navigationController pushViewController:orderVC animated:YES];


(void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:YES];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(RefreshOrderStatusNotification:) name:PASSENGER_PAY_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(hiddenComplaintButtonNotification:) name:HIDDEN_COMPLAIN_BUTTON_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backStageModifyEndOrderNotification:) name:BACK_STAGE_MODIFY_END_ORDER_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(backStageCancelOrderNotification:) name:BACK_STAGE_CANCEL_ORDR_NOTIFICATION object:nil];

}


(void)viewWillDisappear:(BOOL)animated

{

FLDDLogDebug(@”函数”);

[super viewWillDisappear:YES];


[[NSNotificationCenter defaultCenter] removeObserver:self name:PASSENGER_PAY_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self name:HIDDEN_COMPLAIN_BUTTON_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self name:BACK_STAGE_MODIFY_END_ORDER_NOTIFICATION object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self name:BACK_STAGE_CANCEL_ORDR_NOTIFICATION object:nil];

}

                if (NO == [[Singleton sharedInstance] getNeedReloginFlag])
                {

setNeedReloginFlag:YES];

// 账号被踢出

[[NSNotificationCenter defaultCenter] postNotificationName:PresentFirstViewControllerNotification object:nil];

}


(void)PresentFirstViewControllerNotification

{

if (nil == [GlobalShare getGlobalShare].user)

{

return;

}

FLDDLogDebug(@”PresentFirstViewControllerNotification”);

if((LOGIN_ORDER_STATE_SUCESS == [[Singleton sharedInstance] getLoginOrderStat]) || (LOGIN_ORDER_STATE_SUCESS_NO_MAIN_VIEW == [[Singleton sharedInstance] getLoginOrderStat]))

{

// [[NSNotificationCenter defaultCenter] postNotificationName:REMOVE_MAIN_VIEW_CONTROL_NOTIFICATION object:nil];

}

if ([NSThread isMainThread])

{

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@”温馨提示” message:@”您的账号已经在其他设备上登陆!” delegate:self cancelButtonTitle:@”重新登录” otherButtonTitles:nil, nil];

@try

{

[alertView show];

}

@catch (NSException *exception) {

}

}

else

{

dispatch_sync(dispatch_get_main_queue(), ^{

UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@”温馨提示” message:@”您的账号已经在其他设备上登陆!” delegate:self cancelButtonTitle:@”重新登录” otherButtonTitles:nil, nil];

@try

{

[alertView show];

}

@catch (NSException *exception) {

}

});

}


[self PresentFirstViewController];

}


(void)PresentFirstViewController

{


[SVProgressHUD dismiss];

[self ClearUserInfo];

FirstViewController *firstVC = [[FirstViewController alloc] initWithNibName:NSStringFromClass([FirstViewController class]) bundle:nil];

firstNav = [[UINavigationController alloc] initWithRootViewController:firstVC];

FLDDLogDebug(@”%@”, firstNav);


UIViewController *viewController = [CGeneralFunction findCurrentResponderViewController];

if (![viewController isKindOfClass:[StartOrderViewController class]] || ![viewController isKindOfClass:[FirstViewController class]])

{

[viewController dismissViewControllerAnimated:NO completion:^{

}];

}

[self presentViewController:firstNav animated:YES completion:^{

[[NSNotificationCenter defaultCenter] postNotificationName:REMOVE_MAIN_VIEW_CONTROL_NOTIFICATION object:nil];

}];

}

这个方案的优点是内存利用率高,不用频繁的申请申请过的页面;缺点时,当重新跳到这个已经存在的页面时要保证你的数据与页面元素都被初始化,该替换为新数据的换为新数据,要防止重复注册相同的通知。


方法二最直接:

想要跳到哪个页面,在self.navigationController.viewControllers或app.window.rootViewController.childViewControllers找它,若它存在直接删掉它,重新申请一个新的,跳转过去就可以了。每次都保证你的页面是唯一的,每次进入页面都是新面孔,不用再为了喜新厌旧老数据而纠结了。当然若你的应用存在侧边栏就要注意了,想从侧边栏进入主页面不是那么容易,必定他们在两个不同的控制器,你找不到所以删除不了,搞不好你会产生两个相同的主页面。

            AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;
            UINavigationController *rootCT = [app.window.rootViewController.childViewControllers firstObject];
            FLDDLogDebug(@"  %@",rootCT.viewControllers);
            for (UIViewController *viewController in rootCT.viewControllers) {
                if ([viewController isKindOfClass:[MainViewController class]]) {
                    [viewController removeFromParentViewController];
                    break;
                }
            }
            MainViewController *mainVC = [[MainViewController alloc] initWithNibName:NSStringFromClass([MainViewController class]) bundle:nil];
            if((nil != rootCT) && (nil != mainVC))
            {
                MainViewController *mainVC = [[MainViewController alloc] init];
                mainVC.isBookingServicing = YES;
                [self dismissViewControllerAnimated:YES completion:^{
                    [self.navigationController popToRootViewControllerAnimated:YES];
                }];
            }




事例二:
            for (UIViewController *viewController in self.navigationController.viewControllers) {
                if ([viewController isKindOfClass:[MainViewController class]]) {
                    [viewController removeFromParentViewController];
                    break;
                }
            }


            MainViewController *mainVC = [[MainViewController alloc] initWithNibName:NSStringFromClass([MainViewController class]) bundle:nil];
            if((nil != self.navigationController) && (nil != mainVC))
            {
                [self.navigationController pushViewController:mainVC animated:YES];
            }

优缺点就不用说了吧?你明白的。

目录
相关文章
|
19天前
|
前端开发 JavaScript 索引
改变数组页面重新渲染的操作/那些操作不会重新渲染页面以及解决方法
改变数组页面重新渲染的操作/那些操作不会重新渲染页面以及解决方法
16 2
|
19天前
|
小程序
小程序和页面生命周期详解
小程序和页面生命周期详解
19 0
|
19天前
|
JavaScript 前端开发 API
vue改变数组页面重新渲染的操作/那些操作不会重新渲染页面以及解决方法
vue改变数组页面重新渲染的操作/那些操作不会重新渲染页面以及解决方法
16 2
|
19天前
|
JavaScript
在Vue中,如何保证事件监听器的注册和清除操作在正确的生命周期执行?
在Vue中,如何保证事件监听器的注册和清除操作在正确的生命周期执行?
35 2
|
11月前
|
小程序
小程序生命周期和页面生命周期的详情讲解
小程序生命周期和页面生命周期的详情讲解
60 0
|
7月前
|
小程序 JavaScript
小程序 observers--组件访问页面钩子
小程序 observers--组件访问页面钩子
175 1
|
8月前
|
小程序 前端开发 JavaScript
小程序框架语法详解以及页面生命周期的代码预演
小程序框架语法详解以及页面生命周期的代码预演
56 0
|
9月前
|
JavaScript API
更改redux 数据,页面未重新渲染
更改redux 数据,页面未重新渲染
|
10月前
Vue3新增的两个生命周期分析解释【onRenderTracked()状态跟踪和onRenderTriggered() 状态触发】
Vue3新增的两个生命周期分析解释【onRenderTracked()状态跟踪和onRenderTriggered() 状态触发】
|
前端开发 开发者
评论列表案例-创建 CmtList 组件并渲染基本页面结构|学习笔记
快速学习评论列表案例-创建 CmtList 组件并渲染基本页面结构
113 0
评论列表案例-创建 CmtList 组件并渲染基本页面结构|学习笔记