Code Monkey home page Code Monkey logo

swiftuibackports's Introduction

watchOS macOS tvOS ios swift

SwiftUI Backports

Introducing a collection of SwiftUI backports to make your iOS development easier.

Many backports support iOS 13+ but where UIKIt features were introduced in later versions, the same will be applicable to these backports, to keep parity with UIKit.

In some cases, I've also included additional APIs that bring more features to your SwiftUI development.

Note, all backports will be API-matching to Apple's official APIs, any additional features will be provided separately.

All backports are fully documented, in most cases using Apple's own documentation for consistency. Please refer to the header docs or Apple's original documentation for more details.

There is also a Demo project available where you can see full demonstrations of all backports and additional features, including reference code to help you get started.

Lastly, I hope this repo also serves as a great resource for how you can backport effectively with minimal hacks 👍

Documentation

Full documentation can be found here.

Sponsor

Building useful libraries like these, takes time away from my family. I build these tools in my spare time because I feel its important to give back to the community. Please consider Sponsoring me as it helps keep me working on useful libraries like these 😬

You can also give me a follow and a 'thanks' anytime.

Twitter

Usage

The library adopts a backport design by Dave DeLong that makes use of a single type to improve discoverability and maintainability when the time comes to remove your backport implementations, in favour of official APIs.

Backports of pure types, can easily be discovered under the Backport namespace. Similarly, modifiers are discoverable under the .backport namespace.

Unfortunately Environment backports cannot be access this way, in those cases the Apple API values will be prefixed with backport to simplify discovery.

Types:

@Backport.AppStorage("filter-enabled")
private var filterEnabled: Bool = false

Modifier:

Button("Show Prompt") {
    showPrompt = true
}
.sheet(isPresented: $showPrompt) {
    Prompt()
        .backport.presentationDetents([.medium, .large])
}

Environment:

@Environment(\.backportRefresh) private var refreshAction

Backports

SwiftUI

  • AsyncImage
  • AppStorage
  • background – ViewBuilder API
  • DismissAction
  • DynamicTypeSizeLabelLabeledContent
  • NavigationDestination – uses a standard NavigationView
  • navigationTitle – newer API
  • overlay – ViewBuilder API
  • onChange
  • openURL
  • ProgressView
  • presentationDetents
  • presentationDragIndicator
  • quicklookPreview
  • requestReview
  • Refreshable – includes pull-to-refresh 
  • ScaledMetric
  • ShareLink
  • StateObject
  • scrollDisabled
  • scrollDismissesKeyboard
  • scrollIndicators
  • Section(_ header:)
  • task – async/await modifier

UIKit

  • UIHostingConfiguration – simplifies embedding SwiftUI in UICollectionViewCell and UITableViewCell

Extras

Modal Presentations

Adding this to your presented view, you can use the provided closure to present an ActionSheet to a user when they attempt to dismiss interactively. You can also use this to disable interactive dismissals entirely.

presentation(isModal: true) { /* attempt */ }

FittingGeometryReader

A custom GeometryReader implementation that correctly auto-sizes itself to its content. This is useful in many cases where you need a GeometryReader but don't want it to implicitly take up its parent View's bounds.

FittingScrollView

A custom ScrollView that respects Spacer's when the content is not scrollable. This is useful when you need to place a view at the edges of your scrollview while its content is small enough to not require scrolling. Another great use case is vertically centered content that becomes top aligned once the content requires scrolling.

Installation

You can install manually (by copying the files in the Sources directory) or using Swift Package Manager (preferred)

To install using Swift Package Manager, add this to the dependencies section of your Package.swift file:

.package(url: "https://github.com/shaps80/SwiftUIBackports.git", .upToNextMajor(from: "2.0.0"))

swiftuibackports's People

Contributors

auramagi avatar chrisjrex avatar drucelweisse avatar exentrich avatar hguandl avatar ihorshevchuk avatar jordanekay avatar larryonoff avatar mikakruschel avatar mwocu avatar qeude avatar rhysm94 avatar roland-schmitz-ocu avatar schiewe avatar shaps80 avatar skyfoxa avatar snnafi avatar solchan87 avatar stephenwoodford avatar strangeliu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swiftuibackports's Issues

presentationBackground

I thought this could be an easy one, but as it turns out its extremely difficult to get right.

Rich text support in TextEditor

I've been using TextView for a few months and recently noticed that it has been deprecated in favor of Backports.TextEditor. However, I don't see how I'm supposed to enable rich text, ie where URLs, phone numbers and emails are tappable. I'm a bit surprised I don't see any ViewModifiers for this component. Any samples would be appreciated.

Crash FocusState with two TextFields

If you use focus state with two Textfields, app crashes.

If you replace VStack with Form/List it works, but I dont want use a Form.

import SwiftUI
import SwiftUIBackports

struct FocusState: View {
    var body: some View {
        NavigationLink {
            Demo()
                .backport.navigationTitle("Sign In")
        } label: {
            Text("Focus State")
        }
    }
}

private struct Demo: View {
    enum Field: Hashable {
        case username
        case password
    }
    
    @State private var username = ""
    @State private var password = ""
    @Backport.FocusState private var focusedField: Field?
    
    var body: some View {
        VStack {
            TextField("Username", text: $username)
                .backport.focused($focusedField, equals: .username)
                .backport.submitLabel(.next)
                .backport.onSubmit {
                    if !username.isEmpty {
                        focusedField = .password
                    }
                }
            
            
            TextField("Password", text: $password)
                .backport.focused($focusedField, equals: .password)
                .backport.submitLabel(.done)
                .backport.onSubmit {
                    signIn()
                }
            
            
            Button("Sign In") {
                signIn()
                
            }
        }
        .padding()
        
        .onAppear {
            focusedField = .username
        }
    }
    
    private func signIn() {
        if username.isEmpty {
            focusedField = .username
        } else if password.isEmpty {
            focusedField = .password
        } else {
            focusedField = nil
            print(username, password)
        }
    }
}

Xcode 14.3 beta 2 fails to build SwiftUIBackports - iOS 14 API used

Have you read the Contributing Guidelines?

General Information

  • Project version:
    1.15.0

  • Platform/OS version:
    iOS 15+ (not entirely relevant to this)

  • IDE version:
    Xcode 14.3 beta 2

  • Any related GitHub issues:

Describe the bug

When attempting to build a project which imports SwiftUIBackports in Xcode 14.3 beta 2, the compiler fails on the file Toolbar.swift with the error Namespace is only available in iOS 14.0 or newer.
The same error doesn't happen in Xcode 14.2, but I'm not sure why that is. Accessing the same Toolbar.swift file and Cmd+right clicking the Namespace property wrapper shows that it was introduced in iOS 14, and the file shouldn't have been successfully building while the package targets iOS 13+.

Steps to reproduce

Add SwiftUIBackports as a dependency to a project targeting any version of iOS with SwiftUI, and attempt to build in Xcode 14.3 beta 2.

