I have updated my map code so that now I have a region that is set as a state var in my strict. My map links to this state var.
the problem is now I want to update my map based on my long and last variables that are passed to the struct is there a way to do this - going crazy trying to do this
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
I have an iOS 13 app that I’m hoping to release soon that is written entirely in SwiftUI. If I was starting from scratch today, I’d obviously use the new multi platform template which looks awesome.... But since I’m not starting from scratch, what are the recommendations/best practices for existing apps?
Is there a path for migrating existing apps to take advantage of the new app structure (below) when moving to iOS 14?
@main
struct HelloWorld: App {
var body: some Scene {
WindowGroup {
Text(“Hello, world!”).padding()
}
}
}
I'd like to emulate the behavior of UIViewController.isModalInPresentation in SwiftUI. In my first attempt, I defined the following view:
struct ModalView<Content: View>: UIViewControllerRepresentable {
		var content: () -> Content
		func makeUIViewController(context: Context) -> UIHostingController<Content> {
				let controller = UIHostingController(rootView: content())
				controller.isModalInPresentation = true
				return controller
		}
		func updateUIViewController(_ imagePickerController: UIHostingController<Content>, context: Context) {}
}
From my main app view, I then present the ModalView as a sheet:
struct ContentView: View {
		@State
		var presentSheet: Bool = true
		var body: some View {
				Text("Hello, world!")
						.sheet(isPresented: $presentSheet) {
								ModalView {
										Text("Sheet")
								}
						}
		}
}
But the user is still able to dismiss the ModalView by swiping down. I would expect this sheet to be non-dismissible. Is anything like this supposed to work? If not, is there some other way to prevent the dismissal of a sheet in SwiftUI?
The closest workaround I've found is to apply .highPriorityGesture(DragGesture()) to the content of the sheet, but swiping down with two fingers still works.
I have two (local) Swift packages (both with a single library product): RemoteImage, which defines setImage(from:) function on UIImageView and SatelitUI package which directly depends on the first one and defines some views. But when I'm trying to preview views from the second package I'm getting the following error:
linker command failed with exit code 1 (use -v to see invocation)
LinkDylibError: Failed to build TrailerView.swift
Linking failed: linker command failed with exit code 1 (use -v to see invocation)
ld: warning: directory not found for option '-F/Applications/Xcode-beta.app/Contents/SharedFrameworks-iphonesimulator'
Undefined symbols for architecture x86_64:
"(extension in RemoteImage):__C.UIImageView.setImage(from: Foundation.URL?) -> ()", referenced from:
(extension in SatelitUI_PreviewReplacement_TrailerView_2):SatelitUI.TrailerView.(previewupdate in _8C3731B0EF007627509BEEB93277D681)(with: SatelitUI.Trailer?) -> () in TrailerView.2.preview-thunk.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Apparently, Xcode fails to link the library from the first package because it's dynamic. Static linking works as expected.
It's a bug I believe?
On iOS 13 I used to use optional @State properties to adapt views. In my case, the presented view would either create a new object (an assignment) if the state that is passed into it is nil, or edit the assignment if an assignment was passed in. This would be done in the action block of a Button and it worked beautifully.
On iOS 14 / Xcode 12 this no longer seems to work. Given the following code which creates a new assignment and passes it into the editor view when the user taps a "New Assignment" button, the value of assignment remains nil. Is anyone else experiencing similar behaviour?
struct ContentView: View {
		@Environment(\.managedObjectContext) var context
		@State var assignmentEditorIsPresented = false
		@State var assignment: Assignment? = nil
		var Body: some View {
				[...]
				Button("New Assignment", action: {
						self.assignment = Assignment(context: context)
						self.assignmentEditorIsPresented = true
				})
				.sheet(isPresented: assignmentEditorIsPresented) {
						[...]
				}
		}
}
What's even weirder is that I tried adding a random piece of state, an Int, to this view and modifying it right before the assignment state (between lines 9 and 10) and it didn't change either.
Hello, My Custom fonts are not showing in SwiftUI. I am all up to date on all of my software and I have added my TTF's to a fonts folder in my collection. I also added the "Fonts provided by application" array type to my info.plist and the fonts as elements. Here is my code. I have no idea what I'm doing wrong. Is there a bug in the latest version of Swiftui?
Text("Hello World")
			.font(.custom("VervelleScript-lgxR0", size: 36))
