зеркало из https://github.com/xamarin/ios-samples.git
nullability
This commit is contained in:
Родитель
8cd05dce4e
Коммит
a4088aa640
|
@ -1,7 +1,6 @@
|
|||
using LocalAuthentication;
|
||||
|
||||
namespace StoryboardTable;
|
||||
|
||||
/*
|
||||
* https://developer.apple.com/ios/human-interface-guidelines/user-interaction/authentication/
|
||||
*
|
||||
|
@ -19,9 +18,9 @@ namespace StoryboardTable;
|
|||
/// </remarks>
|
||||
partial class AuthenticationViewController : UIViewController
|
||||
{
|
||||
LAContextReplyHandler replyHandler;
|
||||
LAContextReplyHandler? replyHandler;
|
||||
/// <summary>String to use for display</summary>
|
||||
string BiometryType = "";
|
||||
string BiometryType = string.Empty;
|
||||
|
||||
public AuthenticationViewController (IntPtr handle) : base (handle)
|
||||
{
|
||||
|
@ -32,30 +31,22 @@ partial class AuthenticationViewController : UIViewController
|
|||
base.ViewWillAppear (animated);
|
||||
|
||||
// bind every time, to reflect deletion in the Detail view
|
||||
unAuthenticatedLabel.Text = "";
|
||||
unAuthenticatedLabel.Text = string.Empty;
|
||||
|
||||
var context = new LAContext ();
|
||||
var buttonText = "";
|
||||
if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out var authError1))
|
||||
{ // has Biometrics (Touch or Face)
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
|
||||
{
|
||||
var buttonText = string.Empty;
|
||||
if (context.CanEvaluatePolicy (LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out var authError1)) { // has Biometrics (Touch or Face)
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion (11, 0)) {
|
||||
context.LocalizedReason = "Authorize for access to secrets"; // iOS 11
|
||||
BiometryType = context.BiometryType == LABiometryType.TouchId ? "Touch ID" : "Face ID";
|
||||
buttonText = $"Login with {BiometryType}";
|
||||
}
|
||||
else
|
||||
{ // no FaceID before iOS 11
|
||||
} else { // no FaceID before iOS 11
|
||||
buttonText = $"Login with Touch ID";
|
||||
}
|
||||
}
|
||||
else if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthentication, out var authError2))
|
||||
{
|
||||
} else if (context.CanEvaluatePolicy (LAPolicy.DeviceOwnerAuthentication, out var authError2)) {
|
||||
buttonText = $"Login"; // with device PIN
|
||||
BiometryType = "Device PIN";
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// Application might choose to implement a custom username/password
|
||||
buttonText = "Use unsecured";
|
||||
BiometryType = "none";
|
||||
|
@ -72,76 +63,49 @@ partial class AuthenticationViewController : UIViewController
|
|||
// because LocalAuthentication APIs have been extended over time, need to check iOS version before setting some properties
|
||||
context.LocalizedFallbackTitle = "Fallback"; // iOS 8
|
||||
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion(10, 0))
|
||||
{
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion (10, 0)) {
|
||||
context.LocalizedCancelTitle = "Cancel"; // iOS 10
|
||||
}
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion(11, 0))
|
||||
{
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion (11, 0)) {
|
||||
context.LocalizedReason = "Authorize for access to secrets"; // iOS 11
|
||||
BiometryType = context.BiometryType == LABiometryType.TouchId ? "TouchID" : "FaceID";
|
||||
}
|
||||
|
||||
//Use canEvaluatePolicy method to test if device is TouchID or FaceID enabled
|
||||
//Use the LocalAuthentication Policy DeviceOwnerAuthenticationWithBiometrics
|
||||
if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out AuthError))
|
||||
{
|
||||
Console.WriteLine("TouchID/FaceID available/enrolled");
|
||||
replyHandler = new LAContextReplyHandler((success, error) =>
|
||||
{
|
||||
if (context.CanEvaluatePolicy (LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out AuthError)) {
|
||||
replyHandler = new LAContextReplyHandler ( (success, error) => {
|
||||
//Make sure it runs on MainThread, not in Background
|
||||
this.InvokeOnMainThread(() =>
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
Console.WriteLine($"You logged in with {BiometryType}!");
|
||||
|
||||
this.InvokeOnMainThread ( () => {
|
||||
if (success) {
|
||||
PerformSegue ("AuthenticationSegue", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(error.LocalizedDescription);
|
||||
} else {
|
||||
//Show fallback mechanism here
|
||||
unAuthenticatedLabel.Text = $"{BiometryType} Authentication Failed";
|
||||
//AuthenticateButton.Hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
//Use evaluatePolicy to start authentication operation and show the UI as an Alert view
|
||||
//Use the LocalAuthentication Policy DeviceOwnerAuthenticationWithBiometrics
|
||||
context.EvaluatePolicy (LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason, replyHandler);
|
||||
}
|
||||
else if (context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthentication, out AuthError))
|
||||
{
|
||||
Console.WriteLine("When TouchID/FaceID aren't available or enrolled, use the device PIN");
|
||||
replyHandler = new LAContextReplyHandler((success, error) =>
|
||||
{
|
||||
else if (context.CanEvaluatePolicy (LAPolicy.DeviceOwnerAuthentication, out AuthError)) {
|
||||
replyHandler = new LAContextReplyHandler ( (success, error) => {
|
||||
//Make sure it runs on MainThread, not in Background
|
||||
this.InvokeOnMainThread(() =>
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
Console.WriteLine($"You logged in with {BiometryType}!");
|
||||
|
||||
this.InvokeOnMainThread ( () => {
|
||||
if (success) {
|
||||
PerformSegue ("AuthenticationSegue", this);
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine(error.LocalizedDescription);
|
||||
} else {
|
||||
//Show fallback mechanism here
|
||||
unAuthenticatedLabel.Text = "Device PIN Authentication Failed";
|
||||
AuthenticateButton.Hidden = true;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
//Use evaluatePolicy to start authentication operation and show the UI as an Alert view
|
||||
//Use the LocalAuthentication Policy DeviceOwnerAuthenticationWithBiometrics
|
||||
context.EvaluatePolicy (LAPolicy.DeviceOwnerAuthentication, localizedReason, replyHandler);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
// User hasn't configured a PIN or any biometric auth.
|
||||
// App may implement its own login, or choose to allow open access
|
||||
unAuthenticatedLabel.Text = "No device auth configured";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
public partial class DetailViewController : UIViewController
|
||||
{
|
||||
object detailItem;
|
||||
object? detailItem;
|
||||
|
||||
public DetailViewController (IntPtr handle) : base (handle)
|
||||
{
|
||||
|
@ -21,7 +21,7 @@ public partial class DetailViewController : UIViewController
|
|||
void ConfigureView ()
|
||||
{
|
||||
// Update the user interface for the detail item
|
||||
if (IsViewLoaded && detailItem != null)
|
||||
if (IsViewLoaded && detailItem is not null)
|
||||
detailDescriptionLabel.Text = detailItem.ToString ();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// This file is used by Code Analysis to maintain SuppressMessage
|
||||
// attributes that are applied to this project.
|
||||
// Project-level suppressions either have no target or are given
|
||||
// a specific target and scoped to a namespace, type, member, etc.
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
[assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "<Pending>", Scope = "member", Target = "~M:StoryboardTable.SecretTableSource.GetCell(UIKit.UITableView,Foundation.NSIndexPath)~UIKit.UITableViewCell")]
|
|
@ -11,7 +11,7 @@ public class SecretItem {
|
|||
}
|
||||
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Notes { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Notes { get; set; } = string.Empty;
|
||||
public bool Done { get; set; }
|
||||
}
|
||||
|
|
|
@ -14,16 +14,26 @@ public class SecretTableSource : UITableViewSource {
|
|||
}.ToArray ();
|
||||
}
|
||||
public override nint RowsInSection (UITableView tableview, nint section)
|
||||
{
|
||||
return tableItems.Length;
|
||||
}
|
||||
=> tableItems.Length;
|
||||
|
||||
public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
|
||||
{
|
||||
// in a Storyboard, Dequeue will ALWAYS return a cell,
|
||||
UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);
|
||||
// now set the properties as normal
|
||||
|
||||
// Beginning in iOS 14, UITableViewCell has to use cell.ContentConfiguration
|
||||
// to add text
|
||||
if (UIDevice.CurrentDevice.CheckSystemVersion(14, 0)) {
|
||||
var content = cell.DefaultContentConfiguration;
|
||||
content.Text = tableItems[indexPath.Row].Name;
|
||||
content.SecondaryText = tableItems[indexPath.Row].Notes;
|
||||
cell.ContentConfiguration = content;
|
||||
} else {
|
||||
cell.TextLabel.Text = tableItems[indexPath.Row].Name;
|
||||
cell.DetailTextLabel.Text = tableItems[indexPath.Row].Notes;
|
||||
}
|
||||
|
||||
return cell;
|
||||
}
|
||||
public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
|
||||
|
|
Загрузка…
Ссылка в новой задаче