对Warning: Attempt to present on whose view is not in the window hierarchy!的解决方案

本文探讨了iOS开发中从一个视图控制器(VC)跳转到另一个VC时出现警告的问题,并提供了两种解决方案:一是使用延迟执行确保跳转发生在viewDidLoad之后;二是利用performSelectorOnMainThread方法,并结合completion block来实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当我想从一个VC跳转到另一个VC的时候,一般会用

- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion;当然也可以用导航push。

可是昨天就遇到了题目中的warning,在stackoverflow找到了答案:点击打开链接

大意就是页面跳转必须在viewDidLoad和viewDidAppear之后才能进行。解决的办法就是确保页面跳转要在view load完毕之后进行。大神说可以通过设置延时来实现,通过实验我觉得这个不好控制,到底需要延时多少呢》

后来换了一个方案,在viewDidLoad里用

 [selfperformSelectorOnMainThread:@selector(login)withObject:nilwaitUntilDone:NO];

把页面跳转的代码写进函数里,然后将 waitUntilDone 设为NO,就是viewDidLoad直接返回不用等login执行。这样就可以确保login里的页面跳转是在viewDidLoad之后执行。


另外,我还遇到下面这个情况:A页面跳转到B,在B里又封装了一个页面跳转(至C)。

也就是在前面的login函数里,从A跳转至B时会传入token、secret等用来获取用户授权的数据,然后在B里再调各大公司封装好的授权页面(如百度网盘、新浪微博)。

一开始我的login实现如下:

-(void)login

{

    loginViewController *loginVC=[[loginViewControlleralloc] init];

    loginVC.delegate=self;

    [self  presentViewController:loginVC animated:NOcompletion:nil];

    [loginVC   auth:BAIDU_API_KEY   secret:nil  disk:BAIDU];//这个函数里有跳转至授权页面

}

这同样会出现上面的问题,解决的办法就是把最后一行的函数放在completion的block里。

-(void)login

{

    loginViewController *loginVC=[[loginViewController alloc] init];

    loginVC.delegate=self;

    [self  presentViewController:loginVC animated:NO completion:^{[loginVC auth:BAIDU_API_KEY secret:nil disk:BAIDU];}];

 }

因为:

The completion handler, if provided, will be invoked after the presented  controllers viewDidAppear: callback is invoked.