Hey there!
Got a question about font kerning:
When adding a negative kerning to a text (changes via user input) the last character sometimes gets cut off:
dropbox.com/s/49ucdzk8m4k61sj/fontproblem1.png?dl=0
dropbox.com/s/vmklvxp510wjeak/fontproblem2.png?dl=0
What i do is the following:
Text("\(pos, specifier: "%.1f")")
	.font(.system(size: 100,design: .serif))
	.fontWeight(.bold)
	.kerning(-5)
When i remove the kerning it works, but as i understood the kerning keeps the letters as they are? Is there an alternative way of doing it?
Introduction
I created a simple app to test enabling Sign In with Google using Observable Objects in a SwiftUI Application. However, the app only functions properly (displaying the signed in user's name and email) with a UIKit App Delegate Life Cycle. The code of the App file for the SwiftUI life cycle and that of the app delegate and scene delegate files of the UIKit App Delegate life cycle should function identical; however, they do not.
Project Code
SwiftUI Lift Cycle
AppDelegate
import UIKit
import SwiftUI
import GoogleSignIn
class AppDelegate: NSObject, UIApplicationDelegate {
/* GoogleDelegate() is the observable object */
let googleDelegate = GoogleDelegate()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
GIDSignIn.sharedInstance()?.clientID = "CLIENT_ID"
GIDSignIn.sharedInstance()?.delegate = googleDelegate
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance().handle(url)
}
}
App
@main
struct WidgiTubeApp: App {
@UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var window: UIWindow? {
guard let scene = UIApplication.shared.connectedScenes.first,
let windowSceneDelegate = scene.delegate as? UIWindowSceneDelegate,
let window = windowSceneDelegate.window else {
return nil
}
return window
}
@Environment(\.scenePhase) private var scenePhase
let googleDelegate = (UIApplication.shared.delegate as! AppDelegate).googleDelegate
var body: some Scene {
WindowGroup {
GoogleSignInView()
.environmentObject(googleDelegate)
}.onChange(of: scenePhase) { (phase) in
switch phase {
case .active:
GIDSignIn.sharedInstance().presentingViewController = window?.rootViewController
window?.makeKeyAndVisible()
case .inactive:
case .background:
default:
}
}
}
}
Using the SwiftUI Life Cycle the User Is signed in; however, the information does not update in the SwiftUI view. (The view is identical between the SwiftUI Life Cycle and UIKit Application Delegate Life Cycle.)
UIKit Application Delegate Life Cycle
App Delegate
DidFinishLaunchingWithOptions
GIDSignIn.sharedInstance().clientID = "CLIENT_ID"
GIDSignIn.sharedInstance().delegate = googleDelegate
return true
OpenURL
return GIDSignIn.sharedInstance().handle(url)
Scene Delegate
SceneWillConnectTo
let googleDelegate = (UIApplication.shared.delegate as! AppDelegate).googleDelegate
let contentView = ContentView().environmentObject(googleDelegate)
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
GIDSignIn.sharedInstance()?.presentingViewController = window.rootViewController
self.window = window
window.makeKeyAndVisible()
}
Conclusion
Due to this, I have identified that there must be some issue that occurs when adapting the UIKit App Delegate code to the SwiftUI App Code. However, I cannot identify what the issue between the two life cycles is. It is my understanding that anything possible with the UIKit Delegate life cycle should theoretically be possible with SwiftUI. In the mean time, of course, there is no issue continuing with the UIKit Delegate; however, I was hoping to create a SwiftUI app. If anyone could help me identify where the issue lays between these two different life cycles, I would greatly appreciate it. Thanks!
I'm working on an iOS app using SwiftUI and CoreData and am running into a problem that I cannot seem to figure out.
To provide a little bit of information of what I am trying to do:
I have two CoreData entities that have a One-To-Many relationship:
Tarantula - A tarantula may molt many times (To Many) and when deleted, all of the molts shold also be removed (Cascade)
Molt - A molt belongs to a single Tarantula (To One) and when
deleted, should have the reference removed from the Tarantula (Nullify)
I then have a view that lists all of the molts for a given Tarantula that allows adding and deleting molts. It looks like this:
struct MoltListView: View {
		private static let DATE_FORMATTER: DateFormatter = {
						let d = DateFormatter()
						d.dateFormat = "MMM d, y"
						return d
				}()
		