Expected behavior

SwiftUIBackports to build correctly

Screenshots

If applicable, add screenshots, gifs, or videos to help explain your problem.
image
image

Additional context

In the generated header for Namespace, it's attributed like this:

@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
@frozen @propertyWrapper public struct Namespace : DynamicProperty {

So I'm really confused as to how it built/worked before 😅

Mac Catalyst app build fails on Xcode 14 RC

General Information

Catalyst app build fails on Xcode 14 RC with redefinition of module 'QuickLook' error

  • Project version:
    1.4.0-1.6.3

  • Platform/OS version:
    macOS Catalyst

  • IDE version:
    Xcode 14 RC

Xcode 14.2 fails to compile version 2.2+

General Information

  • Project version:
    2.2.0+

  • Platform/OS version:
    iOS 13+ (not relevant for issue)

  • IDE version:
    Xcode 14.2

  • Devices:
    N/A

  • Any related GitHub issues:

Describe the bug

When upgrading to any version past 2.2.0 and trying to build the project on Xcode 14.2, the following error will occur cannot declare local computed variable in result builder which is emitting from the addition of /SwiftUIBackports/Sources/SwiftUIBackports/iOS/AutoCapitalization/AutoCapitalization.swift with this block of code

var type: SwiftUI.TextInputAutocapitalization {
...
}

Steps to reproduce

Try running any version past 2.2 of SwiftUIBackPorts on Xcode 14.2.

Expected behavior

SwiftUIBackports to build correctly

Screenshots

image

Additional context

I believe that this block of #if available code just needs to verify the swift version and this shouldn't be a problem anymore.
We're sadly blocked from moving to Xcode 14.3 at our company and a fix in a later version past 2.2 fixed an issue we were having elsewhere.
One of our developers had 14.3 on their computer and was working off that, but when it got to our build machines that are still running 14.2, this is when we saw it was failing.

iOS 17: Feature requests, please add in comments

In order to best serve the community, please request features (or react to an existing one) using the comments on this issue. I will then prioritise all efforts to try and fill those backports where possible 👍

For Swift (non-UI) requests please see SwiftBackports

–––

I'm surprised I need to say this, but please do not add comments below that are unrelated to this ticket!

PhotoPicker not binding data

PhotoPicker not binding data

func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
isPresented.wrappedValue = false
}

Cannot find type PlatformImage on tvOS

Cannot find type 'PlatformImage' in scope when compiling v1.9.0 against tvOS 16.0.

Seems to be because the public typealias PlatformImage = UIImage is only set for iOS, not tvOS.

Pod Support

Hi, any plan to support cocoapods? thanks

Lazy Stacks

Are there any plans to backport LazyVStack or LazyGrid?

@K1NXZ Moving your question to its own Issue, so its tracked correctly 👍

Should enhancement APIs be moved to SwiftUI+?

@schiewe made a great point on one of my APIs that including non-backport API alongside the real backport could make it difficult to continue using the enhancement once the back port is dropped and no longer required.

Putting it in one modifier allowed me to properly implement the back port and the additional feature in most cases.

Tbh this hasn't come up often yet but I have a couple 'additions' that are not really backports, I wonder if it's just a bad idea to include these in this library at all.

Perhaps I should move these to my SwiftUI+ package instead since these are enhancements. Removes this specific concern too.

Thoughts?

PresentationDetents

Hi, is it possible to backport more presentationDetents like .fraction and .height ?

ShareLink with an iPad

Hi,

Thanks for the library. I've been using your ActivityView library! I'm posting this issue here since the ShareLink code will have the same issue I encountered with ActivityView.

I had a question / issue when presenting an acitivtysheet in iPadOS. The activitySheet is called from my main view, and not from a button like this:

NavigationView { Color.white } .activitySheet($activityItem)

In order to get this to work, I had to modify the ActivitySheet code to add the following:

controller.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY,width: 0,height: 0)

This is based on this thread:

https://stackoverflow.com/questions/32889680/uiactivityviewcontroller-on-ipad

Is this something you can add to this library, or is there something that I need to configure to get this to work on an iPad?

Thanks,

crash on orientation change when using .sheet with backported .presentationDetents and .interactiveDismissDisabled

General Information

  • Project version: latest
  • Platform/OS version: iOS 16
  • IDE version: Xcode 14.3.1
  • Devices: iPhone Simulator and iPhone Devices

Describe the bug

When opening a sheet which has the backported .presentationDetents and .interactiveDismissDisabled view modifiers applied and then changing the device orientation from portrait to landscape and back, then the app crashes.
The stack traces are showing an endless recursion.

Steps to reproduce

  1. Create a new app project in Xcode
  2. Replace the ContentView with this code:
import SwiftUI
import SwiftUIBackports

struct ContentView: View {
    @State private var showSheet = false
    
    var body: some View {
        Button("Show Sheet") {
            showSheet.toggle()
        }
        .sheet(isPresented: $showSheet) {
            Button("Hide Sheet") {
                showSheet.toggle()
            }
            .backport.presentationDetents([.medium])
            .backport.interactiveDismissDisabled(true)
        }
    }
}
  1. Run the app
  2. Open the sheet by tapping the "Show Sheet" button
  3. Change the interface orientation to landscape by rotating the device (or simulator)
  4. Change the interface orientation back to portrait.

For me this always crashes because of an endless recursion

Expected behavior

No crash

