Xamarin.iOS中Async/Await场景下PerformSegue失效问题求助
分析与解决方案
首先,咱们先拆解你遇到的问题:在异步事件处理方法里调用PerformSegue没反应,但同步调用就正常,试过主线程调度也没用。我遇到过类似的情况,大概率是这几个原因:
1. Async Void 导致的异常静默丢失
你用的async private void作为事件处理方法,这种写法虽然符合事件签名,但有个致命问题:如果InvokeApiAsync抛出异常,这个异常会直接被.NET Runtime吞掉(不会冒泡到调用栈),导致你的if (searchItemsResult != null)代码块根本没执行!
验证方法
给你的异步方法加个try-catch,看看是不是API调用抛出了异常:
async private void SearchButton_TouchUpInside(object sender, EventArgs e) { try { var dictionary = new Dictionary<string, string> { {"searchText", "abc" } }; searchItemsResult = await client.InvokeApiAsync<items>("search/searchitems", HttpMethod.Get, dictionary); if (searchItemsResult != null) { Console.WriteLine("准备执行Segue"); // 加个日志确认走到这里了 InvokeOnMainThread(() => { this.PerformSegue("vC2Segue", this); }); } } catch (Exception ex) { Console.WriteLine($"API调用出错:{ex.Message}"); } }
如果控制台输出了异常信息,那就是这个问题——你之前以为API返回了结果,其实是调用失败了,代码根本没走到PerformSegue那一步。
2. Segue 配置的隐性错误
虽然你移除async/await后能正常跳转,但还是要再确认一遍:
- 检查Storyboard里的segue标识符是不是完全匹配
"vC2Segue"(大小写敏感!) - 确认segue是从当前ViewController直接连到目标ViewController,而不是从按钮直接连的(如果是按钮直接连的segue,点击按钮会自动触发,和你的代码逻辑冲突)
3. 主线程调度的正确姿势
你之前的代码里注释了两种主线程调度方式,但可能没正确包裹或者存在上下文问题。试试用BeginInvokeOnMainThread(Xamarin.iOS专用的主线程调度方法),并且确保调用时当前ViewController是活跃状态:
if (searchItemsResult != null) { BeginInvokeOnMainThread(() => { if (this.IsViewLoaded && this.View.Window != null) { // 确认VC处于活跃状态 this.PerformSegue("vC2Segue", this); } }); }
更健壮的写法建议
把异步逻辑抽成单独的async Task方法,这样更容易管理异常和调试:
public override void ViewDidLoad() { base.ViewDidLoad(); searchButton.TouchUpInside += async (s, e) => await HandleSearchAsync(); } private async Task HandleSearchAsync() { try { var dictionary = new Dictionary<string, string> { {"searchText", "abc" } }; searchItemsResult = await client.InvokeApiAsync<items>("search/searchitems", HttpMethod.Get, dictionary); if (searchItemsResult != null) { BeginInvokeOnMainThread(() => { this.PerformSegue("vC2Segue", this); }); } } catch (Exception ex) { // 这里可以弹个Alert提示用户搜索失败 BeginInvokeOnMainThread(() => { var alert = UIAlertController.Create("错误", "搜索失败,请稍后重试", UIAlertControllerStyle.Alert); alert.AddAction(UIAlertAction.Create("确定", UIAlertActionStyle.Default, null)); PresentViewController(alert, true, null); }); } }
先按这个步骤排查,最可能的就是异步方法里的异常没被捕获,导致代码没执行到PerformSegue。如果还是不行,可以再检查下当前ViewController是否被UINavigationController托管(如果你的Segue是push类型的话,必须在导航栈里)。
内容的提问来源于stack exchange,提问作者John D
相关产品推荐
相关产品推荐