		@Environment(\.managedObjectContext) private var viewContext
		
		@ObservedObject private var tarantula: Tarantula
		@FetchRequest private var molts: FetchedResults<Molt>
		@State private var userMessage: String = ""
		@State private var displayMessage: Bool = false
		
		init(tarantula: Tarantula) {
				self.tarantula = tarantula
				self._molts = FetchRequest(entity: Molt.entity(),
																	 sortDescriptors: [NSSortDescriptor(keyPath: \Molt.date, ascending: false)],
																	 predicate: NSPredicate(format: "tarantula = %@", tarantula))
		}
		
		var body: some View {
				List {
						Section(header: Text("Summary")) {
								Text("\(molts.count) Molt\(molts.count == 1 ? "" : "s")")
						}
						Section(header: Text("Molts")) {
								NavigationLink(destination: MoltView(tarantula: tarantula, molt: Molt.newModel())) {
										Text("Add Molt").foregroundColor(.blue)
								}
								ForEach(molts, id: \.self) { molt in
										NavigationLink(destination: MoltView(tarantula: tarantula, molt: molt)) {
												Text(MoltListView.DATE_FORMATTER.string(from: molt.modelDate))
										}
								}
								.onDelete(perform: deleteItems)
						}
				}.alert(isPresented: $displayMessage) {
						Alert(title: Text("Save Failure"), message: Text(userMessage), dismissButton: .default(Text("Ok")))
				}
		}
		