Stack trace, compiler error, code snippets

	Thread 1 Queue : com.apple.main-thread (serial)
	#0	0x000000018bfba694 in char* __swift::__runtime::llvm::hashing::detail::hash_combine_recursive_helper::combine_data<swift::TargetProtocolDescriptor<swift::InProcess> const*>(unsigned long&, char*, char*, swift::TargetProtocolDescriptor<swift::InProcess> const*) ()
	#1	0x000000018bfba610 in __swift::__runtime::llvm::hash_code __swift::__runtime::llvm::hash_combine<swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*>(swift::TargetMetadata<swift::InProcess> const* const&, swift::TargetProtocolDescriptor<swift::InProcess> const* const&) ()
	#2	0x000000018bfba4ac in std::__1::pair<(anonymous namespace)::ConformanceCacheEntry*, unsigned int> swift::ConcurrentReadableHashMap<(anonymous namespace)::ConformanceCacheEntry, swift::LazyMutex>::find<(anonymous namespace)::ConformanceCacheKey>((anonymous namespace)::ConformanceCacheKey const&, swift::ConcurrentReadableHashMap<(anonymous namespace)::ConformanceCacheEntry, swift::LazyMutex>::IndexStorage, unsigned long, (anonymous namespace)::ConformanceCacheEntry*) ()
	#3	0x000000018bfb97c8 in swift_conformsToProtocolMaybeInstantiateSuperclasses(swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptor<swift::InProcess> const*, bool) ()
	#4	0x000000018bfb8e5c in swift_conformsToProtocol ()
	#5	0x000000018bf7a1e8 in swift::_conformsToProtocol(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetProtocolDescriptorRef<swift::InProcess>, swift::TargetWitnessTable<swift::InProcess> const**) ()
	#6	0x000000018bf80690 in _conformsToProtocols(swift::OpaqueValue const*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetExistentialTypeMetadata<swift::InProcess> const*, swift::TargetWitnessTable<swift::InProcess> const**) ()
	#7	0x000000018bf7f788 in tryCastToConstrainedOpaqueExistential(swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetMetadata<swift::InProcess> const*&, swift::TargetMetadata<swift::InProcess> const*&, bool, bool) ()
	#8	0x000000018bf7e488 in tryCast(swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::OpaqueValue*, swift::TargetMetadata<swift::InProcess> const*, swift::TargetMetadata<swift::InProcess> const*&, swift::TargetMetadata<swift::InProcess> const*&, bool, bool) ()
	#9	0x000000018bf7e0cc in swift_dynamicCast ()
	#10	0x000000018bd53150 in _debugPrint_unlocked<τ_0_0, τ_0_1>(_:_:) ()
	#11	0x000000018bdea750 in specialized _debugPrint<τ_0_0>(_:separator:terminator:to:) ()
	#12	0x000000018bddd440 in Optional.debugDescription.getter ()
	#13	0x000000018bd969a8 in String.init<τ_0_0>(describing:) ()
	#14	0x0000000102ca072c in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/Detents.swift:228
	#15	0x0000000102ca09e0 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#16	0x0000000102ca83ac in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/InteractiveDismiss.swift:223
	#17	0x0000000102ca8484 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#18	0x0000000102ca0908 in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/Detents.swift:230
	#19	0x0000000102ca09e0 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#20	0x0000000102ca83ac in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/InteractiveDismiss.swift:223
	#21	0x0000000102ca8484 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#22	0x0000000102ca0908 in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/Detents.swift:230
	#23	0x0000000102ca09e0 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#24	0x0000000102ca83ac in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/InteractiveDismiss.swift:223

	...

	#38644	0x0000000102ca83ac in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/InteractiveDismiss.swift:223
	#38645	0x0000000102ca8484 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#38646	0x0000000102ca0908 in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/Detents.swift:230
	#38647	0x0000000102ca09e0 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#38648	0x0000000102ca83ac in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/InteractiveDismiss.swift:223
	#38649	0x0000000102ca8484 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#38650	0x0000000102ca0908 in Backport<τ_0_0>.Representable.Controller.responds(to:) at .../Repos/SwiftUIBackports/Sources/SwiftUIBackports/iOS/Presentation/Detents.swift:230
	#38651	0x0000000102ca09e0 in @objc Backport<τ_0_0>.Representable.Controller.responds(to:) ()
	#38652	0x0000000104b32eb0 in -[UISheetPresentationController _sheetLayoutInfoDidInvalidateUntransformedFrame:] ()
	#38653	0x00000001041837bc in _UISheetLayoutInfoDirtyUntransformedFrame ()
	#38654	0x0000000104184014 in _UISheetLayoutInfoDirtyOffsetAdjustment ()
	#38655	0x0000000104183ec0 in _UISheetLayoutInfoDirtyPercentFullHeight ()
	#38656	0x00000001041832f8 in _UISheetLayoutInfoDirtyStackAlignmentFrame ()
	#38657	0x0000000104183378 in _UISheetLayoutInfoDirtyMargins ()
	#38658	0x0000000104184434 in _UISheetLayoutInfoDirtyMarginsWhenFloating ()
	#38659	0x000000010417c448 in -[_UISheetLayoutInfo _setContainerSafeAreaInsets:] ()
	#38660	0x0000000104b32cfc in -[UISheetPresentationController _updateLayoutInfoContainerSafeAreaInsets] ()
	#38661	0x0000000104d52c38 in -[UITransitionView safeAreaInsetsDidChange] ()
	#38662	0x0000000104d63508 in -[UIView _safeAreaInsetsDidChangeFromOldInsets:] ()
	#38663	0x0000000104d62d44 in -[UIView _updateSafeAreaInsets] ()
	#38664	0x0000000104d6a27c in -[UIView _updateCombinedInsetsIfNecessary] ()
	#38665	0x0000000104d6f918 in -[UIView(Geometry) setFrame:] ()
	#38666	0x0000000104d52bcc in -[UITransitionView setFrame:] ()
	#38667	0x0000000104d71ccc in -[UIView(Geometry) _resizeWithOldSuperviewSize:] ()
	#38668	0x000000018039e934 in __NSARRAY_IS_CALLING_OUT_TO_A_BLOCK__ ()
	#38669	0x00000001803253a8 in -[__NSArrayM enumerateObjectsWithOptions:usingBlock:] ()
	#38670	0x0000000104d7109c in -[UIView(Geometry) resizeSubviewsWithOldSize:] ()
	#38671	0x0000000104d6f83c in -[UIView(Geometry) setFrame:] ()
	#38672	0x000000010492911c in -[UIWindow setFrame:] ()
	#38673	0x00000001048e9e58 in -[UIApplication setStatusBarOrientation:fromOrientation:windowScene:animationParameters:updateBlock:] ()
	#38674	0x00000001049243a0 in __78-[UIWindow _rotateWindowToOrientation:updateStatusBar:duration:skipCallbacks:]_block_invoke ()
	#38675	0x00000001042821fc in __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke_2 ()
	#38676	0x0000000104d80bdc in +[UIView _performBlockDelayingTriggeringResponderEvents:forScene:] ()
	#38677	0x000000010428208c in __58-[_UIWindowRotationAnimationController animateTransition:]_block_invoke ()
	#38678	0x0000000104d7e6b0 in +[UIView(UIViewAnimationWithBlocksPrivate) _modifyAnimationsWithPreferredFrameRateRange:updateReason:animations:] ()
	#38679	0x0000000104d7d584 in +[UIView _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] ()
	#38680	0x0000000104d7d96c in +[UIView(UIViewAnimationWithBlocks) animateWithDuration:delay:options:animations:completion:] ()
	#38681	0x0000000104281ef4 in -[_UIWindowRotationAnimationController animateTransition:] ()
	#38682	0x0000000104921cfc in -[UIWindow _rotateToBounds:withAnimator:transitionContext:] ()
	#38683	0x0000000104924154 in -[UIWindow _rotateWindowToOrientation:updateStatusBar:duration:skipCallbacks:] ()
	#38684	0x0000000104924594 in -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] ()
	#38685	0x0000000104920f80 in -[UIWindow _internal_setRotatableViewOrientation:updateStatusBar:duration:force:] ()
	#38686	0x0000000104922c18 in __57-[UIWindow _updateToInterfaceOrientation:duration:force:]_block_invoke ()
	#38687	0x000000010492296c in -[UIWindow _updateToInterfaceOrientation:duration:force:] ()
	#38688	0x000000010403bc04 in -[_UIScenefbsSceneBasedMetricsCalculator _updateMetricsOnWindows:animated:] ()
	#38689	0x0000000104b18588 in -[UIWindowScene _computeMetricsForWindows:animated:] ()
	#38690	0x0000000104b17b68 in __55-[UIWindowScene _computeMetrics:withTransitionContext:]_block_invoke ()
	#38691	0x0000000104b17ca8 in -[UIWindowScene _computeTraitCollectionAndCoordinateSpaceForcingDelegateCallback:withAction:] ()
	#38692	0x0000000104b17af8 in -[UIWindowScene _computeMetrics:withTransitionContext:] ()
	#38693	0x0000000104b14ca8 in -[UIWindowScene _computeMetricsAndCrossFadeInLiveResize:withTransitionContext:] ()
	#38694	0x0000000104d7d584 in +[UIView _setupAnimationWithDuration:delay:view:options:factory:animations:start:animationStateGenerator:completion:] ()
	#38695	0x0000000104d7d7b0 in +[UIView(UIViewAnimationWithBlocks) _animateWithDuration:delay:options:factory:animations:completion:] ()
	#38696	0x000000010441d618 in +[BSAnimationSettings(UIKit) tryAnimatingWithSettings:fromCurrentState:actions:completion:] ()
	#38697	0x000000010451d0d4 in _UISceneSettingsDiffActionPerformChangesWithTransitionContextAndCompletion ()
	#38698	0x0000000104040aa8 in -[_UIWindowSceneGeometrySettingsDiffAction _updateSceneGeometryWithSettingObserverContext:windowScene:transitionContext:] ()
	#38699	0x0000000104040718 in -[_UIWindowSceneGeometrySettingsDiffAction _performActionsForUIScene:withUpdatedFBSScene:settingsDiff:fromSettings:transitionContext:lifecycleActionType:] ()
	#38700	0x0000000103eb0b3c in __64-[UIScene scene:didUpdateWithDiff:transitionContext:completion:]_block_invoke.196 ()
	#38701	0x0000000103eaf93c in -[UIScene _emitSceneSettingsUpdateResponseForCompletion:afterSceneUpdateWork:] ()
	#38702	0x0000000103eb07f8 in -[UIScene scene:didUpdateWithDiff:transitionContext:completion:] ()
	#38703	0x00000001044435d8 in -[UIApplicationSceneClientAgent scene:handleEvent:withCompletion:] ()
	#38704	0x0000000184e593d4 in -[FBSScene updater:didUpdateSettings:withDiff:transitionContext:completion:] ()
	#38705	0x0000000184e810d0 in __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke_2 ()
	#38706	0x0000000184e64704 in -[FBSWorkspace _calloutQueue_executeCalloutFromSource:withBlock:] ()
	#38707	0x0000000184e8101c in __94-[FBSWorkspaceScenesClient _queue_updateScene:withSettings:diff:transitionContext:completion:]_block_invoke ()
	#38708	0x0000000103bc9d50 in _dispatch_client_callout ()
	#38709	0x0000000103bcd968 in _dispatch_block_invoke_direct ()
	#38710	0x0000000184e9ef14 in __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ ()
	#38711	0x0000000184e9ee08 in -[FBSSerialQueue _targetQueue_performNextIfPossible] ()
	#38712	0x0000000184e9ef48 in -[FBSSerialQueue _performNextFromRunLoopSource] ()
	#38713	0x000000018039ac6c in __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ ()
	#38714	0x000000018039abb4 in __CFRunLoopDoSource0 ()
	#38715	0x000000018039a324 in __CFRunLoopDoSources0 ()
	#38716	0x0000000180394958 in __CFRunLoopRun ()
	#38717	0x0000000180394254 in CFRunLoopRunSpecific ()
	#38718	0x0000000188eb7c9c in GSEventRunModal ()
	#38719	0x00000001048e2ff0 in -[UIApplication _run] ()
	#38720	0x00000001048e6f3c in UIApplicationMain ()
	#38721	0x00000001089b734c in ___lldb_unnamed_symbol203070 ()
	#38722	0x00000001089b71ec in ___lldb_unnamed_symbol203068 ()
	#38723	0x00000001081af474 in static App.main() ()
	#38724	0x0000000102bc568c in static BackportSheetLocalApp.$main() at .../Repos/Experiments/BackportSheetLocal/BackportSheetLocal/BackportSheetLocalApp.swift:10
	#38725	0x0000000102bc5738 in main ()
	#38726	0x0000000103209514 in start_sim ()
	#38727	0x0000000103335f28 in start ()

