I tried the example from https://developer.apple.com/documentation/swiftui/editmode. It's not working for me.
struct ContentView: View {
@Environment(\.editMode)
private var editMode
@State
private var name = "Maria Ruiz"
var body: some View {
NavigationView {
Form {
Text(String(editMode!.wrappedValue.isEditing))
if editMode?.wrappedValue.isEditing == true {
TextField("Name", text: $name)
} else {
Text("test")
}
}
.animation(nil, value: editMode?.wrappedValue)
.toolbar { // Assumes embedding this view in a NavigationView.
EditButton()
}
}
}
}
It shows the texts "false" and "test", before and after clicking Edit. What am I missing? I'm using XCode 14.0.1 and the deployment target is iOS 16. I also tried on a real iPhone and on iOS 15.5 in the Simulator. Thanks for any help.
SwiftUI
RSS for tagProvide views, controls, and layout structures for declaring your app's user interface using SwiftUI.
Post
Replies
Boosts
Views
Activity
Good morning!
I am developing an iOS app that gets its data from an API and displays it in a list. The list item view has NavigationLink embedded in it that sends users to a detail view. In this detail view, I have some Text views but the issue I am running into is a WKWebView that I have implemented to display some HTML that's is retrieved from the API call.
The WKWebView displays the HTML just how I want it to. The issue I have is in the HyperLinks that are displayed in the WKWebView. When a user taps on a link, it opens inside of the web view. Instead of opening in the web view, I would like this link to open in the user's default web browser. I have searched and found ways of doing this in older versions of Swift using classes but my web view is initialized inside of a struct that conforms to the UIViewRepresentable protocol.
I don't know how to get links to open in the browser instead of the WebView so any help would be appreciated. Here is the code for my WebView that is being used on the details page.
struct NewsItemWebView: UIViewRepresentable {
// HTML from API Call
var text: String
// Method to create the View
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
// Method to update the View by changing properties of the WebView
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.isOpaque = false
uiView.backgroundColor = UIColor.white
uiView.loadHTMLString(text, baseURL: nil)
}
}
Here is how I am implementing the WebView on DetailView
NewsItemWebView(text: item.PageContent)
.frame(height: 450)
Any help on how I can make links open in a browser would be great. Thanks in advance.
In the sidebar column of the NavigationSplitView I'd like to have several sections. All the items are fetched with Core Data.
View all photos (Photos entity in Core Data)
Folder (Folder entity in Core Data)
Folder A
Folder B
Folder C
Tags (Tag entity in Core Data)
Cat
Dog
In the content view, I'd like show the items based on the selection in the sidebar. I tried the following with some success but I think there should be another way of doing this.
NavigationSplitView() {
List(selection: $navigationModel.selectedCategory, content: {
NavigationLink(value: Category(type: .all, predicate: NSPredicate(value: true), title: "View all items") ) {
Text("View all items")
}
Section {
ForEach(folders){ folder in
NavigationLink(value: Category(type: .folder, predicate: NSPredicate(format: "folder == %@", folder), title: folder.name) ) {
FolderRow(folder: folder)
// ... and so on. Another section for tags
And in the content:
ZStack{
List(selection: $navigationModel.selectedPhoto) {
ContentView(photos: FetchRequest(
sortDescriptors: [sortDescriptor],
predicate: navigationModel.selectedCategory?.predicate,
animation: .default)
//....
How can refractor this code with a better solution? The problem that I'm encountering is that the selection argument in the List accepts only one type of object. But I want to select more that one type of object. Another issue is that this solution won't conform to Codable if I'm thinking correctly and reseting the app state on the next launch would be cumbersome.
So I have the default language of my app as Arabic so everything goes from RTL but when I changed the default language to Arabic I started encountering this issue that happens when navigating from one view to another view.
This issue shows the text inverted in a weird way.
here is the image: https://imgur.com/amI8afA
(note that this issue goes away if the TabView is not PageTabViewStyle)
So I'm trying to use MapKit in a SwiftUI project targeting iOS/iPadOS. MapKit is obviously pretty limited in SwiftUI, but I've been getting warnings trying to set up basic annotations for the user to interact with.
When I use a basic MapMarker everything is fine (although it's hard to do anything with it), but whenever I do anything with MapAnnotation, I get this warning in Xcode (14.0.1) whenever I move the map around:
[SwiftUI] Publishing changes from within view updates is not allowed, this will cause undefined behavior.
I'm no SwiftUI expert, and I get how to fix this issue when binding in something like a sheet, but I don't see how what I'm doing with MapAnnotation should be causing this.
It looks like a bug to me, possibly complaining about the $region binding, but maybe I'm wrong? Am I doing something wrong or is this a bug?
Below is some sample code that reproduces this easily for me (just launch an app with the below code and then drag the map around to see the constant warnings in Xcode). It's mostly an example from here: https://www.hackingwithswift.com/books/ios-swiftui/integrating-mapkit-with-swiftui
import SwiftUI
import MapKit
struct Location: Identifiable {
let id = UUID()
let name: String
let coordinate: CLLocationCoordinate2D
}
struct ContentView: View {
@State private var region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: 51.5, longitude: -0.12), span: MKCoordinateSpan(latitudeDelta: 0.2, longitudeDelta: 0.2))
let locations = [
Location(name: "Buckingham Palace", coordinate: CLLocationCoordinate2D(latitude: 51.501, longitude: -0.141)),
Location(name: "Tower of London", coordinate: CLLocationCoordinate2D(latitude: 51.508, longitude: -0.076))
]
var body: some View {
Map(coordinateRegion: $region, annotationItems: locations) { location in
MapAnnotation(coordinate: location.coordinate) {
Circle()
.stroke(.red, lineWidth: 3)
.frame(width: 44, height: 44)
}
}
.navigationTitle("Map")
.edgesIgnoringSafeArea(.all)
}
}
Code to reproduce:
struct CrashView: View {
var body: some View {
ScrollView {
LazyVStack {
ForEach(0...100, id: \.self) { i in
LazyVGrid(columns: Array(repeating: .init(.fixed(100)), count: 3), content: {
ForEach(0...20, id: \.self) { i in
Color.red.opacity(Double(i + 1) / 20).frame(height: 300)
}
})
}
}
}
}
}
Important: it crashes on iOS 16.1 !!!
We have 21 grid item (3 item and 7 full lines) for every LazyVStack item.
Scroll it until 5 LazyVStack item. Start scrolling to top. It blinks and show incorrect count: you see that it shows 1 item in line, but it is impossible. If you continue scrolling app crashes.
I have a class that I cannot change to ObservableObject with Published members.
I tried getting around this by writing my own Binding. Although the value is updated correctly, the UI is not. Why is this.
Below is a simple demo view. When it is run and the toggle is clicked, it will print out correctly that the value is changed, but the UI does not update. Why?
import SwiftUI
class BoolWrapper {
public var value = false {
didSet {
print("Value changed to \(value)")
}
}
}
let boolWrapper = BoolWrapper()
struct ContentView: View {
var body: some View {
Toggle(isOn: Binding(get: {
return boolWrapper.value
}, set: { value in
boolWrapper.value = value
}), label: { Text("Toggle") })
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
while resizing screen on mac, start getting this weird error
[API] cannot add handler to 3 from 3 - dropping
All lazyVgrids fail to show afterwards then app crashes if you keep resizing.
This error started with macOS Ventura.
Any help much appreciated.
I have a project that requires a fixed window size. In previous versions of Xcode when I compile the project with the following :
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.frame(width: 800, height: 600)
}
}
}
It will result in a window with a fixed size of 800x600 (i.e. the window inherits the fixed content size)
With Xcode 14 and macOS Ventura, this is no longer the case. The above code compiles but now the window is resizable, with the content inhabiting an 800x600 area.
In Ventura there is the .windowResizability(.contentSize) property but this is macOS 13 only. I need my app to be able to support macOS 11 and 12 and now the window behaviour is broken with the latest Xcode.
Is there any way to get around this that doesn't involve running a seperate macOS 12/Xcode 13 environment?
Hello all,
In a SwiftUI List, when a row is selected, a blue selection is drawn in the selection, and foreground Text with the default primary color is automatically made white. For other views with custom colors, I'd like to be able to make sure they become tinted white to match the system apps. For example, see the blue dot on the selected row:
Example code:
List(selection: $selection) {
ForEach(0..<4) { index in
HStack {
Image(systemName: "circle.fill")
.foregroundColor(.blue)
Text("Test")
}
.tag(index)
}
}
With NSTableCellView, there is the backgroundStyle property. I've searched all of the available environment variables, and couldn't find anything appropriate. I have also tried manually including an isSelected binding on a view for each row, but the selection binding is not updated by List until mouse-up, while the highlight is updated on mouse-down and drag, so this results in a flickery appearance and is not right either.
Any tips on how to achieve the correct result here? Thanks! 🙏
I'm using Xcode 14.1 to start a Core Data project. I created a new Project, checking CoreData. The resulting program works in Preview and in the Simulator.
I've changed the data from a Item/timestamp to Locations/title. I plan to add more Attributes but that's for later.
I think I've got all the Item instances changed to Locations and timestamp to title. It seems to work OK when in Preview for ContentView.swift but crashes in the Simulator with the error
Swift/UnsafeRawBufferPointer.swift:946: Fatal error: UnsafeRawBufferPointer with negative count
Any suggestions on what I have done wrong? Thanks.
PS, the New Project includes the line Text("Select a location") but Select a location doesn't appear in the Preview.
In my app I try to use SwiftUI's ShareLink to offer sharing of the app's documents.
I followed this video for defining the exported type and the document type.
Unfortunately if I use any ShareLink initializer for sharing Transferable items, the option "save to files" is not offered on the displayed share sheet. (Only "copy" is offered, which works if pasted into the destination directory using the Files app, but that is not an acceptable workaround).
PS: com.example.transferabletestis defined as conforming to com.apple.package
import SwiftUI
import UniformTypeIdentifiers
extension UTType{
static let transferableTest = UTType(exportedAs: "com.example.transferabletest")
}
struct Document:Transferable{
static let filePackageURL = URL.documentsDirectory.appending(components: "0815.transferabletest")
public static var transferRepresentation: some TransferRepresentation {
FileRepresentation(exportedContentType: .transferableTest) { document in
_ = try? FileManager.default.createDirectory(at: Self.filePackageURL, withIntermediateDirectories: false)
FileManager.default.createFile(atPath: Self.filePackageURL.appending(components: "data").path(), contents: "Transferable Test\n".data(using: .utf8))
return SentTransferredFile(Document.filePackageURL)
}
}
}
struct ContentView: View {
var body: some View {
ShareLink("Share as tranferable item", item: Document(), preview: SharePreview("Test"))
}
}
Is this a bug?
What am I doing wrong?
Sharing the document using the ShareLink for URLs does offer "save to files" but I can't use that in my app for various reasons.
There is a conflict when I use selection and onDrag for a list, onDrag blocks the selection on macOS. I think the problem comes from the fact that selection works on mouseDown and the same for onDrag.
So, when the mouseDown event is triggered, swiftUI call the last modifier which is onDrag and it doesn't trigger the selection anymore.
When I check on the Finder app, I noticed that the selection is triggered on mouseUp, which confirms my theory. Moreover, on finder, they combine onDrag, selection, and doubleClick without any conflict. Therefore, I'm pretty sure there is a workaround, but I can't figure it out...
Did anyone already face this issue and found a workaround?
I have app that shows live activity and countdown till a date...
VStack {
Text("Countdown till You finish your homework")
Text(countdownTime, style: .timer)
}
After the time up, the live activity countup, the solution is to update the live activity via backgroundTask and this not always working, really apple sometimes fire the backgroundTask after hours.
Another solution is to set dismissalPolicy: .after(countdownTime), but once I did that the dynamic island not working and the activity status is ended after right calling...
await activity.end(using: state, dismissalPolicy: .after(countdownTime))
Can anyone help please, users feed back is why you we still see the old task on live activity. How come I can not update live activity? and how come if you set dismissalPolicy .after apple changes the activity status to ended and stop showing the dynamic island?
Before iOS 16.1 my app was woking good, if the user set the app language to other language than his device language, my app, widget + extensions all use this language...
After iOS 16.1 if user set the app language to other language than his device language, my app works with this language but the widget + extensions works with the device language, not my app language...
For Example:
@Environment(\.locale.languageCode) private var userLocal
before iOS 16.1 userLocal would be the app local, after iOS 16.1 it return the device local
Any idea why Apple did that? is this a bug?
How to set the widget language to match my app language now? even set .environment(\.locale, dose not work when use Strings(table: because it's still get the bundle that match device language.
I am new to Swift and iOS development. I am trying to wrap a web app where the orientation is dependent on the URL. I have the code working with Stack Overflow as an example where "https://stackoverflow.com" displays in portrait and all other pages change to landscape after being loaded. I have a URL observer that triggers when the URL changes and calls requestGeometryUpdate. I'm running into the following problem:
When changing the orientation with requestGeometryUpdate, the orientation changes, but if the device is physically rotated after the change, the orientation changes again. I would like to make the orientation change locked and permanent until a new page is loaded.
Any help would be much appreciated. My code is below:
import SwiftUI
import WebKit
struct TestView: View {
private let urlString: String = "https://stackoverflow.com/"
var body: some View {
TestWebView(url: URL(string: urlString)!)
.background(Color.black)
.scrollIndicators(.hidden)
.ignoresSafeArea([.all])//stretchs webview over notch on iphone
.defersSystemGestures(on:.bottom)//deprioritizes multitasking indicator
.statusBar(hidden: true)//hides time and battery
}
}
class TestController: UIViewController {
var webview: WKWebView!
var webViewURLObserver: NSKeyValueObservation?
override func viewDidLoad() {
super.viewDidLoad()
let winScene = UIApplication.shared.connectedScenes.first
let windowScene = winScene as! UIWindowScene
webview = WKWebView(frame: self.view.frame)
webview.autoresizingMask = [.flexibleWidth,.flexibleHeight]//makes webview fit screen in portrait and landscape
self.view.addSubview(self.webview)
webViewURLObserver = self.webview.observe(\.url, options: .new) { webview, change in
let url=change.newValue!!;//! converts from optional to string
print(url)
let arr = url.absoluteString.split(separator: "stackoverflow.com").map(String.init)
var portrait=false
if(arr.count>1){
let path = arr[1];
if path=="/"{
portrait=true
}
}
if portrait==true {
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .portrait)) { error in print(error)}
}
else{
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in print(error)}
}
self.setNeedsUpdateOfSupportedInterfaceOrientations()
}
}
}
// WebView Struct
struct TestWebView: UIViewControllerRepresentable {
let url: URL
func makeUIViewController(context: Context) -> TestController {
let webviewController = TestController()
return webviewController
}
func updateUIViewController(_ webviewController: TestController, context: Context) {
let request = URLRequest(url: url)
webviewController.webview.scrollView.contentInsetAdjustmentBehavior = .never
webviewController.webview.load(request)
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
Any one getting any issues with NavigaitonLink to seemingly innocuous views freezing when tapped on? 1 CPU at 100% memory steadily increasing until app gets killed by the system. Will freeze if any NavigationLink on the view is tapped if certain views are linked to using NavigaitonLink.
I note some people have been getting similar freezes if they use @AppStorage, but I'm not using @AppStorage. I do use CoreData tho. tho I have some views that use core data that don't freeze.
https://developer.apple.com/forums/thread/708592?page=1#736374022
has anyone experienced similar issues? or know the cause. it doesn't seem to be any of my code because if I pause the debugger it stops on system code.
Hi!
I have two problems with FileImport and FileExporter
Every time the file modal has been closed I get in the console this error/warning
[DocumentManager] The view service did terminate with error: Error Domain=_UIViewServiceErrorDomain Code=1 "(null)" UserInfo={Terminated=disconnect method}
The modal for FileExporter shows the label "Move", why? I'm creating a new file, not moving an existing one, since there is already the modifier FileMover. Is it correct? Can't be confusing for a user to see the label "Move"? Am I using it in the wrong way?
Can please someone help me with these two problems?
In a SwiftUI project I try to display a background image with ignoring safe area insets (to make it go edge to edge). However, the background scales incorrectly and doesn't respect its aspect ratio.
Here is a small code example of the view structure that I'm using:
struct ContentView: View {
var body: some View {
ZStack {
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.").padding()
}.frame(maxHeight: .infinity).background(Image("dots").resizable().ignoresSafeArea().scaledToFill())
}
}
And an example image for testing (when using this image you can clearly see the circles become more like ovals in the SwiftUI app):
Screenshot:
The following code works:
struct SelectBatteryChemistryView: View {
@ObservedObject var model: SelectBatteryChemistryViewModel = .init()
@Environment(\.presentationMode) private var presentationMode
var body: some View {
VStack {
Spacer()
TitleText("BATTERY MODE")
SimpleModeSelectorView(
selected: $model.batteryChemistry
)
.pickerStyle(.inline)
.frame(minHeight: 300)
PrimaryTitleButton(title: "SELECT") {
if model.batteryChemistry == .user {
model.customChemistryFlow = true
} else {
model.confirmBatterySettings()
}
}
NavigationLink(
destination: CustomBatteryChemistryView(),
isActive: $model.customChemistryFlow
) { EmptyView() }
.isDetailLink(false)
}
.onReceive(model.$batterySettingsConfirmed) { batterySettingsConfirmed in
if batterySettingsConfirmed {
//dismiss()
}
}
.onAppear() {
model.customChemistryFlow = false
}
}
}
The following code causes an infinite loop in the CustomBatteryChemistryView() initialiser.
struct SelectBatteryChemistryView: View {
@ObservedObject var model: SelectBatteryChemistryViewModel = .init()
@Environment(\.dismiss) private var dismiss
var body: some View {
VStack {
Spacer()
TitleText("BATTERY MODE")
SimpleModeSelectorView(
selected: $model.batteryChemistry
)
.pickerStyle(.inline)
.frame(minHeight: 300)
PrimaryTitleButton(title: "SELECT") {
if model.batteryChemistry == .user {
model.customChemistryFlow = true
} else {
model.confirmBatterySettings()
}
}
NavigationLink(
destination: CustomBatteryChemistryView(),
isActive: $model.customChemistryFlow
) { EmptyView() }
.isDetailLink(false)
}
.onReceive(model.$batterySettingsConfirmed) { batterySettingsConfirmed in
if batterySettingsConfirmed {
//dismiss()
}
}
.onAppear() {
model.customChemistryFlow = false
}
}
}
Adding the @Environment(.dismiss) object prevents the use of a navigation link. The program sits there with the stack infinitely calling the getter for the NavigationLink.
It looks like an infinite loop on the accessor due to some strangeness related to the magic of the Dismiss environment object.
How do we pass this on to the Dev team at Apple?