我正在为我的应用程序开发键盘扩展,并且遇到一些问题。我需要将一些少量数据从主应用程序传输到键盘。为此,我将值写入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中编写我的应用程序