iOS 10 added a new `textFieldDidEndEditing:reason:` to `UITextField`. It gets called, if set, before the older `textFieldDidEndEditing`. This cause a problem for code that does add events for both since the internal `*Delegate` does override both (to allow events) so the call might be "lost" without additional logic. This fix makes sure that even using one (or the two) events will work across all versions of iOS. reference: https://bugzilla.xamarin.com/show_bug.cgi?id=53174
This commit is contained in:
Родитель
2380389278
Коммит
7f6f2bf81d
|
@ -1969,6 +1969,7 @@ namespace XamCore.UIKit {
|
|||
[iOS (10,0), TV (10,0), NoWatch]
|
||||
[Native]
|
||||
public enum UITextFieldDidEndEditingReason : nint {
|
||||
Unknown = -1, // helper value (not in headers)
|
||||
Committed,
|
||||
[NoiOS]
|
||||
Cancelled
|
||||
|
|
|
@ -7,10 +7,210 @@
|
|||
// Copyright 2009, Novell, Inc.
|
||||
//
|
||||
|
||||
#if !WATCH
|
||||
#if !WATCH && !COREBUILD
|
||||
|
||||
using System;
|
||||
using XamCore.Foundation;
|
||||
using XamCore.ObjCRuntime;
|
||||
|
||||
namespace XamCore.UIKit {
|
||||
|
||||
public partial class UITextFieldEditingEndedEventArgs : EventArgs {
|
||||
public UITextFieldEditingEndedEventArgs (UITextFieldDidEndEditingReason reason)
|
||||
{
|
||||
this.Reason = reason;
|
||||
}
|
||||
public UITextFieldDidEndEditingReason Reason { get; set; }
|
||||
}
|
||||
|
||||
public delegate bool UITextFieldChange (UITextField textField, NSRange range, string replacementString);
|
||||
|
||||
public delegate bool UITextFieldCondition (UITextField textField);
|
||||
|
||||
public partial class UITextField : IUITextInputTraits {
|
||||
|
||||
internal virtual Type GetInternalEventDelegateType
|
||||
{
|
||||
get { return typeof (_UITextFieldDelegate); }
|
||||
}
|
||||
|
||||
internal virtual _UITextFieldDelegate CreateInternalEventDelegateType ()
|
||||
{
|
||||
return (_UITextFieldDelegate)(new _UITextFieldDelegate());
|
||||
}
|
||||
|
||||
internal _UITextFieldDelegate EnsureUITextFieldDelegate ()
|
||||
{
|
||||
#if XAMCORE_2_0
|
||||
if (Delegate != null)
|
||||
UIApplication.EnsureEventAndDelegateAreNotMismatched (Delegate, GetInternalEventDelegateType);
|
||||
_UITextFieldDelegate del = Delegate as _UITextFieldDelegate;
|
||||
if (del == null){
|
||||
del = (_UITextFieldDelegate)CreateInternalEventDelegateType ();
|
||||
Delegate = (IUITextFieldDelegate)del;
|
||||
}
|
||||
return del;
|
||||
#else
|
||||
var del = Delegate;
|
||||
if (del == null || (!(del is _UITextFieldDelegate))){
|
||||
del = new _UITextFieldDelegate ();
|
||||
Delegate = del;
|
||||
}
|
||||
return (_UITextFieldDelegate) del;
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma warning disable 672
|
||||
[Register]
|
||||
#if XAMCORE_2_0
|
||||
internal class _UITextFieldDelegate : NSObject, IUITextFieldDelegate {
|
||||
#else
|
||||
internal class _UITextFieldDelegate : UITextFieldDelegate {
|
||||
#endif
|
||||
public _UITextFieldDelegate () { IsDirectBinding = false; }
|
||||
|
||||
internal EventHandler editingEnded;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldDidEndEditing:")]
|
||||
public void EditingEnded (UITextField textField)
|
||||
{
|
||||
EventHandler handler = editingEnded;
|
||||
if (handler != null){
|
||||
handler (textField, EventArgs.Empty);
|
||||
} else {
|
||||
// if this is executed before iOS10 and only the new API is used we'll raise the new event (if set)
|
||||
EventHandler<UITextFieldEditingEndedEventArgs> handler2 = editingEnded1;
|
||||
if (handler2 != null) {
|
||||
var args = new UITextFieldEditingEndedEventArgs (UITextFieldDidEndEditingReason.Unknown);
|
||||
handler2 (textField, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal EventHandler<UITextFieldEditingEndedEventArgs> editingEnded1;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldDidEndEditing:reason:")]
|
||||
public void EditingEnded (UITextField textField, UITextFieldDidEndEditingReason reason)
|
||||
{
|
||||
EventHandler<UITextFieldEditingEndedEventArgs> handler = editingEnded1;
|
||||
if (handler != null) {
|
||||
var args = new UITextFieldEditingEndedEventArgs (reason);
|
||||
handler (textField, args);
|
||||
} else {
|
||||
// if this is executed on iOS10 (or late) and only the old API is used then we'll raise the old event (if set)
|
||||
EventHandler handler2 = editingEnded;
|
||||
if (handler2 != null)
|
||||
handler2 (textField, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
internal EventHandler editingStarted;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldDidBeginEditing:")]
|
||||
public void EditingStarted (UITextField textField)
|
||||
{
|
||||
EventHandler handler = editingStarted;
|
||||
if (handler != null){
|
||||
handler (textField, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
internal UITextFieldCondition shouldBeginEditing;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldShouldBeginEditing:")]
|
||||
public bool ShouldBeginEditing (UITextField textField)
|
||||
{
|
||||
UITextFieldCondition handler = shouldBeginEditing;
|
||||
if (handler != null)
|
||||
return handler (textField);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal UITextFieldChange shouldChangeCharacters;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textField:shouldChangeCharactersInRange:replacementString:")]
|
||||
public bool ShouldChangeCharacters (UITextField textField, NSRange range, string replacementString)
|
||||
{
|
||||
UITextFieldChange handler = shouldChangeCharacters;
|
||||
if (handler != null)
|
||||
return handler (textField, range, replacementString);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal UITextFieldCondition shouldClear;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldShouldClear:")]
|
||||
public bool ShouldClear (UITextField textField)
|
||||
{
|
||||
UITextFieldCondition handler = shouldClear;
|
||||
if (handler != null)
|
||||
return handler (textField);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal UITextFieldCondition shouldEndEditing;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldShouldEndEditing:")]
|
||||
public bool ShouldEndEditing (UITextField textField)
|
||||
{
|
||||
UITextFieldCondition handler = shouldEndEditing;
|
||||
if (handler != null)
|
||||
return handler (textField);
|
||||
return true;
|
||||
}
|
||||
|
||||
internal UITextFieldCondition shouldReturn;
|
||||
[Preserve (Conditional = true)]
|
||||
[Export ("textFieldShouldReturn:")]
|
||||
public bool ShouldReturn (UITextField textField)
|
||||
{
|
||||
UITextFieldCondition handler = shouldReturn;
|
||||
if (handler != null)
|
||||
return handler (textField);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#pragma warning restore 672
|
||||
|
||||
public event EventHandler Ended {
|
||||
add { EnsureUITextFieldDelegate ().editingEnded += value; }
|
||||
remove { EnsureUITextFieldDelegate ().editingEnded -= value; }
|
||||
}
|
||||
|
||||
public event EventHandler<UITextFieldEditingEndedEventArgs> EndedWithReason {
|
||||
add { EnsureUITextFieldDelegate ().editingEnded1 += value; }
|
||||
remove { EnsureUITextFieldDelegate ().editingEnded1 -= value; }
|
||||
}
|
||||
|
||||
public event EventHandler Started {
|
||||
add { EnsureUITextFieldDelegate ().editingStarted += value; }
|
||||
remove { EnsureUITextFieldDelegate ().editingStarted -= value; }
|
||||
}
|
||||
|
||||
public UITextFieldCondition ShouldBeginEditing {
|
||||
get { return EnsureUITextFieldDelegate ().shouldBeginEditing; }
|
||||
set { EnsureUITextFieldDelegate ().shouldBeginEditing = value; }
|
||||
}
|
||||
|
||||
public UITextFieldChange ShouldChangeCharacters {
|
||||
get { return EnsureUITextFieldDelegate ().shouldChangeCharacters; }
|
||||
set { EnsureUITextFieldDelegate ().shouldChangeCharacters = value; }
|
||||
}
|
||||
|
||||
public UITextFieldCondition ShouldClear {
|
||||
get { return EnsureUITextFieldDelegate ().shouldClear; }
|
||||
set { EnsureUITextFieldDelegate ().shouldClear = value; }
|
||||
}
|
||||
|
||||
public UITextFieldCondition ShouldEndEditing {
|
||||
get { return EnsureUITextFieldDelegate ().shouldEndEditing; }
|
||||
set { EnsureUITextFieldDelegate ().shouldEndEditing = value; }
|
||||
}
|
||||
|
||||
public UITextFieldCondition ShouldReturn {
|
||||
get { return EnsureUITextFieldDelegate ().shouldReturn; }
|
||||
set { EnsureUITextFieldDelegate ().shouldReturn = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11678,7 +11678,8 @@ namespace XamCore.UIKit {
|
|||
UITableViewRowAction Create (UITableViewRowActionStyle style, [NullAllowed] string title, Action<UITableViewRowAction, NSIndexPath> handler);
|
||||
}
|
||||
|
||||
[BaseType (typeof (UIControl), Delegates=new string [] { "WeakDelegate" }, Events=new Type [] {typeof(UITextFieldDelegate)})]
|
||||
[BaseType (typeof (UIControl), Delegates=new string [] { "WeakDelegate" })]
|
||||
// , Events=new Type [] {typeof(UITextFieldDelegate)})] custom logic needed, see https://bugzilla.xamarin.com/show_bug.cgi?id=53174
|
||||
interface UITextField : UITextInput, UIContentSizeCategoryAdjusting {
|
||||
[Export ("initWithFrame:")]
|
||||
IntPtr Constructor (CGRect frame);
|
||||
|
|
Загрузка…
Ссылка в новой задаче