Workaround

I will create a PR with two simple changes to avoid this endless recursion.

Add an option to fallback on Backport when first-party native API is not available?

Describe the feature

A new public EnvironmentValue (and optionally a public-facing ViewModifier) that enables or disables internal use of the first-party APIs that this package backports when running on a device where it's available?

Is your feature request related to a problem?

Something I find myself doing when using SwiftUIBackports is creating local modifiers and views that check the OS version (#available) and return the native API when it's available and fallback on this package's backports for older OS'es. It'd be super awesome if this could be added as a built-in feature.

Proposed solution

A private EnvironmentKey of type Bool. Maybe the KeyPath for EnvironmentValues would be called something like \.preferNativeAPIWhenAvailable (which would be set to true when the developer wants to use the first-party API when the device is on an OS version that supports the native API). This could also be confusing because it doesn't refer to SwiftUIBackports in the name, so it might not be clear its purpose (aside from good documentation). Or it could be called \.preferBackportOnNewerOS, which would make its value imply the opposite.

This could also be implemented in SwiftBackports.

Additional context

An example of my current solution (which I'm suggesting be implemented in SwiftUIBackports) is as follows:

struct BackportNavigationLink<P: Hashable, Label: View>: View {
    var value: P?
    var label: () -> Label
    
    @ViewBuilder
    var body: some View {
        if #available(iOS 16, *) {
            NavigationLink(value: value, label: label)
        } else {
            Backport.NavigationLink(value: value, label: label)
        }
    }
}

The only difference in the implementation would be this:

struct BackportNavigationLink<P: Hashable, Label: View>: View {
    @Environment(\.preferBackportOnNewerOS)
    private var preferBackportOnNewerOS
    
    var value: P?
    var label: () -> Label
    
    @ViewBuilder
    var body: some View {
        if #available(iOS 16, *), !preferBackportOnNewerOS {
            NavigationLink(value: value, label: label)
        } else {
            Backport.NavigationLink(value: value, label: label)
        }
    }
}

Does .backports.onChange {} really work on macOS 10.15 Catalina?

Have you read the Contributing Guidelines?

General Information

I tried this on my macOS 10.15 virtual machine but find that it doesn't execute the {}-bracketed contents at all.

  • Project version: v1.8.2

  • Platform/OS version: macOS 10.15 Catalina.

  • IDE version: Xcode 14.

  • Devices: VMWare Fusion 13 running on mac mini (macOS 13).

  • Any related GitHub issues:

Describe the bug

(See general information.)


I have no way to create a standalone project demonstrating this issue due to the failure of compiling this package in a new project (targeting macOS 10.15). Once this compilation issue gets solved, I can provide a bare-bone project demonstrating this issue.
image


Steps to reproduce

Provide numbered steps to follow that reproduce the bug.

Expected behavior

Clearly and concisely describe what you expected to happen.

Stack trace, compiler error, code snippets

Paste the full output of any stack trace or compiler error.
Include a code snippet that reproduces the described behavior, if applicable

Screenshots

If applicable, add screenshots, gifs, or videos to help explain your problem.

Additional context

Add any other useful information about the problem here.

crash on iOS 13 and iOS 14

0x109a982fc <+0>:
sub
sp,sp,#0x40

x20,x19,[sp,#0x20]
0x109a98300 <+4>:
stp
0x109a98304 <+8>:
x29,x3日,[sp,#0x3日]
stp
0x109a98308 <+12>:

mov
x19,x0
0x109a9830c <+16>:
x8,10606
adrp

日x109a9831日 <+20>:addnominal type descriptor forBGFoundation.PhotosViewController.Coordinator + 76
x8,x8,#0x8
0x109a98314 <+24>: adrp
x9,106日6
0x109a98318 <+28>:; nominal type descriptor foraddBGFoundation.PhotosViewController.Coordinator + 109
x9,x9,#9x20
0x109a9831c <+32>:
x8,x9,[sp]
stp
0x109a98320 <+36>:
mov
w日,#0x13f
0x10c155514
0x109a98324 <+40>:
bl
; symbol stub for: type metadata accessor for
PhotosUI.PHPickerConfiguration
x1,#0x3f
0x109a98328 <+44>:
cmp
0x109a9832c <+48>:
b.hi
0x109a9836c
; <+112>
0x109a98330 <+52>:
add
x4,x19,#0x5日
ldur
x8,[x日,#-0x8]
0x109a98334 <+56>:
0x109a98338 <+60>:
add
x8,x8,#0x40
0x109a9833c <+64>:
adrp
x9,10606
0x109a98340 <+68>:
add
x9,x9,#0x38
;nominal type descriptor for
BGFoundation.PhotosViewController.Coordinator + 1240x109a98344 <+72>:stp0x109a98348 <+76>:mov
x8,x9,[sp,#0x10]

x3,sp
日x109a9834c <+80>:mov
x0,x19
0x109a98350 <+84>:mov
w1,#0x100
0x109a98354 <+88>:mov
w2,#Ox4
67
0x109a98358 <+92>:
0x10c15cfc日
;symbol stub for: swift updateClassMetadata2
x日,#0x日
0x109a9835c <+96>:cmp
0x109a98360 <+100>:csel
x日, x日, xzr, ne
0x109a98364 <+104>: csel
x1,x1,xzr,ne

XCPreviewAgent crash when using the .task modifier in Xcode 14

General Information

  • Project version: 1.8.2
  • Platform/OS version: 16.0
  • IDE version: Xcode 14
  • Devices: SwiftUI Previews for 15.5 and 16.0 (and maybe more)
  • Any related GitHub issues:

Describe the bug

Since adding .backport.task { await someAsyncWork() } to my SwiftUI views, XCPreviewAgent crashes. Removing the modifier again makes the preview appear.

Steps to reproduce

Implement the task modifier on a SwiftUI view in Xcode and observe that the preview agent crashes.

Expected behavior

The preview works.

Stack trace, compiler error, code snippets

CrashReportError: XCPreviewAgent crashed

XCPreviewAgent crashed. Check ~/Library/Logs/DiagnosticReports for crash logs from your application.

Process: XCPreviewAgent[97637]
Date/Time: 2022-09-27 03:42:32 +0000
Log File: <none>

Application Specific Information:
    libsystem_sim_platform.dylib [
        CoreSimulator 857.7 - Device: iPhone 13 Pro (331455B1-A4E2-4BB6-A161-52F6E4F58603) - Runtime: iOS 15.5 (19F70) - DeviceType: iPhone 13 Pro
    ]
    dyld_sim [
        dyld4 config: DYLD_ROOT_PATH=/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot DYLD_LIBRARY_PATH=/Users/jrogers/Library/Developer/Xcode/DerivedData/Redacted-edjkeuwkldrlgchgtbyjqwvpgezb/Build/Intermediates.noindex/Previews/Redacted/Products/Debug-iphonesimulator DYLD_INSERT_LIBRARIES=/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot//System/Library/PrivateFrameworks/PreviewsInjection.framework/PreviewsInjection DYLD_FRAMEWORK_PATH=/Users/jrogers/Library/Developer/Xcode/DerivedData/Redacted-edjkeuwkldrlgchgtbyjqwvpgezb/Build/Intermediates.noindex/Previews/Redacted/Products/Debug-iphonesimulator
    ]
    dyld [
        dyld4 config: DYLD_ROOT_PATH=/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot DYLD_LIBRARY_PATH=/Users/jrogers/Library/Developer/Xcode/DerivedData/Redacted-edjkeuwkldrlgchgtbyjqwvpgezb/Build/Intermediates.noindex/Previews/Redacted/Products/Debug-iphonesimulator DYLD_INSERT_LIBRARIES=/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot//System/Library/PrivateFrameworks/PreviewsInjection.framework/PreviewsInjection DYLD_FRAMEWORK_PATH=/Users/jrogers/Library/Developer/Xcode/DerivedData/Redacted-edjkeuwkldrlgchgtbyjqwvpgezb/Build/Intermediates.noindex/Previews/Redacted/Products/Debug-iphonesimulator
    ]

Frames: [
    Frame {
        imageIndex: 0
        imageOffset: 0
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 1
        imageOffset: 122464
        symbol: protocol witness for View.body.getter in conformance ViewNameRedactedForPrivacy
        symbolLocation: 24
    }
    Frame {
        imageIndex: 2
        imageOffset: 2760140
        symbol: partial apply for closure #1 in ViewBodyAccessor.updateBody(of:changed:)
        symbolLocation: 28
    }
    Frame {
        imageIndex: 2
        imageOffset: 7873668
        symbol: closure #1 in BodyAccessor.setBody(_:)
        symbolLocation: 44
    }
    Frame {
        imageIndex: 2
        imageOffset: 2759904
        symbol: ViewBodyAccessor.updateBody(of:changed:)
        symbolLocation: 1400
    }
    Frame {
        imageIndex: 2
        imageOffset: 7875384
        symbol: DynamicBody.updateValue()
        symbolLocation: 512
    }
    Frame {
        imageIndex: 2
        imageOffset: 9794408
        symbol: partial apply for implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:)
        symbolLocation: 28
    }
    Frame {
        imageIndex: 3
        imageOffset: 24936
        symbol: AG::Graph::UpdateStack::update()
        symbolLocation: 516
    }
    Frame {
        imageIndex: 3
        imageOffset: 26316
        symbol: AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int)
        symbolLocation: 400
    }
    Frame {
        imageIndex: 3
        imageOffset: 52540
        symbol: AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, unsigned char&, long)
        symbolLocation: 544
    }
    Frame {
        imageIndex: 3
        imageOffset: 140496
        symbol: AGGraphGetValue
        symbolLocation: 232
    }
    Frame {
        imageIndex: 2
        imageOffset: 7904780
        symbol: AnyViewList.updateValue()
        symbolLocation: 76
    }
    Frame {
        imageIndex: 2
        imageOffset: 1664928
        symbol: partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:)
        symbolLocation: 20
    }
    Frame {
        imageIndex: 3
        imageOffset: 24936
        symbol: AG::Graph::UpdateStack::update()
        symbolLocation: 516
    }
    Frame {
        imageIndex: 3
        imageOffset: 26316
        symbol: AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int)
        symbolLocation: 400
    }
    Frame {
        imageIndex: 3
        imageOffset: 52540
        symbol: AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, unsigned char&, long)
        symbolLocation: 544
    }
    Frame {
        imageIndex: 3
        imageOffset: 140496
        symbol: AGGraphGetValue
        symbolLocation: 232
    }
    Frame {
        imageIndex: 2
        imageOffset: 10195940
        symbol: _ViewList_Group.Init.value.getter
        symbolLocation: 184
    }
    Frame {
        imageIndex: 2
        imageOffset: 1274680
        symbol: specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:)
        symbolLocation: 36
    }
    Frame {
        imageIndex: 3
        imageOffset: 24936
        symbol: AG::Graph::UpdateStack::update()
        symbolLocation: 516
    }
    Frame {
        imageIndex: 3
        imageOffset: 26316
        symbol: AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int)
        symbolLocation: 400
    }
    Frame {
        imageIndex: 3
        imageOffset: 52540
        symbol: AG::Graph::input_value_ref_slow(AG::data::ptr<AG::Node>, AG::AttributeID, unsigned int, AGSwiftMetadata const*, unsigned char&, long)
        symbolLocation: 544
    }
    Frame {
        imageIndex: 3
        imageOffset: 140496
        symbol: AGGraphGetValue
        symbolLocation: 232
    }
    Frame {
        imageIndex: 2
        imageOffset: 7906496
        symbol: AnyViewList.Item.list.getter
        symbolLocation: 120
    }
    Frame {
        imageIndex: 2
        imageOffset: 7905140
        symbol: AnyViewList.updateValue()
        symbolLocation: 436
    }
    Frame {
        imageIndex: 2
        imageOffset: 1664928
        symbol: partial apply for specialized implicit closure #2 in implicit closure #1 in closure #1 in closure #1 in Attribute.init<A>(_:)
        symbolLocation: 20
    }
    Frame {
        imageIndex: 3
        imageOffset: 24936
        symbol: AG::Graph::UpdateStack::update()
        symbolLocation: 516
    }
    Frame {
        imageIndex: 3
        imageOffset: 26316
        symbol: AG::Graph::update_attribute(AG::data::ptr<AG::Node>, unsigned int)
        symbolLocation: 400
    }
    Frame {
        imageIndex: 3
        imageOffset: 50544
        symbol: AG::Graph::value_ref(AG::AttributeID, AGSwiftMetadata const*, unsigned char&)
        symbolLocation: 160
    }
    Frame {
        imageIndex: 3
        imageOffset: 140572
        symbol: AGGraphGetValue
        symbolLocation: 308
    }
    Frame {
        imageIndex: 2
        imageOffset: 2183124
        symbol: TestableViewContent.list.getter
        symbolLocation: 100
    }
    Frame {
        imageIndex: 2
        imageOffset: 2182240
        symbol: TestableViewContent.children.getter
        symbolLocation: 44
    }
    Frame {
        imageIndex: 2
        imageOffset: 2181596
        symbol: View.withChildrenForTest<A>(environment:options:body:)
        symbolLocation: 192
    }
    Frame {
        imageIndex: 2
        imageOffset: 5936640
        symbol: View._allPreviews.getter
        symbolLocation: 104
    }
    Frame {
        imageIndex: 2
        imageOffset: 5936480
        symbol: MakePreviews.visit<A>(type:)
        symbolLocation: 156
    }
    Frame {
        imageIndex: 2
        imageOffset: 11123448
        symbol: _callVisitViewType2
        symbolLocation: 44
    }
    Frame {
        imageIndex: 2
        imageOffset: 5936280
        symbol: static _PreviewProvider._allPreviews.getter
        symbolLocation: 172
    }
    Frame {
        imageIndex: 4
        imageOffset: 147008
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 4
        imageOffset: 146736
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 4
        imageOffset: 116768
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 4
        imageOffset: 99416
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 4
        imageOffset: 97520
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 4
        imageOffset: 98252
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 5
        imageOffset: 20488
        symbol: +[BSXPCServiceConnectionProxy invokeMethod:onTarget:withMessage:forConnection:]
        symbolLocation: 1232
    }
    Frame {
        imageIndex: 5
        imageOffset: 74448
        symbol: __63-[BSXPCServiceConnectionEventHandler connection:handleMessage:]_block_invoke
        symbolLocation: 624
    }
    Frame {
        imageIndex: 5
        imageOffset: 235828
        symbol: BSXPCServiceConnectionExecuteCallOut
        symbolLocation: 304
    }
    Frame {
        imageIndex: 5
        imageOffset: 73436
        symbol: -[BSXPCServiceConnectionEventHandler connection:handleMessage:]
        symbolLocation: 156
    }
    Frame {
        imageIndex: 5
        imageOffset: 232492
        symbol: -[BSXPCServiceConnection _connection_handleMessage:fromPeer:withHandoff:]
        symbolLocation: 284
    }
    Frame {
        imageIndex: 6
        imageOffset: 8772
        symbol: _dispatch_call_block_and_release
        symbolLocation: 24
    }
    Frame {
        imageIndex: 6
        imageOffset: 15000
        symbol: _dispatch_client_callout
        symbolLocation: 16
    }
    Frame {
        imageIndex: 6
        imageOffset: 43724
        symbol: _dispatch_lane_serial_drain
        symbolLocation: 652
    }
    Frame {
        imageIndex: 6
        imageOffset: 46720
        symbol: _dispatch_lane_invoke
        symbolLocation: 456
    }
    Frame {
        imageIndex: 6
        imageOffset: 70500
        symbol: _dispatch_main_queue_drain
        symbolLocation: 792
    }
    Frame {
        imageIndex: 6
        imageOffset: 69692
        symbol: _dispatch_main_queue_callback_4CF
        symbolLocation: 40
    }
    Frame {
        imageIndex: 7
        imageOffset: 547884
        symbol: __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__
        symbolLocation: 12
    }
    Frame {
        imageIndex: 7
        imageOffset: 524464
        symbol: __CFRunLoopRun
        symbolLocation: 2432
    }
    Frame {
        imageIndex: 7
        imageOffset: 520728
        symbol: CFRunLoopRunSpecific
        symbolLocation: 572
    }
    Frame {
        imageIndex: 8
        imageOffset: 13836
        symbol: GSEventRunModal
        symbolLocation: 160
    }
    Frame {
        imageIndex: 9
        imageOffset: 12638872
        symbol: -[UIApplication _run]
        symbolLocation: 992
    }
    Frame {
        imageIndex: 9
        imageOffset: 12658228
        symbol: UIApplicationMain
        symbolLocation: 112
    }
    Frame {
        imageIndex: 2
        imageOffset: 10302100
        symbol: closure #1 in KitRendererCommon(_:)
        symbolLocation: 160
    }
    Frame {
        imageIndex: 2
        imageOffset: 10301936
        symbol: runApp<A>(_:)
        symbolLocation: 164
    }
    Frame {
        imageIndex: 2
        imageOffset: 4220544
        symbol: static App.main()
        symbolLocation: 80
    }
    Frame {
        imageIndex: 10
        imageOffset: 14208
        symbol: <none>
        symbolLocation: <none>
    }
    Frame {
        imageIndex: 11
        imageOffset: 7384
        symbol: start_sim
        symbolLocation: 20
    }
    Frame {
        imageIndex: 12
        imageOffset: 20620
        symbol: start
        symbolLocation: 520
    }
]