		private func deleteItems(offsets: IndexSet) {
				withAnimation {
						offsets.map { molts[$0] }.forEach(viewContext.delete)
						do {
								try viewContext.save()
						} catch {
								viewContext.rollback()
								userMessage = "\(error): \(error.localizedDescription)"
								displayMessage.toggle()
						}
				}
		}
}
The error I am experiencing comes from whenever I try to delete a molt from the list view. The app instantly crashes and the error is:
Simultaneous accesses to 0x7f92efc61cb8, but modification requires exclusive access
Find the complete error here:
error - https://developer.apple.com/forums/content/attachment/6d74dcde-d82b-4024-ade0-5936d8926488
I have tried removing the animation block and have played around with removing different UI components/restructuring.
The only way I have been able to prevent this error is to remove the delete rule on the Molt->Tarantula relationship from Nullify to No Action. However, this seems more like a hack to me instead of a fix.
Was hoping for some help on this issue.
I've been using the new template for a document-based SwiftUI app. While you get a lot of file-management "for free" in the new template, as it stands in the iOS version users have to back out of the file to the file browser to change the filename. I want to create an opportunity for the user to rename the file while it is open.
Here's a sample project focused on the issue: https://github.com/stevepvc/DocumentRenamer
In the code, I've added to the template code a simple UI with a textfield for the user to enter a new name. When the user hits the "rename" button, the app checks to see if the URL with that name component is available, appending a suffix if necessary to create a target url.
func getTargetURL() -> URL {
		let baseURL	=	self.fileurl.deletingLastPathComponent()
		print("filename: \(self.filename)")
		print("fileURL: \(self.fileurl)")
		print("BaseURL: \(baseURL)")
		var target = URL(fileURLWithPath: baseURL.path + "/\(filename).exampletext")
		var nameSuffix = 1
		
		while (target as NSURL).checkPromisedItemIsReachableAndReturnError(nil) {
				
				target = URL(fileURLWithPath: baseURL.path + "/\(filename)-\(nameSuffix).sermon")
				print("Checking: \(target)")
				nameSuffix += 1
	 }
		print("Available Target: \(target)")
		return target
}
It then attempts to rename the file, and this is when I am stuck. I have tried several methods, most recently the following:
func changeFilename(){
		let target	= getTargetURL()
		var rv = URLResourceValues()
		let newFileName = target.deletingPathExtension().lastPathComponent
		rv.name = newFileName
		do {
				if fileurl.startAccessingSecurityScopedResource(){
						try fileurl.setResourceValues(rv)
						fileurl.stopAccessingSecurityScopedResource()
				}
		} catch {
				print("Error:\(error)")
		}
}
But I keep getting the following error whenever I run the app on a device:
Domain=NSCocoaErrorDomain Code=513 "You don’t have permission to save the file “Untitled” in the folder “DocumentRenamer”."
I have also tried this without the startAccessingSecurityScopedResource() check, and alternatively have tried creating a helper class as follows:
class FileMover: NSObject {
func moveFile(originalURL: URL, updatedURL:URL) -> Bool {
		let coordinator = NSFileCoordinator(filePresenter: nil)
		var writingError: NSError? = nil
		var success : Bool = true
		print("moving file")
		coordinator.coordinate(writingItemAt: originalURL, options: NSFileCoordinator.WritingOptions.forMoving, error: &writingError, byAccessor: { (coordinatedURL) in
				do {
						try FileManager.default.moveItem(at: coordinatedURL, to: updatedURL)
						success = true
						print("file moved")
						
				} catch {
						print(error)
						success = false
				}
		})
return success
		
}
}
But using this method locks up the app entirely.
What is the correct method for renaming a file in the app's container, particularly using the new Swiftui Document based template?
I tried animating the scrollTo() like so, as described in the docs. - https://developer.apple.com/documentation/swiftui/scrollviewreader
swift
withAnimation {
scrollProxy.scrollTo(index, anchor: .center)
}
the result is the same as if I do
swift
withAnimation(Animation.easeIn(duration: 20)) {
scrollProxy.scrollTo(progress.currentIndex, anchor: .center)
}
I tried this using the example from the ScrollViewReader docs.
With the result that up and down scrolling has exactly the same animation.
struct ScrollingView: View {
@Namespace var topID
@Namespace var bottomID
var body: some View {
ScrollViewReader { proxy in
ScrollView {
Button("Scroll to Bottom") {
withAnimation {
proxy.scrollTo(bottomID)
}
}
.id(topID)
VStack(spacing: 0) {
ForEach(0..100) { i in
color(fraction: Double(i) / 100)
.frame(height: 32)
}
}
Button("Top") {
withAnimation(Animation.linear(duration: 20)) {
proxy.scrollTo(topID)
}
}
.id(bottomID)
}
}
}
func color(fraction: Double) - Color {
Color(red: fraction, green: 1 - fraction, blue: 0.5)
}
}
struct ScrollingView_Previews: PreviewProvider {
static var previews: some View {
ScrollingView()
}
}
Hello,
in my Mac Catalyst app, I have detail view with sections modeled as DisclosureGroups. The label view has a button, that shall trigger a file import view when pushed. The label view is defined as follows:
swift
HStack {
Text(LocalizedStringKey("Documents")).font(.title)
Spacer()
Button {
showFileImporter = false
// fix broken picker sheet
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
showFileImporter = true
}
} label: {
Image(systemName: "doc.badge.plus")
.padding(.horizontal, 10)
}
.disabled(!expanded)
.fileImporter(
isPresented: $showFileImporter,
allowedContentTypes: [.data],
allowsMultipleSelection: false) { result in
// add fileUrl.startAccessingSecurityScopedResource() before accessing file
NSLog("\(result)")
}
}
Unfortunately the file import view is not showing, when the button is pushed, although the state changes to true.
Does anybody have any hints?
BTW the repo is available at https://github.com/thbonk/repti/tree/ui-refactoring
The view in question is https://github.com/thbonk/repti/blob/ui-refactoring/Repti/Source/UI/Views/IndividualDetails/DocumentsSubview.swift
Thanks & Best regards
Thomas
I have an iOS app by using a swift package to hold most of the logic. However, the previews of SwiftUI views often fail with following error:
HumanReadableSwiftError
BuildError: failedToGenerateThunkInfo(Error Domain=com.apple.xcbuild Code=19 "could not generate preview info: noTargetBuildGraph" UserInfo={NSLocalizedDescription=could not generate preview info: noTargetBuildGraph})
To reproduce this, please clone https://github.com/pointfreeco/isowords and check for preview of ChangelogView.
I have been playing around with the new AsyncImage Api in SwiftUI
I am using the initialiser that passes in a closure with the AsyncImagePhase, to view why an image may not load, when I looked at the error that is passed in if the phase is failure, the localised description of the error is "Cancelled" but this is happening before the view is being displayed.
I am loading these images in a list, I imagine I am probably doing something which is causing the system to decide to cancel the loading, but I cannot see what.
Are there any tips to investigate this further?
How does one add Codable conformance to a class that needs to be isolated to the MainActor?
For example, the following code gives compiler errors:
@MainActor final class MyClass: Codable {
var value: Int
enum CodingKeys: String, CodingKey {
case value
}
init(from decoder: Decoder) throws { // <-- Compiler error: Initializer 'init(from:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Decodable'
let data = try decoder.container(keyedBy: CodingKeys.self)
self.value = try data.decode(Int.self, forKey: .value)
}
func encode(to encoder: Encoder) throws { // <-- Compiler error: Instance method 'encode(to:)' isolated to global actor 'MainActor' can not satisfy corresponding requirement from protocol 'Encodable'
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(value, forKey: .value)
}
}
I'm definitely struggling to get my head around actors and @MainActor at the moment!
Hello
I want to be able to save Date in @AppStorage, and it works however I was wondering what was the difference between these two extensions, which one is better and why?
extension Date: RawRepresentable {
static var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateStyle = .long
return formatter
}()
public var rawValue: String {
Date.dateFormatter.string(from: self)
}
public init?(rawValue: String) {
self = Date.dateFormatter.date(from: rawValue) ?? Date()
}
}
and
extension Date: RawRepresentable {
private static let formatter = ISO8601DateFormatter()
public var rawValue: String {
Date.formatter.string(from: self)
}
public init?(rawValue: String) {
self = Date.formatter.date(from: rawValue) ?? Date()
}
}
Thank You!
I am working on a library, a Swift package. We have quite a few properties on various classes that can change and we think the @Published property wrapper is a good way to annotate these properties as it offers a built-in way to work with SwiftUI and also Combine.
Many of our properties can change on background threads and we've noticed that we get a purple runtime issue when setting the value from a background thread. This is a bit problematic for us because the state did change on a background thread and we need to update it at that time. If we dispatch it to the main queue and update it on the next iteration, then our property state doesn't match what the user expects. Say they "load" or "start" something asynchronously, and that finishes, the status should report "loaded" or "started", but that's not the case if we dispatch it to the main queue because that property doesn't update until the next iteration of the run loop.
There also isn't any information in the documentation for @Published that suggests that you must update it on the main thread. I understand why SwiftUI wants it on the main thread, but this property wrapper is in the Combine framework. Also it seems like SwiftUI internally could ask to receive the published updates on the main queue and @Published shouldn't enforce a specific thread.
One thing we are thinking about doing is writing our own property wrapper, but that doesn't seem to be ideal for SwiftUI integration and it's one more property wrapper that users of our package would need to be educated about.
Any thoughts on direction? Is there anyway to break @Published from the main thread?
This question was originally posted to StackOverflow, but I found it more suitable to be placed here.
Was working on migrating one of my app from AppDelegate lifecycle to SwiftUI lifecycle according to this question.
After following all the steps, The simulator simply shows a blank screen (the app does not launch at all):
There is no log in the console. However, if the app is removed from the simulator (or device) and reinstalled, it will launch the new SwiftUI lifecycle correctly. So there seems to be some problem with scene caching that causes iOS to be confused after the migration.
Am I missing something during the migration?
SwiftUI Preview Don't work.
Progress Preparing iPhone Simulator for Previews.
SwiftUI
Xcode version 13.0
macOS Big Sur version 11.6
I have a SwiftUI menu
Menu{
....
}, label : {
Image(...).accessibility(identifier: "cardMenu")
}
I used to be able to bring up the menu (before upgrading to xcode 13 (ios15)) like this
let app = XCUIApplication()
app.launch()
app.buttons["cardMenu"].tap()
But now i am unable to see the identifier in app.buttons. Can't seem to find the identifier anymore. I've tried looking for the identifier in the other app fields and changing to use text instead of identifer. No luck. These tests used to work prior to the upgrade.
Any help would be appreciated