This is driving me crazy for many days now. I am trying to use the .fileImport() modifier in SwiftUI and apparently I am missing something VERY obvious but for the life of me I cannot find a way to have the "Select" option (see screenshots.
This is like the simplest it can get:
import SwiftUI
import UniformTypeIdentifiers
struct DocImporterView: View {
// #Binding var document: ProofOfBugDocument
#State var isPicking: Bool = false
var body: some View {
Button("Pick") {
isPicking.toggle()
}
.fileImporter(
isPresented: $isPicking,
allowedContentTypes: [.item, .folder, .directory],
allowsMultipleSelection: true, //this btw does not enable the select. Instead just starts the Document Picker in selection mode (but folders cannot be selected)
onCompletion: { result in
print("Picked: \(result)")
})
}
}
struct DocImporterView_Previews: PreviewProvider {
static var previews: some View {
DocImporterView()//(document: .constant(ProofOfBugDocument()))
}
}
Any ideas/help appreciated
Related
import SwiftUI
import CodeScanner
struct ContentView: View {
#State var isPresentingScanner = false
#State var scannedCode: String = "Scan a QR code to get started."
var scannerSheet : some View {
CodeScannerView(
codeTypes: [.qr],
completion:{ result in
if case let.success(code) = result {
self.scannedCode = code.string
self.isPresentingScanner = false
}
}
)
var body: some View {
VStack(spacing: 10) {
Text(scannedCode)
Button("Scan QR code") {
self.isPresentingScanner = true
}
.sheet(isPresented: $isPresentingScanner) {
self.scannerSheet
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
}
I'm a very new beginner in XCODE and am a bit stuck with these errors shown on my code and I've tried looking up solutions but I cannot get anywhere, unfortunately. I would appreciate any help or feedback.
The errors that are occuring are "Type 'ContentView' does not conform to protocol 'View'", "Function declares an opaque return type, but has no return statements in its body from which to infer an underlying type", "Result of 'CodeScannerView' initializer is unused"
P.S I am attempting to create a code scanner and I already have a packaged added.
enter image description here
It's because you didn't put closing brackets for scannerSheet, and had extra closing brackets after the body variable.
This should work.
import SwiftUI
import CodeScanner
struct ContentView: View {
#State var isPresentingScanner = false
#State var scannedCode: String = "Scan a QR code to get started."
var scannerSheet : some View {
CodeScannerView(
codeTypes: [.qr],
completion:{ result in
if case let.success(code) = result {
self.scannedCode = code.string
self.isPresentingScanner = false
}
}
)
} // ←
var body: some View {
VStack(spacing: 10) {
Text(scannedCode)
Button("Scan QR code") {
self.isPresentingScanner = true
}
.sheet(isPresented: $isPresentingScanner) {
self.scannerSheet
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
P.S. Something that would help you spot this type of error in the future would be to re-indent all the code.
You can do that by selecting all the code in the file (CMD+A), then selecting Editor -> Structure -> Re-Indent (CTRL+I)
I am trying to present a sequence of Views, each gathering some information from the user. When users enter all necessary data, they can move to next View. So far I have arrived at this (simplified) code, but I am unable to display the subview itself (see first line in MasterView VStack{}).
import SwiftUI
protocol DataEntry {
var entryComplete : Bool { get }
}
struct FirstSubView : View, DataEntry {
#State var entryComplete: Bool = false
var body: some View {
VStack{
Text("Gender")
Button("Male") {
entryComplete = true
}
Button("Female") {
entryComplete = true
}
}
}
}
struct SecondSubView : View, DataEntry {
var entryComplete: Bool {
return self.name != ""
}
#State private var name : String = ""
var body: some View {
Text("Age")
TextField("Your name", text: $name)
}
}
struct MasterView: View {
#State private var currentViewIndex = 0
let subview : [DataEntry] = [FirstSubView(), SecondSubView()]
var body: some View {
VStack{
//subview[currentViewIndex]
Text("Subview placeholder")
Spacer()
HStack {
Button("Prev"){
if currentViewIndex > 0 {
currentViewIndex -= 1
}
}.disabled(currentViewIndex == 0)
Spacer()
Button("Next"){
if (currentViewIndex < subview.count-1){
currentViewIndex += 1
}
}.disabled(!subview[currentViewIndex].entryComplete)
}
}
}
}
I do not want to use NavigationView for styling reasons. Can you please point me in the right direction how to solve this problem? Maybe a different approach?
One way to do this is with a Base View and a switch statement combined with an enum. This is a similar pattern I've used in the past to separate flows.
enum SubViewState {
case ViewOne, ViewTwo
}
The enum serves as a way to easily remember and track which views you have available.
struct BaseView: View {
#EnvironmentObject var subViewState: SubViewState = .ViewOne
var body: some View {
switch subViewState {
case ViewOne:
ViewOne()
case ViewTwo:
ViewTwo()
}
}
}
The base view is a Container for the view control. You will likely add a view model, which is recommended, and set the state value for your #EnvironmentObject or you'll get a null pointer exception. In this example I set it, but I'm not 100% sure if that syntax is correct as I don't have my IDE available.
struct SomeOtherView: View {
#EnvironmentObject var subViewState: SubViewState
var body: some View {
BaseView()
Button("Switch View") {
subViewState = .ViewTwo
}
}
}
This is just an example of using it. You can access your #EnvironmentObject from anywhere, even other views, as it's always available until disposed of. You can simply set a new value to it and it will update the BaseView() that is being shown here. You can use the same principle in your code, using logic, to determine the view to be shown and simply set its value and it will update.
I recently implemented an Edit Button into my app. However, it created a strange and annoying animation in the View both when it loads (everything comes in from the left), and when I sort the elements. I noticed that if I remove the .animation that is after the .environment it solves this issue, but then everything appears and moves instantly without the .easeInOut look that I wanted to give. How can I apply this animation only to the appearing and disappearing of the sort and delete buttons of the cells of the Form?
If you want to take a look at my problem (since I don't think I was able to explain it correctly) you can look at this video.
The code is this one, ContentView:
import SwiftUI
struct ContentView: View {
#ObservedObject var dm : DataManager
#ObservedObject var vm : ValueModel
#State var showAlertDeleteContact = false
#State var isEditing = false
#State private var editMode = EditMode.inactive
var body: some View {
NavigationView {
Color(UIColor.systemGray6).ignoresSafeArea(.all).overlay(
VStack {
scrollViewFolders
Form {
ForEach(dm.storageValues) { contacts in
NavigationLink(
destination:
//Contact View,
label: {
IconView(dm: dm, vm: contacts)
})
}.onDelete(perform: { indexSet in
self.showAlertDeleteContact = true
self.indexDeleteContact = indexSet
})
.onMove(perform: onMove)
Section {
buttonNewFolder
buttonSort
}
}
}
.navigationBarTitle("Contacts")
.navigationBarItems(trailing: editButton)
.environment(\.editMode, .constant(self.isEditing ? EditMode.active : EditMode.inactive))
.animation(.easeInOut)
//I also tried with this -> .animation(.some(Animation.default))
)
}.alert(isPresented: $showAlertDeleteContact, content: {
alertDeleteContact
})
}
If you want to recreate the project, the DataManager is:
import SwiftUI
import Combine
class DataManager : Equatable, Identifiable, ObservableObject {
static let shared = DataManager()
#Published var storageValues : [ValueModel] = []
typealias StorageValues = [ValueModel]
//The rest of the code
}
And the ValueModel is:
import SwiftUI
import Combine
class ValueModel : Codable, Identifiable, Equatable, ObservableObject, Comparable {
var id = UUID()
var valueName : String
var notes : String?
var expires : Date?
init(valueName: String, notes: String?, expires: Date?) {
self.valueName = valueName
self.notes = notes
self.expires = expires
}
}
Thanks to everyone who will help me!
I am trying to build a MVP with SwiftUI that simply shows me the changes in altitude on my Apple Watch. From there I will figure out where to go next (I want to use it for paragliding and other aviation things).
I have previous experience in python, but nothing in Swift, so even after a ton of tutorials I am very unsure about how and where to declare and then use functionalities.
Here is my code so far:
//
// ContentView.swift
// Altimeter WatchKit Extension
//
// Created by Luke Crouch on 29.09.20.
//
import SwiftUI
import CoreMotion
//class func isRelativeAltitudeAvailable() -> Bool
struct ContentView: View {
let motionManager = CMMotionManager()
let queue = OperationQueue()
let altimeter = CMAltimeter()
let altitude = 0
var relativeAltitude: NSNumber = 0
var body: some View {
if motionManager.isRelativeAltitudeAvailable() {
switch CMAltimeter.authorizationStatus() {
case .notDetermined: // Handle state before user prompt
fatalError("Awaiting user prompt...")
case .restricted: // Handle system-wide restriction
fatalError("Authorization restricted!")
case .denied: // Handle user denied state
fatalError("Auhtorization denied!")
case .authorized: // Ready to go!
print("Authorized!")
#unknown default:
fatalError("Unknown Authorization Status")
}
altimeter.startRelativeAltitudeUpdates(to: queue, withHandler: CMAltitudeHandler)
}
// something like relative Altitude = queue[..]
Text("\(relativeAltitude)")
.font(.largeTitle)
.fontWeight(.bold)
.foregroundColor(Color.green)
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
I am getting multiple errors that I dont know how to deal with:
Type 'Void' cannot conform to 'View', only struct/enum/class types can conform to protocols.
Value of type CMMotionManager has no member 'isRelativeAltitudeAvailable'
Type '()' cannot conform to View...
Cannot convert value of type 'CMAltitudeHandler.Type' (aka '((Optional, Optional) -> ()).Type') to expected argument type 'CMAltitudeHandler' (aka '(Optional, Optional) -> ()')
Could you please give me some hints?
Thank you so much!
Luke
I figured it out after trying around a lot:
//
// ContentView.swift
// Altimeter WatchKit Extension
//
// Created by Lukas Wheldon on 29.09.20.
//
import SwiftUI
import CoreMotion
struct ContentView: View {
#State var relativeAltitude: NSNumber = 0
#State var altitude = 0
let altimeter = CMAltimeter()
func update(d: CMAltitudeData?, e: Error?){
print("altitude \(altitude)")
print("CMAltimeter \(altimeter)")
print("relative Altitude \(relativeAltitude))")
}
var body: some View {
VStack {
Text("\(altimeter)")
.fontWeight(.bold)
.foregroundColor(Color.green)
Button(action: {
print("START")
self.startAltimeter()
}, label: {
Text("Start Altimeter")
.bold()
.foregroundColor(.green)
})
}
}
func startAltimeter() {
if CMAltimeter.isRelativeAltitudeAvailable() {
switch CMAltimeter.authorizationStatus() {
case .notDetermined: // Handle state before user prompt
print("bb")
//fatalError("Awaiting user prompt...")
case .restricted: // Handle system-wide restriction
fatalError("Authorization restricted!")
case .denied: // Handle user denied state
fatalError("Authorization denied!")
case .authorized: // Ready to go!
let _ = print("Authorized!")
#unknown default:
fatalError("Unknown Authorization Status")
}
self.altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) {(data,error) in DispatchQueue.main.async {
print("\(altitude)")
print("\(relativeAltitude)")
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Next steps will be to check if I can access the barometer raw data and calculate altitudes on that.
This was working until beta 7. It seems that when I want to pass one element in a collection as a binding to another view, the preview gets broken
I followed the release notes where it says #Binding no longer conforms to collection protocol comments are at the bottom
I have Catalina and xcode in beta 7
Parent:
struct SimpleStructure {
var label: String
}
struct ContentView: View {
#State private var myVariables = [SimpleStructure(label: "hello")]
var body: some View {
ChildView(myVariables: $myVariables)
}
}
Child
struct ChildView: View {
#Binding var myVariables: [SimpleStructure]
var body: some View {
List(myVariables.indexed(), id: \.1.label) {(index, variable) in
GrandChildView(myVariable: self.$myVariables[index])
}
}
}
GrandChild
struct GrandChildView: View {
#Binding var myVariable:SimpleStructure
var body: some View {
Text(myVariable.label)
}
}
UPDATE:
Still an issue with Beta 8
The release notes have a typo. You need to change:
var endIndex: Index { base.startIndex }
with
var endIndex: Index { base.endIndex }
Dunno, is this one solved for you? If not, maybe this helps:
struct ChildView: View {
#Binding var myVariables: [SimpleStructure]
var body: some View {
List(myVariables.indices) { index in
GrandChildView(myVariable: self.$myVariables[index])
}
}
}
If solved, either mark the correct answer, or provide a solution here by yourself in case you may have found one in the meantime.
The issue was fixed in SwiftUI Beta 10