Images: [
    Image {
        uuid: 00000000-0000-0000-0000-000000000000
        base: 0
        name: <none>
        path: <none>
    }
    Image {
        uuid: b8a2035a-839d-3f1b-82e1-ae1ed0d8fa6e
        base: 733331456
        name: Redacted_FD5DA5DE38C1551_PackageProduct
        path: /Users/USER/Library/Developer/Xcode/DerivedData/Redacted-edjkeuwkldrlgchgtbyjqwvpgezb/Build/Intermediates.noindex/Previews/Redacted/Products/Debug-iphonesimulator/PackageFrameworks/Redacted_FD5DA5DE38C1551_PackageProduct.framework/Redacted_FD5DA5DE38C1551_PackageProduct
        arch: arm64
    }
    Image {
        uuid: 230fac38-33f4-348b-b676-e5d65157ca8c
        base: 195624960
        name: SwiftUI
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/SwiftUI.framework/SwiftUI
        arch: arm64
    }
    Image {
        uuid: 09d49b75-24ad-3293-b5cd-0121dbb15b97
        base: 92815360
        name: AttributeGraph
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/AttributeGraph.framework/AttributeGraph
        arch: arm64
    }
    Image {
        uuid: 12ca1c72-a2ee-3b3b-b6c5-6569b0a74f55
        base: 38551552
        name: PreviewsInjection
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/PreviewsInjection.framework/PreviewsInjection
        arch: arm64
    }
    Image {
        uuid: 7b01370c-32d3-347b-9ec9-9255084d9eee
        base: 333053952
        name: BoardServices
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/BoardServices.framework/BoardServices
        arch: arm64
    }
    Image {
        uuid: a06c95dc-09e7-3a87-afb6-7e1b0bec1287
        base: 59965440
        name: libdispatch.dylib
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/usr/lib/system/libdispatch.dylib
        arch: arm64
    }
    Image {
        uuid: 673c8a21-98bf-38f0-a038-55ab0de23142
        base: 94666752
        name: CoreFoundation
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
        arch: arm64
    }
    Image {
        uuid: 9334a354-2177-30b1-b919-4fecf59fef22
        base: 84492288
        name: GraphicsServices
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/GraphicsServices.framework/GraphicsServices
        arch: arm64
    }
    Image {
        uuid: 7bbc9f13-df06-3c47-9a63-8483442bdfcb
        base: 628752384
        name: UIKitCore
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/PrivateFrameworks/UIKitCore.framework/UIKitCore
        arch: arm64
    }
    Image {
        uuid: 83c5ea3a-4a49-3f59-8136-67d6353e1f1b
        base: 33865728
        name: XCPreviewAgent
        path: /Users/USER/Library/Developer/Xcode/UserData/Previews/Simulator Devices/331455B1-A4E2-4BB6-A161-52F6E4F58603/data/Containers/Bundle/Application/1A1C8D9D-47B9-4E9B-88CA-D4341D693157/XCPreviewAgent.app/XCPreviewAgent
        arch: arm64
    }
    Image {
        uuid: 67298116-bb18-3438-b22e-8d2b9d4618e9
        base: 37093376
        name: dyld_sim
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/usr/lib/dyld_sim
        arch: arm64
    }
    Image {
        uuid: 38ee9fe9-b66d-3066-8c5c-6ddf0d6944c6
        base: 35274752
        name: dyld
        path: /usr/lib/dyld
        arch: arm64e
    }
    Image {
        uuid: 92169345-9fa9-3925-bc8b-8a67f59dfcea
        base: 39436288
        name: libswiftCore.dylib
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/usr/lib/swift/libswiftCore.dylib
        arch: arm64
    }
    Image {
        uuid: 6de4a53b-8d96-3c92-b3c9-4a5ed84776fb
        base: -871718912
        name: libsystem_pthread.dylib
        path: /usr/lib/system/libsystem_pthread.dylib
        arch: arm64
    }
    Image {
        uuid: 3f1dda9e-9999-35d8-9886-03267422f518
        base: -872067072
        name: libsystem_kernel.dylib
        path: /usr/lib/system/libsystem_kernel.dylib
        arch: arm64
    }
    Image {
        uuid: ded71e05-af0a-3172-b09e-7f070ec7d4aa
        base: 51527680
        name: Foundation
        path: /Library/Developer/CoreSimulator/Profiles/Runtimes/iOS 15.5.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation
        arch: arm64
    }
]

