Xamarin iOS自定义键盘无法正常工作

时间:2018-02-22 14:29:12

标签: ios xamarin custom-keyboard

我正在为我的应用程序开发键盘扩展,并且遇到一些问题。我需要将一些少量数据从主应用程序传输到键盘。为此,我将值写入NSUserDefaults,它们在app和extension之间共享。我还在用户默认值的某些键中添加了观察者,以跟踪值何时更改并采取适当的操作。 它必须按以下顺序工作:键盘将某些内容写入用户默认值 - >观察者在申请中被解雇 - >应用程序写入响应 - >观察者在键盘上发射。他们为不同的密钥写入值。 这是在键盘中注册观察者的代码:

    void RegisterObservers()
    {
        byte[] buff = new byte[4];
        rng.GetNonZeroBytes(buff);
        appRunToken = (IntPtr)buff[0];
        accountsToken = (IntPtr)buff[1];
        passwordToken = (IntPtr)buff[2];
        otpToken = (IntPtr)buff[3];

        plist.AddObserver(this, (NSString)"AppRun",
                              NSKeyValueObservingOptions.Old | NSKeyValueObservingOptions.New,
                              appRunToken);
        plist.AddObserver(this, (NSString)"Accounts",
                              NSKeyValueObservingOptions.Old | NSKeyValueObservingOptions.New,
                              accountsToken);
        plist.AddObserver(this, (NSString)"CurrentPassword",
                              NSKeyValueObservingOptions.Old | NSKeyValueObservingOptions.New,
                              passwordToken);
        plist.AddObserver(this, (NSString)"CurrentOTP",
                              NSKeyValueObservingOptions.Old | NSKeyValueObservingOptions.New,
                              passwordToken);
    }

当其中一个观察者触发时调用此方法:

// NSUserDefaults observer
    public override void ObserveValue(NSString keyPath, NSObject ofObject, NSDictionary change, IntPtr context)
    {
        try
        {
            if (context == appRunToken)
            {
                Console.WriteLine(">>>Observer fired: appRunToken");
                // some strange workaround to get bool from change dictionary
                if (((NSNumber)change.ValueForKey((NSString)"new")).Equals(new NSNumber(0)))
                    AppRunChangedEvent?.Invoke(new AppRunChangedEventArgs(false));
                else
                    AppRunChangedEvent?.Invoke(new AppRunChangedEventArgs(true));
            }
            else if (context == accountsToken)
            {
                Console.WriteLine(">>>Observer fired: accountsToken");
            }
            else if (context == passwordToken)
            {
                Console.WriteLine(">>>Observer fired: passwordToken");
                PasswordChangedEvent.Invoke(new PasswordChangedEventArgs(plist.StringForKey("someRandomStringGeneratedAutomatically")));
                plist.SetString("", "someRandomStringGeneratedAutomatically");
            } 
            else if (context == otpToken) 
            {
                Console.WriteLine(">>>Observer fired: otp token");
                OTPChangedEvent.Invoke(new OTPChangedEventArgs(plist.StringForKey("CurrentOtp")));
                plist.SetString("", "CurrentOtp");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

在主要应用中使用相同的方法。 问题是,在将信息写入用户默认值后,键盘冻结。在我执行手势以隐藏键盘后,它隐藏着拉扯,再次打开后我在控制台中多次输出:

Full thread dump:

"<unnamed thread>"
"<unnamed thread>"
"Finalizer"
"<unnamed thread>"
"Debugger agent"

然后键盘切换到上一个。

有时UI只是冻结而没有任何输出,有时观察者根本不会开火。

然后我试图摆脱键盘中的观察者并在使用Task.Delay(200)延迟后从NSUserDefaults读取值。看起来200足以让应用程序对NSUserDefaults值更改和写入响应做出反应。我有像以前一样的行为,除了控制台消息。现在它就像

Full thread dump:

"Debugger agent"
"<unnamed thread>"
"Finalizer"
"<unnamed thread>"
"Threadpool worker"
"<unnamed thread>"
"Timer-Scheduler" at <unknown> <0xffffffff>
at (wrapper managed-to-native) System.Threading.WaitHandle.WaitOne_internal (intptr,int) <0x00007>
at System.Threading.WaitHandle.WaitOneNative (System.Runtime.InteropServices.SafeHandle,uint,bool,bool) [0x0000a] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/corlib/System.Threading/WaitHandle.cs:104
at System.Threading.WaitHandle.InternalWaitOne (System.Runtime.InteropServices.SafeHandle,long,bool,bool) [0x00014] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/waithandle.cs:250
at System.Threading.WaitHandle.WaitOne (long,bool) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/waithandle.cs:239
at System.Threading.WaitHandle.WaitOne (int,bool) [0x00019] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/waithandle.cs:206
at System.Threading.WaitHandle.WaitOne (int) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/waithandle.cs:227
at System.Threading.Timer/Scheduler.SchedulerThread () [0x0020b] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/corlib/System.Threading/Timer.cs:395
at System.Threading.ThreadHelper.ThreadStart_Context (object) [0x00014] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/thread.cs:68
at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00071] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:957
at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object,bool) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:904
at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext,System.Threading.ContextCallback,object) [0x0002b] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/executioncontext.cs:893
at System.Threading.ThreadHelper.ThreadStart () [0x00008] in /Library/Frameworks/Xamarin.iOS.framework/Versions/11.6.1.4/src/mono/mcs/class/referencesource/mscorlib/system/threading/thread.cs:105
at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) [0x0001e] in <d680a8bf3a2a4c8dbbfde665ba81f6f2>:0

"<unnamed thread>"
"<threadpool thread>"

有时候一切正常。 键盘和NSUserDefauts有什么问题?请帮我解决这个问题

更新即可。
我试图用CFNotificationCenter.Darwin观察者替换NSUserDefaults观察者并获得相同的行为。 Xamarin键盘的观察者到底怎么了?当我删除它们一切正常。看起来我必须在Swift中编写我的应用程序

0 个答案:

没有答案