设置MKMapView的框架会导致FirstResponder辞职,但仅在带有拆分键盘的iPad上

设置MKMapView的框架会导致FirstResponder辞职,但仅在带有拆分键盘的iPad上,ipad,uikit,mkmapview,becomefirstresponder,Ipad,Uikit,Mkmapview,Becomefirstresponder,这有点奇怪,我不知道到底发生了什么。我使用的是一个带有自定义注释的MKMapView。在该注释中,我有一个可编辑的文本字段。当用户点击该字段时,键盘弹出,我通过移动/缩小地图视图并重新居中注释来响应。除了在带有分体式键盘的横向模式下的iPad上,一切都很好。只有在这种情况下,当我更改地图视图的框架时,它才会在文本字段上调用“resignFirstResponder”,并开始在屏幕外设置键盘动画。当它移到屏幕外时,我的代码会相应地移动/扩展我的地图视图以填充空间。然后,我的文本字段再次接收消息be

这有点奇怪,我不知道到底发生了什么。我使用的是一个带有自定义注释的MKMapView。在该注释中,我有一个可编辑的文本字段。当用户点击该字段时,键盘弹出,我通过移动/缩小地图视图并重新居中注释来响应。除了在带有分体式键盘的横向模式下的iPad上,一切都很好。只有在这种情况下,当我更改地图视图的框架时,它才会在文本字段上调用“resignFirstResponder”,并开始在屏幕外设置键盘动画。当它移到屏幕外时,我的代码会相应地移动/扩展我的地图视图以填充空间。然后,我的文本字段再次接收消息
becomeFirstResponder
。我检查了调用堆栈,这来自:
[UIView(Hierarchy)deferredBecomeFirstResponder]
。键盘又向上移动,我再次响应,循环继续:向上->向下->向上->向下->向上->向下…..不断地。辞职的FirstResponder肯定来自设置我的地图视图的框架。如果我在文本字段的
resignFirstResponder
上设置了一个中断,并检查了调用堆栈,那么上一个调用就是我对地图视图框架的设置。此外,如果我在键盘被解除时中断了响应该键盘的代码,我会在设置地图视图帧后立即在堆栈上注意到这些调用:

#6  0x001264cf in -[CTView resignFirstResponder]
#7  0x00e3bed7 in -[UIView setUserInteractionEnabled:] ()
#8  0x00710020 in ___lldb_unnamed_function213$$MapKit ()
#9  0x00714c14 in ___lldb_unnamed_function326$$MapKit ()
#10 0x00716f82 in ___lldb_unnamed_function361$$MapKit ()
#11 0x007168c4 in ___lldb_unnamed_function359$$MapKit ()
#12 0x00716068 in ___lldb_unnamed_function344$$MapKit ()
#13 0x00715c5c in ___lldb_unnamed_function343$$MapKit ()
#14 0x007198d0 in ___lldb_unnamed_function385$$MapKit ()
#15 0x0071a1ad in ___lldb_unnamed_function392$$MapKit ()
#16 0x0071a417 in ___lldb_unnamed_function396$$MapKit ()
#17 0x00711074 in ___lldb_unnamed_function255$$MapKit ()
我可以通过不调整地图视图的大小来解决这个问题。如果我不这样做,循环就永远不会开始。相反,如果我将地图视图放在容器视图中,在容器视图上设置
clipToBounds=YES
,在地图视图上设置no auto resizing,我可以调整容器视图的大小,并保持地图视图的大小不变……问题是这是一个解决方法。如果用户旋转iPad,我需要改变地图视图的大小,但这将开启这个丑陋的循环


有人知道发生了什么吗?

在调整大小期间,
MKMapView
可能会计算注释的位置在屏幕外,并转储或标记包含当前第一响应者的
UITextField
MKAnnotationView
。这会导致
UITextField
对其调用
ResignFirstResponder
。调整大小后,UIKit决定
UITextField
仍然应该是第一响应者。也许
UITextField
仍然有isFirstResponder==YES,因为这一系列动画是UIKit无法很好处理的边缘情况。UIKit然后显示键盘,触发您的代码,等等等等

您是否尝试过使用
UITextField
UIResponder
继承的方法?可能在调整动画大小期间设置canResignFirstResponder==否


或者,如果这是由
MKMapView
计算不应显示
MKAnnotationView
而触发的,您是否尝试过设置动画,以便注释永远不会被计算为在可见范围之外?

因此,最终我能找到的唯一解决方案是将文本字段作为MKMapView的子视图删除,并将其放置在MKMapView的superview中。据我所知,允许MKMapView的任何子视图成为第一响应者不是一个好主意。MKMapView倾向于“窃取”帧更改的第一响应者状态。如果您正在响应UIKeyboardNotification,这可能会导致奇怪的响应程序周期


无论如何,从地图视图中删除文本字段也会带来更好的UI体验。通过设置更改的动画,用户更明确地体验到了从“我正在操作此地图”到“我正在编辑此文本字段”的转变。在编辑期间禁用地图也会加强这一点。这需要做更多的工作,但最终证明是有价值的。

建议不错,但不幸的是没有成功。如果我为
canResignFirstResponder
返回
no
,在这种情况下,我会使用
EXC\u BAD\u访问崩溃。显然,MKMapView的这种行为是有原因的。我会将注释视图移动到地图的中心,以确保在动画开始之前它处于视图中。不管怎样,这似乎都没有帮助。我开始认为唯一的解决方案是将文本字段从注释视图中“撕裂”,并在编辑期间将其放置在superview中。