==================================

|  MessageError: Connection interrupted
|  
|  ==================================
|  
|  |  MessageSendFailure: Message send failure for <ServiceMessage 249: update>

Not Dismissing

Have you read the Contributing Guidelines?

General Information

  • Project version:

1.2.0

  • Platform/OS version:

iOS 16.1

  • IDE version:

Xcode 14.1

  • Devices:

Real iPhone 13, Simulator iPhone 14 Pro Max

  • Any related GitHub issues:

Describe the bug

Clearly and concisely describe the bug.
I am using ActivityView in one of my Apps. I have noticed that if you bring up the activity view and choose to email or text or anything else. If you cancel the email or text the activity view doesn’t dismiss it stays on top of the screen. I can’t seem to figure out why this is not dismissing. Any help or advice would be appreciated….

Steps to reproduce

Provide numbered steps to follow that reproduce the bug.

  1. Bring up an activity view
  2. Choose to email
  3. Then hit cancel when MailView comes up
  4. You'll notice the MailVIew goes away but the share sheet stays on the screen

Expected behavior

Clearly and concisely describe what you expected to happen.
I would expect that if you canceled whatever activity you've chosen the share sheet should dismiss and go away

Stack trace, compiler error, code snippets

Paste the full output of any stack trace or compiler error.
Include a code snippet that reproduces the described behavior, if applicable

