Rather than selecting from a list, I'm trying to navigate between drawings like a book by using buttons to cycle through, but the canvas doesn't update.
I'm following the great tutorial by DevTechie for PencilKit in SwiftUI with CoreData.
The github repo is at [https://github.com/devtechie/DrawingDocuments]()
Here's my ContentView and my version of the DrawingWrapper. The DrawingWrapper uses a DrawingManager (SwiftUI) to pull from CoreData and the DrawingViewController to define a PKCanvas. I wasn't sure which delegate to use and really struggling understanding how to refresh the canvas.
ContentView
struct ContentView: View {
	@StateObject var manager = DrawingManager()
	@State var addNewShown = false
	@State var pageNumber: Int = 0
	@State var newVar = UUID()
	
	var body: some View {
	 VStack{
			Text(manager.docs[pageNumber].name!)
			HStack{
				Button(action:{
					pageNumber -= 1
					newVar = manager.docs[pageNumber].id!
					//desiredDoc = manager.docs[pageNumber]
				}){
					Image(systemName: "chevron.left")
				}
				Spacer()
				Button(action:{
					pageNumber += 1
					newVar = manager.docs[pageNumber].id!
					//desiredDoc = manager.docs[pageNumber]
				}){
					Image(systemName: "chevron.right")
				}
			}
	 }
}
DrawingWrapper
struct DrawingWrapper: UIViewControllerRepresentable {
	var manager: DrawingManager
	@Binding var doc: DrawingDoc
	
	typealias UIViewControllerType = DrawingViewController
	
	class Coordinator: NSObject, PKCanvasViewDelegate {
		var parent: DrawingWrapper
		init(_ parent: DrawingWrapper){
			self.parent = parent
		}
		
		func canvasViewDidFinishRendering(_ canvasView: PKCanvasView) {
			if let uiDrawing = canvasView.drawing as? PKDrawing {
				parent.doc.data = uiDrawing.dataRepresentation()
			}
		}
	}
	
	func makeCoordinator() -> Coordinator {
		Coordinator(self)
	}
	
	func makeUIViewController(context: UIViewControllerRepresentableContext<DrawingWrapper>) -> DrawingWrapper.UIViewControllerType {
		let viewController = DrawingViewController()
		viewController.drawingData = doc.data!
		viewController.drawingChanged = {data in
			manager.update(data: data, for: doc.id!)
		}
		viewController.delegate = context.coordinator
		return viewController
	}
	
	func updateUIViewController(_ uiViewController: DrawingViewController, context: UIViewControllerRepresentableContext<DrawingWrapper>) {
		uiViewController.drawingData = doc.data!
	}
}
Post
Replies
Boosts
Views
Activity
I now have a view where I need to display thousands of results from Core Data and I need to figure out how to handle the delay; either by optimizing the code, adding a ProgressView() or some other option. What is the best way to let the user know something is loading, or better yet, avoid the delay?
When I click on a button, there is an obvious and unwanted delay before it pushes to the new view displaying all the data. I've tried LazyVStack, but since I'm loading by sections, the view jumps around as data is loaded as the user scrolls.
I thought maybe using a technique similar to loading infinite lists, but can't figure out how that would work with a Core Data fetch and the sections/foreaches.
I also thought maybe using a ProgressView() but I can't figure out how to know that the results from the Core Data fetch have fully loaded.
Code snippet below the example (sorry if I missed a } or a )). I have categories of grouped items and want the view to look something like this:
Category 1
Group 1-1
Item 1-1-1
...
Item 1-1-n
Group 1-2
Item 1-2-1
...
Item 1-2-n
Category 2
Group 2-1
Item 2-1-1
and so on
BigView
var body: some View {
						ScrollView{
						//categoryList is a [String] of Category Names and each Group has an attribute called CategoryName
							ForEach(categoryList, id:\.self){category in
									Section(header:
														Text(category)
									){
										VStack{
										//Group is an entity in Core Data, and the fetchedEntity with a predicate on CategoryName
											ForEach(groups){group in
													BigSubView(group: Group)
												}
											}
										}
									}
							}
BigSubView
@ObservedObject var group: Group
var body: some View {
				Section(header:
								HStack{
									Text(group.wrappedName)
								}.background(Color(UIColor.systemFill))){
			
				VStack{
				//A Group has a one-many relationship with Item entity in Core Data, I convert that to an [Item]
					ForEach(group.itemsArray, id:\.self){item in
							Text(item.wrappedName)
				}
			}
		}
	}
I'm trying to filter such that criteria is met for each AND every item in a set vice each OR every item.
If I use groceryItem IN %@, desiredGroceries
it acts like an OR statement.
Example: I'm trying to view all grocery lists that included milk AND eggs (defined in desiredGroceries Set).
If I use the above code, it returns all lists that included milk as well as lists that included eggs.
But I only want the lists that include both milk and eggs.
What's the correct Predicate for this?
I am attempting to parse XML using an URLSession, XCode 12, SwiftUI but it keeps returning [] or nil. If I print immediately after the parse(see code), all the data is there, but for some reason, it seems to be clearing it all out.
If I try it with a .xml file, the code works fine, so it must be something in my URLSession in a XMLParserDelegate class:
class ParseController: NSObject, XMLParserDelegate{
var items: [Item] = []
var itemStore: [Item]?
func loadData() {		
		let url = URL(string: "website")!		
		let request=URLRequest(url: url)
		
		let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
			if data == nil {
				print("dataTaskWithRequest error: \(String(describing: error?.localizedDescription))")
				return
			}
			
			let parser = XMLParser(data: data!)
			parser.delegate=self
			parser.parse()
			
			self.itemStore=self.items
			print(self.itemStore)
		}
		task.resume()
		
		/*
		if let path = Bundle.main.url(forResource: "Items", withExtension: "xml") {
				if let parser = XMLParser(contentsOf: path) {
						parser.delegate = self
						parser.parse()
					self.itemStore=self.items
				}
		}
		*/
	}
And then I call that with a button in my View:
struct MyParserView: View {
	@State var itemsResult: [Item]?
	
	var body: some View {
		if ((itemsResult?.isEmpty) == nil) {
			VStack {
				Text("Stuff here")
				Button(action: {
					let parserControl = ParseController()
					parserControl.loadData()
					itemsResult = parserControl.itemStore
				}){
					Text("Push")
				}
			}
		}else {
			List{
				ForEach(itemResult!, id:\.id){item in
					Text(item.name)
				}
			}
		}
	}
}
Using XCode12, beta 4, I am trying to separate a header area and a ScrollView. I've tried both VStack and GeometryReader; however, when I click in the header area, the navigation link in the ScrollView item beneath it is triggered.
If I use a list, this undesired behavior is not observed. If I use the ScrollView in XCode 11.6 and build for iOS13, this undesired behavior is also not observed.
Did something change with ScrollViews in VStacks or GeometryReaders in iOS14?
struct ContentView: View {
var body: some View {
NavigationView{
//GeometryReader { geo in
VStack{
VStack{
Text("Blah")
}//.frame(height: geo.size.height*0.20)
VStack {
ScrollView {
ForEach(0..<10) { i in
NavigationLink(destination: Text("\(i)")) {
cardRow(i: i)
.frame(maxWidth: .infinity)
.foregroundColor(Color(UIColor.label))
.padding()
.background(RoundedRectangle(cornerRadius: 12))
.foregroundColor(Color(UIColor.secondarySystemFill))
.padding()
}
}
}
}//.frame(height: geo.size.height*0.90)
}
}.navigationViewStyle(StackNavigationViewStyle())
}
struct cardRow: View {
var i: Int
var body: some View {
HStack {
VStack {
Text("Www")
Text("88")
}.hidden()
.overlay(
VStack{
Text("\(i)")
}
)
Divider()
.background(Color(UIColor.label))
Spacer()
}
}
}
}