diff --git a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/AuthenticationViewController.cs b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/AuthenticationViewController.cs
index e06c1c8e..a1c909c3 100644
--- a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/AuthenticationViewController.cs
+++ b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/AuthenticationViewController.cs
@@ -1,7 +1,6 @@
using LocalAuthentication;
namespace StoryboardTable;
-
/*
* https://developer.apple.com/ios/human-interface-guidelines/user-interaction/authentication/
*
@@ -19,137 +18,102 @@ namespace StoryboardTable;
///
partial class AuthenticationViewController : UIViewController
{
- LAContextReplyHandler replyHandler;
+ LAContextReplyHandler? replyHandler;
/// String to use for display
- string BiometryType = "";
+ string BiometryType = string.Empty;
- public AuthenticationViewController(IntPtr handle) : base(handle)
+ public AuthenticationViewController (IntPtr handle) : base (handle)
{
}
- public override void ViewWillAppear(bool animated)
+ public override void ViewWillAppear (bool animated)
{
- base.ViewWillAppear(animated);
+ 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 context = new LAContext ();
+ 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";
}
- AuthenticateButton.SetTitle(buttonText, UIControlState.Normal);
+ AuthenticateButton.SetTitle (buttonText, UIControlState.Normal);
}
- partial void AuthenticateMe(UIButton sender)
+ partial void AuthenticateMe (UIButton sender)
{
- var context = new LAContext();
+ var context = new LAContext ();
NSError AuthError;
- var localizedReason = new NSString("To access secrets");
+ var localizedReason = new NSString ("To access secrets");
// 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}!");
-
- PerformSegue("AuthenticationSegue", this);
- }
- else
- {
- Console.WriteLine(error.LocalizedDescription);
+ this.InvokeOnMainThread ( () => {
+ if (success) {
+ PerformSegue ("AuthenticationSegue", this);
+ } 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);
+ 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}!");
-
- PerformSegue("AuthenticationSegue", this);
- }
- else
- {
- Console.WriteLine(error.LocalizedDescription);
+ this.InvokeOnMainThread ( () => {
+ if (success) {
+ PerformSegue ("AuthenticationSegue", this);
+ } 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
- {
+ context.EvaluatePolicy (LAPolicy.DeviceOwnerAuthentication, localizedReason, replyHandler);
+ } 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";
- var okCancelAlertController = UIAlertController.Create("No authentication", "This device does't have authentication configured.", UIAlertControllerStyle.Alert);
- okCancelAlertController.AddAction(UIAlertAction.Create("Use unsecured", UIAlertActionStyle.Default, alert => PerformSegue("AuthenticationSegue", this)));
- okCancelAlertController.AddAction(UIAlertAction.Create("Cancel", UIAlertActionStyle.Cancel, alert => Console.WriteLine("Cancel was clicked")));
- PresentViewController(okCancelAlertController, true, null);
+ var okCancelAlertController = UIAlertController.Create ("No authentication", "This device does't have authentication configured.", UIAlertControllerStyle.Alert);
+ okCancelAlertController.AddAction(UIAlertAction.Create ("Use unsecured", UIAlertActionStyle.Default, alert => PerformSegue ("AuthenticationSegue", this)));
+ okCancelAlertController.AddAction(UIAlertAction.Create ("Cancel", UIAlertActionStyle.Cancel, alert => Console.WriteLine ("Cancel was clicked")));
+ PresentViewController (okCancelAlertController, true, null);
}
}
}
diff --git a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/DetailViewController.cs b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/DetailViewController.cs
index fd436caa..9e5f2b4f 100644
--- a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/DetailViewController.cs
+++ b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/DetailViewController.cs
@@ -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 ();
}
diff --git a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/GlobalSuppressions.cs b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/GlobalSuppressions.cs
new file mode 100644
index 00000000..5b3e7a67
--- /dev/null
+++ b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/GlobalSuppressions.cs
@@ -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 = "", Scope = "member", Target = "~M:StoryboardTable.SecretTableSource.GetCell(UIKit.UITableView,Foundation.NSIndexPath)~UIKit.UITableViewCell")]
diff --git a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/MasterViewController.cs b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/MasterViewController.cs
index 87ca58fd..fc4d0278 100755
--- a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/MasterViewController.cs
+++ b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/MasterViewController.cs
@@ -12,6 +12,6 @@ public partial class MasterViewController : UITableViewController
base.ViewWillAppear (animated);
// bind every time, to reflect deletion in the Detail view
- TableView.Source = new SecretTableSource();
+ TableView.Source = new SecretTableSource ();
}
}
diff --git a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretItem.cs b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretItem.cs
index 8ec038c6..fc2f1cd0 100644
--- a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretItem.cs
+++ b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretItem.cs
@@ -3,7 +3,7 @@ namespace StoryboardTable;
///
/// Represents a Chore.
///
-///
+///
public class SecretItem {
public SecretItem ()
@@ -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; }
}
diff --git a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretTableSource.cs b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretTableSource.cs
index ceaf1aed..fe02df78 100644
--- a/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretTableSource.cs
+++ b/dotnet/ios/ios11/FaceIDSample/LocalAuthentication/SecretTableSource.cs
@@ -9,25 +9,35 @@ public class SecretTableSource : UITableViewSource {
public SecretTableSource ()
{
tableItems = new List {
- new SecretItem() {Name="Gift list", Notes="iPhone X, Apple Watch, HomePod", Done=false},
- new SecretItem() {Name="Reminders", Notes="buy flowers", Done=false}
- }.ToArray();
+ new SecretItem () {Name="Gift list", Notes="iPhone X, Apple Watch, HomePod", Done=false},
+ new SecretItem () {Name="Reminders", Notes="buy flowers", Done=false}
+ }.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
- cell.TextLabel.Text = tableItems[indexPath.Row].Name;
- cell.DetailTextLabel.Text = tableItems[indexPath.Row].Notes;
+
+ // 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)
+ public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
{
- tableView.DeselectRow(indexPath, true);
+ tableView.DeselectRow (indexPath, true);
}
}