[Code-along] SwiftUI on the Mac: Build the fundamentals

RSS for tag

Discuss the WWDC21 session [Code-along] SwiftUI on the Mac: Build the fundamentals.

View Session

Posts under wwdc21-10062 tag

18 Posts
Sort by:
Post not yet marked as solved
1 Replies
214 Views
Hi, using the following ContentView in a SwiftUI app on macOS I would expect that the state of the toggle persists across application launches: struct ContentView: View { @SceneStorage("Toggle") var onOrOff: Bool = false var body: some View { VStack { Toggle("Will it persist?", isOn: $onOrOff) .padding() } } } To my surprise it does not persist. Am I wrong about how @SceneStorage should work? (I am trying this on the lates macOS/Xcode versions) Does @SceneStorage work for anybody on macOS? Thanks for your feedback! Cheers, Michael
Posted
by milutz.
Last updated
.
Post not yet marked as solved
5 Replies
973 Views
Hi, How can I use a Table view to build a data grid for a dynamic set of data? Say, I have a 2D collection of data elements (a matrix, basically) with variable number of columns, and a 1D collection of column labels (a vector). For the sake of simplicity, let's assume that all data elements are Strings. let data: [[String]]; let columnLabels: [String] How can I build TableColumn definitions without key paths? Thanks!
Posted
by ilia_saz.
Last updated
.
Post not yet marked as solved
1 Replies
164 Views
I am working through the "Creating and Combining Views" Swift UI Landmarks tutorial using MacOS 12.3 and XCode 13.3. When trying to preview the MapView I receive the error: |  LoadingError: failed to load library at path "/Users/Elizabeth_Russell/Library/Developer/Xcode/DerivedData/Landmarks-fifnagwlpuhontdywqyzptoyghbg/Build/Intermediates.noindex/Previews/Landmarks/Intermediates.noindex/Landmarks.build/Debug-iphonesimulator/Landmarks.build/Objects-normal/arm64/MapView.1.preview-thunk.dylib": Optional(dlopen(/Users/Elizabeth_Russell/Library/Developer/Xcode/DerivedData/Landmarks-fifnagwlpuhontdywqyzptoyghbg/Build/Intermediates.noindex/Previews/Landmarks/Intermediates.noindex/Landmarks.build/Debug-iphonesimulator/Landmarks.build/Objects-normal/arm64/MapView.1.preview-thunk.dylib, 0x0002): Symbol not found: _$s9Landmarks16MapView_PreviewsV8previewsQrvgZTx |    Referenced from: /Users/Elizabeth_Russell/Library/Developer/Xcode/DerivedData/Landmarks-fifnagwlpuhontdywqyzptoyghbg/Build/Intermediates.noindex/Previews/Landmarks/Intermediates.noindex/Landmarks.build/Debug-iphonesimulator/Landmarks.build/Objects-normal/arm64/MapView.1.preview-thunk.dylib |    Expected in: /Users/Elizabeth_Russell/Library/Developer/Xcode/UserData/Previews/Simulator Devices/49F2A163-EF87-47EC-B1F3-425A9742D1F7/data/Containers/Bundle/Application/0F7E6CF4-2589-42E5-B1C5-EE37941E4186/Landmarks.app/Landmarks) Can someone help me understand why the library is not being loaded? Thank you
Posted
by ERussell.
Last updated
.
Post not yet marked as solved
1 Replies
973 Views
How does one declare a TableColumn with a nullable field? I have a Book model with several nullable fields: struct Book: Codable, Equatable, Identifiable { // ... let productURL: String? // ... } This is how I'm trying define the corresponding TableColumn: TableColumn("Product URL", value: \.productURL) { book in Text(String(book.productURL ?? "")) } Though this results in several errors: Referencing initializer 'init(_:value:comparator:content:)' on 'TableColumn' requires that 'Book' inherit from 'NSObject' Referencing initializer 'init(_:value:comparator:content:)' on 'TableColumn' requires that 'Book' inherit from 'NSObject' Referencing initializer 'init(_:value:comparator:content:)' on 'TableColumn' requires the types 'KeyPathComparator' and 'SortDescriptor' be equivalent Referencing initializer 'init(_:value:comparator:content:)' on 'TableColumn' requires the types 'KeyPathComparator' and 'SortDescriptor' be equivalent Other, non-nullable columns work just fine. For example: TableColumn("ID", value: \.id) { book in     Text(String(book.id)) } TableColumn("Slug", value: \.slug) TableColumn("Category", value: \.category) TableColumn("Title", value: \.title) // ...
Posted Last updated
.
Post not yet marked as solved
1 Replies
197 Views
While passing data from ViewController to SecondViewController, the data remains nil. Can someone provide me with a working example? Thank you
Posted
by uhsnamih.
Last updated
.
Post not yet marked as solved
2 Replies
686 Views
The video wwdc21-10062 claimed that by using swiftUI developers can build an app with a detail panel (like the right sidebar in Xcode), but didn't say how to implement that. I have tried to use HSplitView but failed. My code is like: var body: some View { NavigationView { Text("sidebar") HSplitView { Text("Primary View") Text("Detail Panel") } } }
Posted Last updated
.
Post marked as solved
1 Replies
358 Views
This problem was posted previously but the answer was to update MacOS and Xcode. I am using the latest versions and the problem persists - for me at least. This is probably something really simple that everyone does and I just don't know about. I installed MacOS Monterey, XCode and downloaded the Building a Great Mac App with SwiftUI sample code so I can code along. After opening the workspace I added a developer account and added an Apple Development certificate. I think I should be able to build code now. I configure my developer team (for the target) to the development account I just setup, and the signing certificate to "Development". 2 warnings appear before I do anything: asking me to enable hardened runtime. Since it recommends I should do this, I tell it it's ok to go ahead and configure this. This gets rid of all the warnings for the moment. I open the ContentView (Part1 start -> GardenApp -> Garden App -> Navigation -> ContentView). An error shows instead of a preview: "Cannot preview the file - active scheme does not build this file". There's an information icon next to the error that reveals: "Select a scheme that builds a target which contains the current file, or add this file to a target that is built by the current scheme." When I search for "scheme" in the build settings I get nothing. This seems pretty odd. Any suggestions on how to resolve this would be great.
Posted
by ty-n.
Last updated
.
Post not yet marked as solved
0 Replies
240 Views
Hi, has anyone experienced the same problem? Also, while the New Plant menu command seems to work at least one time, the WaterPlants Menu command creates the same crash... Debug instrumentation shows a race condition in memory consumption, and the app needs to be force quit or the debug process terminated in Xcode. XCode Version is: 13.2 (13C90) MacOS Version is: 12.1 MacOS Build Target is: 12.0 Machine is: MacBook Air M1 2020, 8GB RAM, 256 GB SSD.
Posted
by Beato.
Last updated
.
Post not yet marked as solved
1 Replies
352 Views
I am using the new SwiftUI Table() structure available for macOS. This structure takes a selection of multiple rows as a Set<Object.ID> and can be stored in a state property wrapper like so... @State private var selectedPeople = Set<Person.ID>() (per the example in the Apple documentation) Table() doesn't take any other type of identifier (that I am aware of), so I am constrained to use the ObjectIdentifier unique identifier. I am using Table() to present a list of NSManagedObjects. These NSManagedObjects are sourced from a Core Data Entity relationship property, in this case via a @FetchRequest. I want to be able to add new instances of the entity and also delete existing instances of the entity. I have worked out how to add a new instance - this is relatively easy. What I am struggling to work out is how to delete an NSManagedObject from the Table() by using the Object.ID that is used to track row selection. I have attempted this...     @State private var tableSelection = Set<Action.ID>() ... for actionID in tableSelection { let context = event.managedObjectContext let actionToDelete = context?.object(with: actionID) print(actionToDelete) context?.delete(actionToDelete) } but of course I have a type mismatch here and the compiler complains... Cannot convert value of type 'Action.ID' (aka 'ObjectIdentifier') to expected argument type 'NSManagedObjectID' So how I do grab a reference to the selected NSManagedObject from the set of Action.ID?
Posted Last updated
.
Post not yet marked as solved
2 Replies
451 Views
Hi everyone! So i have recently decided to start watching apple code along tutorials. The one i've chosen is "SwfiftUI on the mac" and when i build the project, it fails and says: Signing for "Garden App" requires a development team. Select a development team in the Signing & Capabilities editor. I have specified the team (my account) and Signing Certificate, which is set to "Sign to run locally". I tried to set Xcode settings to default, but it didn't help.
Posted
by Maaaks.
Last updated
.
Post not yet marked as solved
0 Replies
296 Views
This is a followup to SwiftUI Table does not work when trying to use Int values After getting a result from looking up an album or song in AppleMusic API, I parse the returned json using SwiftyJSON as shown here:  URLSession.shared.dataTask(with: musicRequest) { (data, response, error) in             guard error == nil else { return }             if let json = try? JSON(data: data!) {                 let result = (json["data"]).array!                 for songDetail in result {                     let attributes = songDetail["attributes"]                     let song = SongDetails(albumName: attributes["albumName"].string!,                                artistName: attributes["artistName"].string!,                                artworkURL: attributes["artwork"]["url"].string!,                                composerName: attributes["composerName"].string ?? "-",                                discNumber: attributes["discNumber"].int!,                                durationInMillis: attributes["durationInMillis"].int!,                                genreNames: attributes["genreNames"].arrayValue,                                isrc: attributes["isrc"].string!,                                name: attributes["name"].string!,                                id: attributes["playParams"]["id"].string!,                                releaseDate: attributes["releaseDate"].string!,                                trackNumber: attributes["trackNumber"].int!)                     songDetails.append(song)                     print(songDetails)                 } Notice how [genreNames] needs ".arrayValue" instead of ".string!". I Think the reason is because "genreNames" are listed in an Array of Strings. Here is the data model I use for the parsed results: struct SongDetails {     var albumName: String     var artistName: String     var artworkURL: String     var composerName: String     var discNumber: Int     var durationInMillis: Int     var genreNames: Array<Any>     var isrc: String     var name: String     var id: String     var releaseDate: String     var trackNumber: Int     init(albumName: String, artistName: String, artworkURL: String, composerName: String, discNumber: Int, durationInMillis: Int, genreNames: Array<Any>, isrc: String, name: String, id: String, releaseDate: String, trackNumber: Int) {         self.albumName = albumName         self.artistName = artistName         self.artworkURL = artworkURL         self.composerName = composerName         self.discNumber = discNumber         self.durationInMillis = durationInMillis         self.genreNames = genreNames         self.isrc = isrc         self.name = name         self.id = id         self.releaseDate = releaseDate         self.trackNumber = trackNumber      } } Here I have genreNames as "Array". This set up works and I can call and print jus the genreNames, but everything I have read online says that "[String]" should be used instead of "Array", but if I do that, I get an error in the previous code when using [genreNames].string!. The way I currently have it set up, genreNames show up in the console as genreNames: [Pop, Music] , so I think it is correct. The issue arises when I try to use genreNames in a SwiftUI view. In my SwiftUI view I have a Table where these results go.             HStack {                 WebImage(url: URL(string: songDetail.artworkURL.replacingOccurrences(of: "{w}", with: "5000").replacingOccurrences(of: "{h}", with: "5000")))                     .resizable()                     .indicator(.activity)                     .frame(width: 400, height: 400)                     .cornerRadius(5)                     .shadow(radius: 2)                                  VStack (alignment: .leading) {                     Text("song id: \(songDetail.id)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("title: \(songDetail.name)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("artist: \(songDetail.artistName)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("composer: \(songDetail.composerName)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("disc number \(songDetail.discNumberString)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("track number: \(songDetail.trackNumberString)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("duration in ms: \(songDetail.durationInMillisString)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("release date: \(songDetail.releaseDate)")                         .foregroundColor(.secondary)                         .padding(2)                     Text("isrc: \(songDetail.isrc)")                         .foregroundColor(.secondary)                         .padding(2)                 }                 .font(.system(size: 14))                 }             }         }.padding(.leading, 20.0)         .frame(minWidth:800, idealWidth: 1000, maxWidth: .infinity, minHeight:600, idealHeight: 800, maxHeight: .infinity)         .onAppear {             SKCloudServiceController.requestAuthorization { (status) in                 if status == .authorized {                     self.searchResults = AppleMusicAPI().getSongDetails(self.songId)                 }             }         }     } } extension SongDetails {     var discNumberString: String {         String(discNumber)     }     var trackNumberString: String {         String(trackNumber)     }     var durationInMillisString: String {         String(durationInMillis)     } } The extension at the bottom is how the issue of the original post was solved. It seems that the new SwiftUI Table can only accept String values. To get the genreNames into this table I tried making a similar extension where I used join() to try and make a string of the genreResults, but that did not work either. I can't remember the exact code, but it could have been wrong. So how would this be accomplished? Anyone know? This is the last thing that I need to get into my Table. Thanks! I appreciate the help!
Posted Last updated
.
Post not yet marked as solved
2 Replies
627 Views
My project is a universal app with iOS 15 and macOS 12 targets, to attempt to take advantage of latest technologies, including SwiftUI and Table. I let Xcode take care of the CodeGen by selecting type "Class Definition" and then write Extensions for custom properties. I have an entity named Event with a class name PTG_Event. Each Event can have a number of actions and so each Event also has a one-to-many relationship with Action (class PTG_Action). I am attempting to use Table to display the actions for each event... but this doesn't work... struct ActionTable: View {     @ObservedObject var event: PTG_Event     @FetchRequest(entity: PTG_Action.entity(),                   sortDescriptors: []     ) var eventActions: FetchedResults<PTG_Action>     @State var sortOrder: [SortDescriptor<PTG_Action>] = [         .init(\.dateCommences, order: SortOrder.forward)     ]     var body: some View {         let events = eventActions.filter { $0.event == event }         Text("Action Table")         Table(events, sortOrder: $sortOrder) {             TableColumn("Ref", value: \.reference)             { action in                 Text(action.reference ?? "NO REF")             }             TableColumn("Date", value: \.dateCommences)             { action in                 Text(action.dateCommences?.formatted(date: .abbreviated, time: .omitted) ?? "NO DATE")             }         }     } } I have attempted many variations on this. Any suggestions?
Posted Last updated
.
Post marked as solved
3 Replies
802 Views
I opened the Session1 - Part1 - End file. In the "GardenDetail" view in the "Navigation" Folder of the project Xcode throws the error "cannot find 'Table' in scope". I did not changed anything from the original tutorial and have Xcode 13 and BigSur 11.6 on a M1 Mac.
Posted
by Jonas54.
Last updated
.
Post not yet marked as solved
1 Replies
405 Views
Aim To use a keyboard shortcut on a Multiplatform app (iOS and macOS) When keyboard shortcut is tapped, the price needs to be printed Problem The same code doesn't work on iPad but works on macOS Question: Why is not working? How to fix this? Environment macOS Big Sur - 11.6 (20G165) Version 13.0 (13A233) Code @main struct TestApp: App { @State private var price = 0 var body: some Scene { WindowGroup { ContentView(price: $price) .focusedValue(\.price, $price) } .commands { PriceCommands() } } } struct ContentView: View { @Binding var price: Int var body: some View { IncreasePriceButton(price: $price) } } struct IncreasePriceButton: View { @Binding var price: Int var body: some View { Button("Increase Price") { price += 1 print("price = \(price)") } } } struct PriceCommandButton: View { @FocusedBinding(\.price) var price var body: some View { Button("Print Price") { print("price = \(price)") } } } struct PriceCommands: Commands { var body: some Commands { CommandMenu("Custom") { PriceCommandButton() .keyboardShortcut(KeyboardShortcut("C", modifiers: [.command, .shift])) } } } struct FocusedPriceKey: FocusedValueKey { typealias Value = Binding<Int> } extension FocusedValues { var price: FocusedPriceKey.Value? { get { self[FocusedPriceKey.self] } set { self[FocusedPriceKey.self] = newValue } } }
Posted
by newwbee.
Last updated
.
Post not yet marked as solved
2 Replies
864 Views
Hi, I'm trying to use Table in an app sort of similar to the garden example but imagine if there was a third view in the NavigationView for a third column. And then imagine that if you selected a single plant in the middle table, a sort of detail inspector would appear in the third position with the data from your selection, updating as the selection in the middle table changed. I'm struggling a bit to get this working. I've tried: Wrapping the table column content closure's contents in a NavigationLink. This sort of works but it styles things oddly in the table column and as I scroll around, it seems to trigger on it's own, I'm guessing as cells are re-used or something behind the scenes. This feels wrong. Moving row creation into the rows: parameter with TableRow but the only modifier there is for drag and drop, there's no onTapGesture or similar. Watching for changes to the selected item via the binding and then acting on it then - this fires when I select stuff and I can get the related model object but I can't put a NavigationLink in there as it's outside of the view hierarchy so I'm not sure how to act on it. I'm guessing there's some other way to handle this that I'm simply not thinking of but if anyone has any pointers, much appreciated!
Posted
by Hunter.
Last updated
.
Post not yet marked as solved
3 Replies
1.5k Views
I'm working on what is essentially a "Hello World" app from the developer's conference. (Garden App) I'm trying to get the Automatic preview working, but I get "Automatic preview updating paused". I'm getting a bunch of errors, "Cannot find type 'KeyPathComparator' in scope. And a bunch of similar. Could someone please help?
Posted Last updated
.
Post not yet marked as solved
2 Replies
583 Views
I've been trying to use the Table function as described in the session. When I try expanding the table beyond 10 columns the compiler hangs with the issue "The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions." I've tried this in both the code provided in the session by replicating some of the given columns, and in other projects of my own. In all cases at adding the 11th column the same message is given. Does anyone know if there is a limit to the column count? Or if a workaround exists?
Posted
by gregwerth.
Last updated
.
Post not yet marked as solved
2 Replies
675 Views
While not a major problem, selecting table rows seems to be noticeably more sluggish compared to other apps that make heavy use of table views (such as Finder). In other words, the time between clicking and the table row visibly highlighting feels longer than in other apps. I assume this is due to some details in SwiftUI that have yet to be sorted out, or is it the fault of the Garden App sample code? Perhaps both?
Posted Last updated
.