diff --git a/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs b/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs
index fbdfe3aa7d..b04397f1c6 100644
--- a/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs
+++ b/src/Avalonia.Controls/ApplicationLifetimes/IActivatableApplicationLifetime.cs
@@ -11,13 +11,13 @@ public interface IActivatableApplicationLifetime
/// An event that is raised when the application is Activated for various reasons
/// as described by the enumeration.
///
- event EventHandler Activated;
+ event EventHandler? Activated;
///
/// An event that is raised when the application is Deactivated for various reasons
/// as described by the enumeration.
///
- event EventHandler Deactivated;
+ event EventHandler? Deactivated;
///
/// Tells the application that it should attempt to leave its background state.
diff --git a/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj b/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
index eb4938c13f..4201ae0ad3 100644
--- a/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
+++ b/src/iOS/Avalonia.iOS/Avalonia.iOS.csproj
@@ -1,9 +1,15 @@
net7.0-ios16.0
- 13.0
+ 13.0
+ 13.0
+ 13.1
true
true
+
+
+
+ $(NoWarn);CA1416
@@ -12,4 +18,5 @@
+
diff --git a/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs b/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
index ecb9e56aa9..e4ec20bbbd 100644
--- a/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
+++ b/src/iOS/Avalonia.iOS/AvaloniaAppDelegate.cs
@@ -15,7 +15,7 @@ namespace Avalonia.iOS
public class AvaloniaAppDelegate : UIResponder, IUIApplicationDelegate, IAvaloniaAppDelegate
where TApp : Application, new()
{
- private EventHandler _onActivated, _onDeactivated;
+ private EventHandler? _onActivated, _onDeactivated;
public AvaloniaAppDelegate()
{
@@ -37,7 +37,7 @@ namespace Avalonia.iOS
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder;
[Export("window")]
- public UIWindow Window { get; set; }
+ public UIWindow? Window { get; set; }
[Export("application:didFinishLaunchingWithOptions:")]
public bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
@@ -64,7 +64,7 @@ namespace Avalonia.iOS
builder.SetupWithLifetime(lifetime);
- Window.MakeKeyAndVisible();
+ Window!.MakeKeyAndVisible();
return true;
}
diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs b/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs
index 0b0e169e8a..dbdddd2cc5 100644
--- a/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs
+++ b/src/iOS/Avalonia.iOS/AvaloniaView.Text.cs
@@ -1,4 +1,3 @@
-#nullable enable
using Avalonia.Input.TextInput;
using UIKit;
diff --git a/src/iOS/Avalonia.iOS/AvaloniaView.cs b/src/iOS/Avalonia.iOS/AvaloniaView.cs
index f44202c240..b6cde47c7a 100644
--- a/src/iOS/Avalonia.iOS/AvaloniaView.cs
+++ b/src/iOS/Avalonia.iOS/AvaloniaView.cs
@@ -1,7 +1,6 @@
-#nullable enable
-
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Runtime.Versioning;
using Avalonia.Controls;
using Avalonia.Controls.Embedding;
@@ -12,7 +11,6 @@ using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
-using Avalonia.iOS.Storage;
using Avalonia.Platform;
using Avalonia.Platform.Storage;
using Avalonia.Rendering.Composition;
@@ -24,6 +22,9 @@ using IInsetsManager = Avalonia.Controls.Platform.IInsetsManager;
namespace Avalonia.iOS
{
+ ///
+ /// Root view container for Avalonia content, that can be embedded into iOS visual tree.
+ ///
public partial class AvaloniaView : UIView, ITextInputMethodImpl
{
internal IInputRoot InputRoot
@@ -35,7 +36,7 @@ namespace Avalonia.iOS
private TextInputMethodClient? _client;
private IAvaloniaViewController? _controller;
private IInputRoot? _inputRoot;
- private MetalRenderTarget? _currentRenderTarget;
+ private Metal.MetalRenderTarget? _currentRenderTarget;
public AvaloniaView()
{
@@ -49,13 +50,14 @@ namespace Avalonia.iOS
InitLayerSurface();
#if !TVOS
- MultipleTouchEnabled = true;
+ if (OperatingSystem.IsIOS() || OperatingSystem.IsMacCatalyst())
+ {
+ MultipleTouchEnabled = true;
+ }
#endif
}
- [ObsoletedOSPlatform("ios12.0", "Use 'Metal' instead.")]
- [SupportedOSPlatform("ios")]
- [UnsupportedOSPlatform("maccatalyst")]
+ [SuppressMessage("Interoperability", "CA1422:Validate platform compatibility")]
private void InitLayerSurface()
{
var l = Layer;
@@ -68,13 +70,13 @@ namespace Avalonia.iOS
OpenGLES.EAGLDrawableProperty.RetainedBacking, false,
OpenGLES.EAGLDrawableProperty.ColorFormat, OpenGLES.EAGLColorFormat.RGBA8
);
- _topLevelImpl.Surfaces = new[] { new EaglLayerSurface(eaglLayer) };
+ _topLevelImpl.Surfaces = new[] { new Eagl.EaglLayerSurface(eaglLayer) };
}
else
#endif
if (l is CAMetalLayer metalLayer)
{
- _topLevelImpl.Surfaces = new[] { new MetalPlatformSurface(metalLayer, this) };
+ _topLevelImpl.Surfaces = new[] { new Metal.MetalPlatformSurface(metalLayer, this) };
}
}
@@ -85,6 +87,12 @@ namespace Avalonia.iOS
public override bool CanResignFirstResponder => true;
///
+ [ObsoletedOSPlatform("ios17.0", "Use the 'UITraitChangeObservable' protocol instead.")]
+ [ObsoletedOSPlatform("maccatalyst17.0", "Use the 'UITraitChangeObservable' protocol instead.")]
+ [ObsoletedOSPlatform("tvos17.0", "Use the 'UITraitChangeObservable' protocol instead.")]
+ [SupportedOSPlatform("ios")]
+ [SupportedOSPlatform("tvos")]
+ [SupportedOSPlatform("maccatalyst")]
public override void TraitCollectionDidChange(UITraitCollection? previousTraitCollection)
{
base.TraitCollectionDidChange(previousTraitCollection);
@@ -125,8 +133,12 @@ namespace Avalonia.iOS
{
_view = view;
_nativeControlHost = new NativeControlHostImpl(view);
-#if !TVOS
- _storageProvider = new IOSStorageProvider(view);
+#if TVOS
+ _storageProvider = null;
+ _clipboard = null;
+ _inputPane = null;
+#else
+ _storageProvider = new Storage.IOSStorageProvider(view);
_clipboard = new ClipboardImpl();
_inputPane = UIKitInputPane.Instance;
#endif
@@ -152,7 +164,8 @@ namespace Avalonia.iOS
// No-op
}
- public Compositor Compositor => Platform.Compositor;
+ public Compositor Compositor => Platform.Compositor
+ ?? throw new InvalidOperationException("iOS backend wasn't initialized. Make sure UseiOS was called.");
public void Invalidate(Rect rect)
{
@@ -237,7 +250,6 @@ namespace Avalonia.iOS
return _insetsManager;
}
-#if !TVOS
if (featureType == typeof(IClipboard))
{
return _clipboard;
@@ -252,7 +264,6 @@ namespace Avalonia.iOS
{
return _inputPane;
}
-#endif
return null;
}
@@ -262,7 +273,7 @@ namespace Avalonia.iOS
public static Class LayerClass()
{
#if !MACCATALYST
- if (Platform.Graphics is EaglPlatformGraphics)
+ if (Platform.Graphics is Eagl.EaglPlatformGraphics)
{
return new Class(typeof(CAEAGLLayer));
}
@@ -299,7 +310,7 @@ namespace Avalonia.iOS
set => _topLevel.Content = value;
}
- internal void SetRenderTarget(MetalRenderTarget target)
+ internal void SetRenderTarget(Metal.MetalRenderTarget target)
{
_currentRenderTarget = target;
}
diff --git a/src/iOS/Avalonia.iOS/ClipboardImpl.cs b/src/iOS/Avalonia.iOS/ClipboardImpl.cs
index 0bc03e9160..27cbc0246c 100644
--- a/src/iOS/Avalonia.iOS/ClipboardImpl.cs
+++ b/src/iOS/Avalonia.iOS/ClipboardImpl.cs
@@ -1,20 +1,22 @@
#if !TVOS
using System;
+using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Input;
using Avalonia.Input.Platform;
+using Foundation;
using UIKit;
namespace Avalonia.iOS
{
internal class ClipboardImpl : IClipboard
{
- public Task GetTextAsync()
+ public Task GetTextAsync()
{
return Task.FromResult(UIPasteboard.General.String);
}
- public Task SetTextAsync(string text)
+ public Task SetTextAsync(string? text)
{
UIPasteboard.General.String = text;
return Task.CompletedTask;
@@ -22,15 +24,40 @@ namespace Avalonia.iOS
public Task ClearAsync()
{
- UIPasteboard.General.String = "";
+ UIPasteboard.General.Items = Array.Empty();
return Task.CompletedTask;
}
- public Task SetDataObjectAsync(IDataObject data) => Task.CompletedTask;
+ public Task SetDataObjectAsync(IDataObject data)
+ {
+ if (data.Contains(DataFormats.Text))
+ {
+ UIPasteboard.General.String = data.GetText();
+ }
+
+ return Task.CompletedTask;
+ }
+
+ public Task GetFormatsAsync()
+ {
+ var formats = new List();
+ if (UIPasteboard.General.HasStrings)
+ {
+ formats.Add(DataFormats.Text);
+ }
- public Task GetFormatsAsync() => Task.FromResult(Array.Empty());
+ return Task.FromResult(formats.ToArray());
+ }
- public Task