Screenshots

If applicable, add screenshots, gifs, or videos to help explain your problem.

Additional context

Add any other useful information about the problem here.

PresentationDetents and DragIndicatorVisibility are not applied after rotating the device

Have you read the Contributing Guidelines?

Yes

General Information

  • Project version:
    v1.9.0 (latest release)

  • Platform/OS version:
    iOS 16 (Simulator, any device)

  • IDE version:
    Xcode 14.2

Describe the bug

After rotating the device from portrait to landscape and back, the PresentationDetents and the visibility of the DragIndicator are not applied correctly anymore.

Minimal reproduction

struct SheetView: View {
    @State private var showSheet = false
    
    var body: some View {
        Button("Show Sheet") {
            showSheet = true
        }
        .sheet(isPresented: $showSheet) {
            Color.red.edgesIgnoringSafeArea(.all)
                .backport.presentationDetents([.medium])
                .backport.presentationDragIndicator(.visible)
        }
    }
}

Steps to reproduce

  1. Use the example code from above
  2. Start app in portrait mode
  3. Rotate to landscape and back to portrait
  4. The sheet is now showing in .large mode and the drag indicator is hidden

Expected behavior

The sheet should still show up in .medium mode and the drag indicator should still be visible

Bugfix branch

I already fixed the bug in this branch https://github.com/mwocu/SwiftUIBackports/tree/fix_sheet_presentation_after_device_rotation
and could submit a PR, if wanted
main...mwocu:SwiftUIBackports:fix_sheet_presentation_after_device_rotation

Does not compile for macOS

Neither release v1.9.0 nor the main branch compile for target platform macOS in Xcode 14.0.1 because of numerous errors.

Apple privacy manifest

Describe the feature

Because the library uses UserDefaults, it has to contain PrivacyInfo manifest, check Apple doc

Is your feature request related to a problem?

Starting March 13: If you upload a new or updated app to App Store Connect that uses an API requiring approved reasons, we’ll send you an email letting you know if you’re missing reasons in your app’s privacy manifest. This is in addition to the existing notification in App Store Connect.

Starting May 1: You’ll need to include approved reasons for the listed APIs used by your app’s code to upload a new or updated app to App Store Connect. If you’re not using an API for an allowed reason, please find an alternative. And if you add a new third-party SDK that’s on the list of commonly used third-party SDKs, these API, privacy manifest, and signature requirements will apply to that SDK. Make sure to use a version of the SDK that includes its privacy manifest and note that signatures are also required when the SDK is added as a binary dependency.

https://developer.apple.com/news/?id=3d8a9yyh

Proposed solution

Add Privacy manifest supporting UserDefaults privacy reason type, https://developer.apple.com/support/third-party-SDK-requirements/

Alternatives considered

Additional context

toolbarBackground style modifier

Hi, thanks for the nice work on the package !

I see that public func toolbarBackground<S>(_ style: S, for bars: ToolbarPlacement...) -> some View where S : ShapeStyle is commented, what is blocking/missing for making it usable ?

Refreshable not enabling pull-to-refresh

Have you read the Contributing Guidelines?

General Information

  • Project version:
    1.0.9

  • Platform/OS version:
    iOS 14.0.1, iOS 15.5, iOS 16

  • IDE version:
    Xcode 13.4.1, Xcode 14 beta 2

  • Devices:
    iPhone Simulator

  • Any related GitHub issues:
    N/A

Describe the bug

Using .backport.refreshable does not add pull-to-refresh to a list.

Steps to reproduce

Add .backport.refreshable to a List.

Expected behavior

Should add pull-to-refresh to the list.

Stack trace, compiler error, code snippets

struct RootView: View {
    var body: some View {
        TabView {
            NavigationView {
                List {
                    Text("1")
                    Text("2")
                    Text("3")
                }
                .navigationTitle("Native")
                .refreshable {
                    print("Refresh!")
                }
            }
            .tabItem {
                Text("Native")
            }

            NavigationView {
                List {
                    Text("1")
                    Text("2")
                    Text("3")
                }
                .navigationTitle("Backport")
                .backport.refreshable {
                    print("Refresh!")
                }
            }
            .tabItem {
                Text("Backport")
            }
        }
    }
}

Screenshots

Simulator Screen Shot - iPhone 12 mini - 2022-06-30 at 21 03 35
Simulator Screen Shot - iPhone 12 mini - 2022-06-30 at 21 03 28

Additional context

It could be argued that the backport is complete; it does set the environment value. But not adding the pull-to-refresh was a surprise to me. It does look to be possible (https://github.com/Geri-Borbas/iOS.Package.Refreshable) so maybe something similar could be added?

Infinite loop in UIView parentController property on iOS 14.0-14.4

General Information

See attached project

  • Project version:
    1.6.3

  • Platform/OS version:
    iOS 14.0-14.4

  • IDE version:
    Xcode 13

  • Devices:

  • Any related GitHub issues:

Describe the bug

Uninited tab body causes infinite loop in UIView parentController property

Steps to reproduce

  1. Run attached project on iOS 14.0-14.4
  2. Tap "Show modal" on tab A
  3. Select TextField

Expected behavior

No infinite loop in OwningController.swift

Stack trace, compiler error, code snippets

Archive.zip

Additional context

If tab B were opened before Modal, all works fine.

Work in progress

In order to keep everyone up-to-date with what I'm working on and to avoid duplication, here's a list of the currently planned additions/backports. Some just require documentation and cleanup (since they were developed some time ago), others are not yet in development. If you need a feature and want to know if you should start on it yourself, please check with me first to ensure we reach a similar solution.

WIP

  • scrollBounceBehaviour

Up next

Version 2.0.0

  • FocusState
  • onSubmit
  • submitLabel
  • presentationBackgroundInteraction
  • presentationContentInteraction
  • presentationCornerRadius
  • TextEditor

Version `1.13.0

  • UniformTypeIdentifiers

Version 1.12.0

  • PhotosPicker

Version 1.11.0

  • Toolbar (limited)

Version 1.10.0

Version 1.9.0

  • ImageRenderer
  • ShareLink

Version 1.5.0

  • Table Hosting

Version 1.5.0

  • LabelledContent
  • quickLookPreview

Version 1.4.0

  • ScrollDismissesKeyboard
  • ScrollIndicators
  • ScrollEnabled

Version 1.3.1

  • List Pull-to-Refresh

Version 1.2.0

  • Dismiss (environment)
  • DynamicTypeSize
  • AppStore Review
  • OpenURL modifier

README update

The README documentation says for installation to utilize .upToNextMinor(from: "1.0.0") in a Swift Package, but we're clearly past that. I'd recommend updating the docs to utilize branch: "main"

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.