Browse Source

Merge pull request #10190 from workgroupengineering/fixes/Warnings/Nullable/iOS

fix: iOS Nullable
Max Katz 2 years ago
parent
commit
e7e04a067f

+ 2 - 3
src/iOS/Avalonia.iOS/PlatformSettings.cs

@@ -1,8 +1,7 @@
+#nullable enable
 using System;
-using System.Linq;
 using Avalonia.Media;
 using Avalonia.Platform;
-using Foundation;
 using UIKit;
 
 namespace Avalonia.iOS;
@@ -10,7 +9,7 @@ namespace Avalonia.iOS;
 // TODO: ideally should be created per view/activity.
 internal class PlatformSettings : DefaultPlatformSettings
 {
-    private PlatformColorValues _lastColorValues;
+    private PlatformColorValues? _lastColorValues;
 
     public override PlatformColorValues GetColorValues()
     {

+ 5 - 3
src/iOS/Avalonia.iOS/Storage/IOSStorageItem.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
 using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
@@ -24,8 +23,11 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
 
         using (var doc = new UIDocument(url))
         {
-            _filePath = doc.FileUrl?.Path ?? url.FilePathUrl.Path;
-            Name = doc.LocalizedName ?? System.IO.Path.GetFileName(_filePath) ?? url.FilePathUrl.LastPathComponent;
+            _filePath = doc.FileUrl?.Path ?? url.FilePathUrl?.Path ?? string.Empty;
+            Name = doc.LocalizedName 
+                ?? System.IO.Path.GetFileName(_filePath) 
+                ?? url.FilePathUrl?.LastPathComponent
+                ?? string.Empty;
         }
     }
 

+ 55 - 26
src/iOS/Avalonia.iOS/TextInputResponder.cs

@@ -1,14 +1,13 @@
 using System;
 using System.Runtime.InteropServices;
-using System.Runtime.Versioning;
 using Avalonia.Controls.Presenters;
-using Foundation;
-using ObjCRuntime;
-using Avalonia.Input.TextInput;
 using Avalonia.Input;
 using Avalonia.Input.Raw;
+using Avalonia.Input.TextInput;
 using Avalonia.Logging;
 using CoreGraphics;
+using Foundation;
+using ObjCRuntime;
 using UIKit;
 // ReSharper disable InconsistentNaming
 // ReSharper disable StringLiteralTypo
@@ -25,6 +24,9 @@ partial class AvaloniaView
     [Adopts("UIKeyInput")]
     partial class TextInputResponder : UIResponder, IUITextInput
     {
+        private static AvaloniaEmptyTextPosition? _emptyPosition;
+        private static AvaloniaEmptyTextPosition EmptyPosition => _emptyPosition ??= new();
+
         private class AvaloniaTextRange : UITextRange, INSCopying
         {
             private UITextPosition? _start;
@@ -67,6 +69,15 @@ partial class AvaloniaView
             public NSObject Copy(NSZone? zone) => new AvaloniaTextPosition(Index);
         }
 
+        private class AvaloniaEmptyTextPosition : UITextPosition, INSCopying
+        {
+            public AvaloniaEmptyTextPosition()
+            {
+
+            }
+            public NSObject Copy(NSZone? zone) => this;
+        }
+
         public TextInputResponder(AvaloniaView view, ITextInputMethodClient client)
         {
             _view = view;
@@ -93,7 +104,25 @@ partial class AvaloniaView
 
         public override NSString TextInputContextIdentifier => new NSString(Guid.NewGuid().ToString());
 
-        public override UITextInputMode TextInputMode => UITextInputMode.CurrentInputMode;
+        public override UITextInputMode TextInputMode
+        {
+            get
+            {
+                var mode = UITextInputMode.CurrentInputMode;
+                // Can be empty see https://developer.apple.com/documentation/uikit/uitextinputmode/1614522-activeinputmodes
+                if (mode is null && UITextInputMode.ActiveInputModes.Length > 0)
+                {
+                    mode = UITextInputMode.ActiveInputModes[0];
+                }
+                // See: https://stackoverflow.com/a/33337483/20894223
+                if (mode is null)
+                {
+                    using var tv = new UITextView();
+                    mode = tv.TextInputMode;
+                }
+                return mode;
+            }
+        }
 
         [DllImport("/usr/lib/libobjc.dylib")]
         private static extern void objc_msgSend(IntPtr receiver, IntPtr selector, IntPtr arg);
@@ -105,8 +134,8 @@ partial class AvaloniaView
         private readonly AvaloniaView _view;
         private string? _markedText;
 
-        
-        
+
+
         private void SurroundingTextChanged(object? sender, EventArgs e)
         {
             Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "SurroundingTextChanged");
@@ -153,9 +182,9 @@ partial class AvaloniaView
                 switch (ReturnKeyType)
                 {
                     case UIReturnKeyType.Done:
-                        case UIReturnKeyType.Go:
-                        case UIReturnKeyType.Send:
-                        case UIReturnKeyType.Search:
+                    case UIReturnKeyType.Go:
+                    case UIReturnKeyType.Send:
+                    case UIReturnKeyType.Search:
                         ResignFirstResponder();
                         break;
                 }
@@ -164,7 +193,7 @@ partial class AvaloniaView
 
             TextInput(text);
         }
-        
+
         void IUIKeyInput.DeleteBackward() => KeyPress(Key.Back);
 
         bool IUIKeyInput.HasText => true;
@@ -176,8 +205,8 @@ partial class AvaloniaView
             Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.TextInRange {start} {end}", r.StartIndex, r.EndIndex);
 
             string result = "";
-            if(string.IsNullOrEmpty(_markedText))
-                result = s.Text[r.StartIndex .. r.EndIndex];
+            if (string.IsNullOrEmpty(_markedText))
+                result = s.Text[r.StartIndex..r.EndIndex];
             else
             {
                 var span = new CombinedSpan3<char>(s.Text.AsSpan().Slice(0, s.CursorOffset),
@@ -214,7 +243,7 @@ partial class AvaloniaView
         void IUITextInput.UnmarkText()
         {
             Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "IUIKeyInput.UnmarkText");
-            if(_markedText == null)
+            if (_markedText == null)
                 return;
             var commitString = _markedText;
             _markedText = null;
@@ -239,15 +268,15 @@ partial class AvaloniaView
             Logger.TryGet(LogEventLevel.Debug, ImeLog)
                 ?.Log(null, "IUIKeyInput.GetPosition {start} {offset}", pos.Index, (int)offset);
 
-             var res = GetPositionCore(pos, offset);
-             Logger.TryGet(LogEventLevel.Debug, ImeLog)
-                 ?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index));
-             return res!;
+            var res = GetPositionCore(pos, offset);
+            Logger.TryGet(LogEventLevel.Debug, ImeLog)
+                ?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index));
+            return res!;
         }
 
         private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition pos, nint offset)
         {
-            
+
             var end = pos.Index + (int)offset;
             if (end < 0)
                 return null!;
@@ -261,14 +290,14 @@ partial class AvaloniaView
         {
             var pos = (AvaloniaTextPosition)fromPosition;
             Logger.TryGet(LogEventLevel.Debug, ImeLog)
-                ?.Log(null, "IUIKeyInput.GetPosition {start} {direction} {offset}", pos.Index,  inDirection, (int)offset);
+                ?.Log(null, "IUIKeyInput.GetPosition {start} {direction} {offset}", pos.Index, inDirection, (int)offset);
 
             var res = GetPositionCore(pos, inDirection, offset);
             Logger.TryGet(LogEventLevel.Debug, ImeLog)
                 ?.Log(null, $"res: " + (res == null ? "null" : (int)res.Index));
             return res!;
         }
-        
+
         private AvaloniaTextPosition? GetPositionCore(AvaloniaTextPosition fromPosition, UITextLayoutDirection inDirection,
             nint offset)
         {
@@ -348,7 +377,7 @@ partial class AvaloniaView
 
         CGRect IUITextInput.GetFirstRectForRange(UITextRange range)
         {
-            
+
             Logger.TryGet(LogEventLevel.Debug, ImeLog)?
                 .Log(null, "IUITextInput:GetFirstRectForRange");
             // TODO: Query from the input client
@@ -377,11 +406,11 @@ partial class AvaloniaView
             if (presenter is { })
             {
                 var hitResult = presenter.TextLayout.HitTestPoint(new Point(point.X, point.Y));
-                
+
                 return new AvaloniaTextPosition(hitResult.TextPosition);
             }
 
-            return null;
+            return EmptyPosition;
         }
 
         UITextPosition IUITextInput.GetClosestPositionToPoint(CGPoint point, UITextRange withinRange)
@@ -440,7 +469,7 @@ partial class AvaloniaView
         NSDictionary? IUITextInput.MarkedTextStyle
         {
             get => null;
-            set {}
+            set { }
         }
 
         UITextPosition IUITextInput.BeginningOfDocument => _beginningOfDocument;
@@ -478,7 +507,7 @@ partial class AvaloniaView
             var res = base.ResignFirstResponder();
             if (res && ReferenceEquals(CurrentAvaloniaResponder, this))
             {
-                
+
                 Logger.TryGet(LogEventLevel.Debug, "IOSIME")
                     ?.Log(null, "Resigned first responder");
                 _client.SurroundingTextChanged -= SurroundingTextChanged;