-
Bring Core Data concurrency to Swift and SwiftUI
Discover how Core Data is adopting the new concurrency capabilities of Swift 5.5, leading to more concise, efficient, and safe asynchronous code. We'll show you how to update Core Data in your apps to work with concurrency, and detail the many other improvements throughout the framework that make working with Swift and SwiftUI more expressive and powerful.
Recursos
Videos relacionados
WWDC21
-
Buscar este video…
-
-
20:36 - FetchRequest dynamic configuration: sort descriptors
private let sorts = [( name: "Time", descriptors: [SortDescriptor(\Quake.time, order: .reverse)] ), ( name: "Time", descriptors: [SortDescriptor(\Quake.time, order: .forward)] ), ( name: "Magnitude", descriptors: [SortDescriptor(\Quake.magnitude, order: .reverse)] ), ( name: "Magnitude", descriptors: [SortDescriptor(\Quake.magnitude, order: .forward)] )] struct ContentView: View { @FetchRequest(sortDescriptors: [SortDescriptor(\Quake.time, order: .reverse)]) private var quakes: FetchedResults<Quake> @State private var selectedSort = SelectedSort() var body: some View { List(quakes) { quake in QuakeRow(quake: quake) } .toolbar { ToolbarItem(placement: .primaryAction) { SortMenu(selection: $selectedSort) .onChange(of: selectedSort) { _ in let sortBy = sorts[selectedSort.index] quakes.sortDescriptors = sortBy.descriptors } } } } struct SelectedSort: Equatable { var by = 0 var order = 0 var index: Int { by + order } } struct SortMenu: View { @Binding private var selectedSort: SelectedSort init(selection: Binding<SelectedSort>) { _selectedSort = selection } var body: some View { Menu { Picker("Sort By", selection: $selectedSort.by) { ForEach(Array(stride(from: 0, to: sorts.count, by: 2)), id: \.self) { index in Text(sorts[index].name).tag(index) } } Picker("Sort Order", selection: $selectedSort.order) { let sortBy = sorts[selectedSort.by + selectedSort.order] let sortOrders = sortOrders(for: sortBy.name) ForEach(0..<sortOrders.count, id: \.self) { index in Text(sortOrders[index]).tag(index) } } } label: { Label("More", systemImage: "ellipsis.circle") } .pickerStyle(InlinePickerStyle()) } private func sortOrders(for name: String) -> [String] { switch name { case "Magnitude": return ["Highest to Lowest", "Lowest to Highest"] case "Time": return ["Newest on Top", "Oldest on Top"] default: return [] } } } } -
21:33 - FetchRequest dynamic configuration: predicates
struct ContentView: View { @FetchRequest(sortDescriptors: [SortDescriptor(\Quake.time, order: .reverse)]) private var quakes: FetchedResults<Quake> @State private var searchText = "" var query: Binding<String> { Binding { searchText } set: { newValue in searchText = newValue quakes.nsPredicate = newValue.isEmpty ? nil : NSPredicate(format: "place CONTAINS %@", newValue) } } var body: some View { List(quakes) { quake in QuakeRow(quake: quake) } .searchable(text: query) } } -
23:26 - SectionedFetchRequest
extension Quake { lazy var dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "MMMM d, yyyy" return formatter }() @objc var day: String { return dateFormatter.string(from: time) } } struct ContentView: View { @SectionedFetchRequest( sectionIdentifier: \.day, sortDescriptors: [SortDescriptor(\Quake.time, order: .reverse)]) private var quakes: SectionedFetchResults<String, Quake> var body: some View { List { ForEach(quakes) { section in Section(header: Text(section.id)) { ForEach(section) { quake in QuakeRow(quake: quake) } } } } } } -
24:56 - SectionedFetchRequest dynamic configuration: sort descriptors
extension Quake { lazy var dateFormatter: DateFormatter = { let formatter = DateFormatter() formatter.dateFormat = "MMMM d, yyyy" return formatter }() @objc var day: String { return dateFormatter.string(from: time) } @objc var magnitude_str: String { return "\(magnitude)" } } private let sorts = [( name: "Time", descriptors: [SortDescriptor(\Quake.time, order: .reverse)], section: \Quake.day ), ( name: "Time", descriptors: [SortDescriptor(\Quake.time, order: .forward)], section: \Quake.day ), ( name: "Magnitude", descriptors: [SortDescriptor(\Quake.magnitude, order: .reverse)], section: \Quake.magnitude_str ), ( name: "Magnitude", descriptors: [SortDescriptor(\Quake.magnitude, order: .forward)], section: \Quake.magnitude_str )] struct ContentView: View { @SectionedFetchRequest( sectionIdentifier: \.day, sortDescriptors: [SortDescriptor(\Quake.time, order: .reverse)]) private var quakes: SectionedFetchResults<String, Quake> @State private var selectedSort = SelectedSort() var body: some View { List { ForEach(quakes) { section in Section(header: Text(section.id)) { ForEach(section) { quake in QuakeRow(quake: quake) } } } } .toolbar { ToolbarItem(placement: .primaryAction) { SortMenu(selection: $selectedSort) .onChange(of: selectedSort) { _ in let sortBy = sorts[selectedSort.index] let config = quakes config.sectionIdentifier = sortBy.section config.sortDescriptors = sortBy.descriptors } } } } struct SelectedSort: Equatable { var by = 0 var order = 0 var index: Int { by + order } } struct SortMenu: View { @Binding private var selectedSort: SelectedSort init(selection: Binding<SelectedSort>) { _selectedSort = selection } var body: some View { Menu { Picker("Sort By", selection: $selectedSort.by) { ForEach(Array(stride(from: 0, to: sorts.count, by: 2)), id: \.self) { index in Text(sorts[index].name).tag(index) } } Picker("Sort Order", selection: $selectedSort.order) { let sortBy = sorts[selectedSort.by + selectedSort.order] let sortOrders = sortOrders(for: sortBy.name) ForEach(0..<sortOrders.count, id: \.self) { index in Text(sortOrders[index]).tag(index) } } } label: { Label("More", systemImage: "ellipsis.circle") } .pickerStyle(InlinePickerStyle()) } private func sortOrders(for name: String) -> [String] { switch name { case "Magnitude": return ["Highest to Lowest", "Lowest to Highest"] case "Time": return ["Newest on Top", "Oldest on Top"] default: return [] } } } }
-