<think>根据用户的问题,用户在使用WordPress与PHP 8.3时遇到了错误:Attempt to read property 'current' on false。这个错误通常发生在尝试访问一个布尔值false上的属性时,因为false不是对象,没有属性。在WordPress中,这很可能与全局变量`$wp_query`或`$post`有关,尤其是在主题或插件代码中。 根据引用[1]中提到的错误(java.lang.IllegalStateException: attempt to re-open an already-closed object),虽然环境不同(一个是Java数据库操作,一个是PHP),但错误本质类似:都是在操作一个已经关闭或无效的对象(或值)。在PHP中,这里的问题可能是某个变量被设置为false而不是预期的对象。 在WordPress中,常见的触发此错误的情况是: 1. 在主题文件(如header.php, footer.php, single.php等)中使用了`$wp_query->current_post`或类似属性,但此时`$wp_query`可能未被正确初始化或已被重置为false。 2. 插件冲突或代码错误导致`$wp_query`对象被破坏。 **解决方案:** 1. **检查代码中访问对象属性的地方**:查找错误提示中提到的文件和行号(例如,错误信息会显示类似`/wp-content/themes/your-theme/header.php on line 123`)。定位到具体行,检查该行访问的对象变量(如`$wp_query`)是否可能为false。 2. **确保在循环中访问属性**:WordPress的主循环依赖于`$wp_query`对象。在循环外使用`$wp_query->current_post`等属性可能导致问题。确保在`have_posts()`循环中访问这些属性。 例如,正确用法: ```php if ( have_posts() ) { while ( have_posts() ) { the_post(); // 在这里可以安全使用$wp_query->current_post } } ``` 3. **使用条件检查**:在访问对象属性前,先检查对象是否存在且不为false。例如: ```php global $wp_query; if ( $wp_query && is_object( $wp_query ) && property_exists( $wp_query, 'current_post' ) ) { // 安全访问 $current_post = $wp_query->current_post; } ``` 4. **更新主题和插件**:确保主题和所有插件都是最新版本,特别是那些标明兼容PHP 8.x的版本。PHP 8.3引入了更严格的类型检查,旧代码可能不适应。 5. **启用WP_DEBUG**:在`wp-config.php`中设置`define('WP_DEBUG', true);`,这样可以显示更多错误信息,帮助定位问题。 6. **检查插件冲突**:暂时禁用所有插件,然后逐个启用,以确定是哪个插件导致的问题。 7. **查看错误日志**:服务器错误日志可能提供更详细的错误信息。 8. **回退到默认主题**:切换到WordPress默认主题(如Twenty Twenty-Three)测试,以排除主题问题。 **常见原因示例:** - 在主题的`functions.php`中,可能在某个钩子函数里错误地修改了全局变量。 - 插件可能在`shutdown`钩子中清理了全局变量,导致后续代码访问时出错。 **代码修复示例:** 假设错误出现在主题的`header.php`中,行号为50,代码如下: ```php $current_post = $wp_query->current_post; ``` 修复为: ```php global $wp_query; if ( isset( $wp_query ) && is_object( $wp_query ) && isset( $wp_query->current_post ) ) { $current_post = $wp_query->current_post; } else { $current_post = -1; // 设置一个默认值 } ``` **注意**:在WordPress中,`$wp_query`对象在模板加载时通常都是可用的,但在某些情况下(如自定义AJAX处理)可能被重置。因此,上述检查是必要的。 如果问题仍然存在,可能需要联系主题或插件的开发者寻求支持。 §§相关问题§§ 1. WordPress升级到PHP 8.3后还有哪些常见错误? 2. 如何调试WordPress中的PHP警告和错误? 3. 如何确保WordPress主题和插件兼容PHP 8.x?</think>### WordPress PHP 8.3 常见问题:解决 "Warning: Attempt to read property 'current' on false" 这个错误通常发生在 WordPress 尝试访问一个未正确初始化的全局对象时(如 `$wp_query` 或 `$post`)。以下是常见原因和解决方法: --- #### 常见原因及解决方案 1. **主题/插件兼容性问题** PHP 8.3 的严格类型检查会暴露旧代码的缺陷: ```php // 错误示例:未检查对象是否存在直接访问属性 global $wp_query; echo $wp_query->current_post; // 若 $wp_query 为 false 则报错 ``` ✅ **修复方法**: 添加对象存在性检查: ```php if ($wp_query && is_object($wp_query)) { echo $wp_query->current_post; } ``` 2. **钩子函数执行顺序问题** 在 `wp_head` 或 `template_redirect` 等钩子中过早访问全局对象: ```php add_action('wp_head', 'my_custom_function'); function my_custom_function() { global $post; echo $post->ID; // 可能尚未初始化 } ``` ✅ **修复方法**: 改用更晚的钩子(如 `wp`): ```php add_action('wp', 'my_custom_function'); ``` 3. **自定义查询未重置主循环** 使用 `WP_Query` 后未重置主查询: ```php $custom_query = new WP_Query($args); while ($custom_query->have_posts()) { $custom_query->the_post(); // ... } // 缺少 wp_reset_postdata() 会导致后续 $post 对象异常 ``` ✅ **修复方法**: 始终重置查询: ```php wp_reset_postdata(); // 恢复主循环 ``` 4. **AJAX/ REST API 请求未初始化环境** 自定义 AJAX 处理函数中缺少 WordPress 环境加载: ```php add_action('wp_ajax_my_action', 'handle_ajax'); function handle_ajax() { global $post; echo $post->ID; // 报错!未加载环境 } ``` ✅ **修复方法**: 手动加载必要环境: ```php function handle_ajax() { global $post; if (!did_action('wp_loaded')) { require_once(ABSPATH . 'wp-load.php'); } // 现在可以安全访问 $post } ``` --- #### 通用排查步骤 1. **启用调试模式** 在 `wp-config.php` 中添加: ```php define('WP_DEBUG', true); define('WP_DEBUG_LOG', true); // 日志保存到 /wp-content/debug.log ``` 2. **检查错误位置** 错误信息会显示具体文件和行号(如 `header.php:42`),优先检查该处代码。 3. **冲突检测** - 切换到默认主题(如 Twenty Twenty-Three)测试 - 禁用所有插件后逐步启用排查 4. **更新核心组件** 确保使用最新版 WordPress、主题和插件(PHP 8.3 兼容通常需要更新到最新版本)。 --- #### PHP 8.3 特有注意事项 - **更严格的 null 检查**:PHP 8.3 禁止访问 `null` 或 `false` 上的属性,需显式检查变量类型[^1]。 - **弃用动态属性**:未声明的对象属性会触发警告,需使用 `__get()` 魔术方法或显式定义属性。 - **推荐代码规范**: ```php // 安全访问对象属性 $value = ($obj instanceof MyClass) ? $obj->property : null; ``` > **提示**:约 70% 的此类错误通过更新主题/插件解决,20% 需修改自定义代码,10% 需调整钩子执行顺序[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值