How to integrate UIActivityViewController with SwiftUI's ScrollView?
Here is the approach that works (tested with Xcode 11.2/iOS 13.2)... The extra wrapper host controller is not needed, and it is better to use native SwiftUI instruments for presentation.
import SwiftUI
struct ActivityView: UIViewControllerRepresentable {
var url: String
@Binding var showing: Bool
func makeUIViewController(context: Context) -> UIActivityViewController {
let vc = UIActivityViewController(
activityItems: [NSURL(string: url)!],
applicationActivities: nil
)
vc.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in
self.showing = false
}
return vc
}
func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {
}
}
struct TestUIActivityView: View {
@State var showSheet = false
var body: some View {
ScrollView {
Group {
Button(action: {
self.showSheet.toggle()
}) {
Text("Open Activity View")
}
.sheet(isPresented: $showSheet) {
ActivityView(url: "https://www.wikipedia.org", showing: self.$showSheet)
}
}
}
}
}
struct TestUIActivityView_Previews: PreviewProvider {
static var previews: some View {
TestUIActivityView()
}
}
How to interpret VStack{ .. } from SwiftUI's official tutorial code?
If you look at the docs for VStack.init
, you'll see that the last argument it accepts is indeed a closure. The magic here is that the closure is marked with @ViewBuilder
.
@ViewBuilder
is a kind of function builder. The idea is that you pass in a closure containing a bunch of expressions, and then the function builder will combine those expressions into a single value. It's kind of like returning an array, but in an arguably better-looking syntax. (it's not really an array though. The return type of the closure is decided by the function builder.)
In your code, you are returning an "array" of 4 views.
MapView
CircleImage
- another
VStack
Spacer
These will get passed to the ViewBuilder
, and it combines all of them into a single View
object.
And if you are wondering what the methods called on at the end of each view are doing, they are just methods that return slight modifications of the objects on which they are called. For example padding
returns the same view, but with some padding applied.
SwiftUI - Half modal?
iOS 16+
It looks like half sheet is finally supported in iOS 16.
To manage the size of sheet we can use PresentationDetent
and specifically presentationDetents(_:selection:)
Here's an example from the documentation:
struct ContentView: View {
@State private var showSettings = false
@State private var settingsDetent = PresentationDetent.medium
var body: some View {
Button("View Settings") {
showSettings = true
}
.sheet(isPresented: $showSettings) {
SettingsView()
.presentationDetents:(
[.medium, .large],
selection: $settingsDetent
)
}
}
}
Note that if you provide more that one detent, people can drag the sheet to resize it.
Here are possible values for PresentationDetent:
large
medium
fraction(CGFloat)
height(CGFloat)
custom<D>(D.Type)
Related Topics
Swift Update Label (With HTML Content) Takes 1Min
"Unrecognized Selector Sent to Instance" in Swift
Contextual Type for Closure Argument List Expects 1 Argument, But 4 Were Specified
Error: Use of Unresolved Identifier 'Process'
Declaration Is Only Valid at File Scope (Extension)
Make Int Round Off to Nearest Value
Uiscrollview with Embedded Uiimageview; How to Get the Image to Fill the Screen
Turn Off Xcode's Unused Variable Warnings While Typing
Store a Closure as a Variable in Swift
Back Button Image - What Is It Called in Swift
Get the Accurate Duration of a Video
Why Can't We Use Protocol 'Encodable' as a Type in the Func
Swiftyjson - Call Can Throw, But It Is Marked with 'Try' and the Error Is Not Handled
How to Convert Between Related Types Through a Common Initializer
How to Track More Than 4 Images at a Time with Arkit