Home Blog

ios – Listing will not replace when merchandise is deleted


I’ve two selectable lists, the primary is populated with Class mannequin objects and the second with Subcategory mannequin objects (that are taken from chosen Class worth of the primary checklist).

Once I delete an merchandise from the primary checklist, the second checklist doesn’t replace. Here’s a video that exhibits what I imply: https://youtube.com/shorts/VJCe_UK0TNA

I’ve coded the selectable lists in order that the chosen object is retrieved from a computed property binding that returns the item with the latest chosen date:

personal var selectedCategoryBinding: Binding
{
    return Binding(get: { self.classes.max(by: { ($0.lastSelectedDate) < ($1.lastSelectedDate) })}, set:{_ in})
}

personal var selectedSubcategoriesBinding: Binding<[Subcategory1]?>
{
    Binding<[Subcategory1]?>(get: { self.selectedCategoryBinding.wrappedValue?.subcategories }, set: { self.selectedCategoryBinding.wrappedValue?.subcategories = $0 })
} 

I concern that this can be the place the issue lies, however I am uncertain the right way to repair it. Beneath is the whole code. Any assist could be appreciated.

import SwiftUI
import SwiftData

protocol SelectableListItem: Equatable, Identifiable, PersistentModel {
    var identify: String { get set }
    var lastSelectedDate: Date { get set }
}

@Mannequin
closing class Project1 {
    var identify: String = ""
    @Relationship(deleteRule: .cascade, inverse: Category1.undertaking) var classes: [Category1]?
    
    init(identify: String) {
        self.identify = identify
    }
}

@Mannequin
closing class Category1: SelectableListItem {
    var identify: String = ""
    @Relationship(deleteRule: .cascade, inverse: Subcategory1.class) var subcategories: [Subcategory1]?
    var undertaking: Project1?
    var lastSelectedDate: Date = Date.now
    
    init(identify: String) {
        self.identify = identify
    }
}

@Mannequin
closing class Subcategory1: SelectableListItem {
    var identify: String = ""
    var class: Category1?
    var lastSelectedDate: Date = Date.now
    
    init(identify: String) {
        self.identify = identify
    }
}

struct HomeView: View {
    @Setting(.modelContext) personal var modelContext
    @Question personal var queriedProjects: [Project1]

    var physique: some View {
        NavigationStack {
            VStack {
                Listing {
                    ForEach(queriedProjects) { undertaking in
                        if let categoriesBinding = Binding(
                            Binding<[Category1]?>(
                                get: { undertaking.classes },
                                set: { undertaking.classes = $0 }
                            )
                        ) {
                            NavigationLink(
                                vacation spot: ProjectView1(undertaking: undertaking, classes: categoriesBinding),
                                label: { Textual content(undertaking.identify) }
                            )
                        }
                    }
                }
                .toolbar {
                    ToolbarItem(placement: .navigationBarTrailing) {
                        Button {
                            let undertaking = Project1(identify: "Undertaking 1")
                            
                            let subcategory1 = Subcategory1(identify: "Subcategory 1")
                            let subcategory2 = Subcategory1(identify: "Subcategory 2")
                            let subcategory3 = Subcategory1(identify: "Subcategory 3")
                            let subcategory4 = Subcategory1(identify: "Subcategory 4")
                            
                            let category1 = Category1(identify: "Class 1")
                            category1.subcategories = [subcategory1, subcategory2]
                            
                            let category2 = Category1(identify: "Class 2")
                            category2.subcategories = [subcategory3, subcategory4]
                            
                            undertaking.classes = [category1, category2]
                            modelContext.insert(undertaking)
                        } label: {
                            Label("Plus", systemImage: "plus")
                        }
                    }
                }
            }
            .overlay {
                if queriedProjects.isEmpty {
                    Textual content("Faucet the + button to create a brand new undertaking")
                }
            }
            .process {
                do {
                    attempt modelContext.delete(mannequin: Project1.self)
                } catch {
                    fatalError(error.localizedDescription)
                }
            }
        }
        .navigationSplitViewStyle(.balanced)
    }
}

struct ProjectView1: View {
    @Bindable var undertaking: Project1
    @Binding var classes: [Category1]
    
    @Setting(.editMode) personal var editMode
    @Setting(.modelContext) personal var modelContext
    
    @State personal var columnVisibility: NavigationSplitViewVisibility = .all

    personal var selectedCategoryBinding: Binding {
        Binding(
            get: { classes.max(by: { $0.lastSelectedDate < $1.lastSelectedDate }) },
            set: { _ in }
        )
    }
    
    personal var selectedSubcategoriesBinding: Binding<[Subcategory1]?> {
        Binding<[Subcategory1]?>(
            get: { selectedCategoryBinding.wrappedValue?.subcategories },
            set: { selectedCategoryBinding.wrappedValue?.subcategories = $0 }
        )
    }
    
    var physique: some View {
        NavigationSplitView(columnVisibility: $columnVisibility) {
            SelectableList(gadgets: $classes) { class in
                class.undertaking = nil
            }
            
            if !classes.isEmpty {
                if let subcategoriesBinding = Binding(selectedSubcategoriesBinding) {
                    SelectableList(gadgets: subcategoriesBinding) { subcategory in
                        subcategory.class = nil
                    }
                }
            }
        } element: {
            EmptyView()
        }
    }
}

struct SelectableList: View {
    @Binding var gadgets: [T]
    personal(set) var deleteItem: (T) -> Void
    
    @Setting(.modelContext) personal var modelContext
    @Question personal var queriedItems: [T]
    
    personal var filteredAndSortedItems: [T] {
        queriedItems
            .filter { gadgets.incorporates($0) }
            .sorted { $0.identify.localizedCaseInsensitiveCompare($1.identify) == .orderedAscending }
    }
    
    personal var selectedItem: T? {
        filteredAndSortedItems.max(by: { $0.lastSelectedDate < $1.lastSelectedDate })
    }
    
    var physique: some View {
        Listing {
            ForEach(filteredAndSortedItems) { merchandise in
                HStack {
                    Button {
                        if selectedItem != merchandise {
                            merchandise.lastSelectedDate = .now
                        }
                    } label: {
                        Textual content(merchandise.identify)
                    }
                    .buttonStyle(PlainButtonStyle())
                                                                                                
                    if selectedItem == merchandise {
                        Picture(systemName: "checkmark")
                    }
                    
                    Spacer()
                    
                    Button {
                        deleteItem(merchandise)
                        modelContext.delete(merchandise)
                    } label: {
                        Picture(systemName: "trash")
                    }
                }
            }
        }
    }
}

webkit – iOS 26 internet web page with script is terminated on customized scheme WKURLSchemeHandler


One thing has modified in iOS 26 (examined on beta 4) and now if customized scheme is used and internet web page accommodates script aspect then WebKit is terminated with following log:

0x1130bc170 - [PID=47858] WebProcessProxy::didClose: (internet course of 0 crash)
0x1130bc170 - [PID=47858] WebProcessProxy::processDidTerminateOrFailedToLaunch: motive=Crash

Steps to breed:

  1. Create WKWebView with customized configuration and customized url scheme handler
  2. Load HTML with script aspect inside that references to a different file

Anticipated consequence: WKWebView is loaded

Precise consequence: WKWebView is terminated

Code instance:

last class CustomSchemeViewController: UIViewController {
    override func viewDidLoad() {
        tremendous.viewDidLoad()

        let sampleConfiguration = WKWebViewConfiguration()
        sampleConfiguration.setURLSchemeHandler(
            SampleURLSchemeHandler(),
            forURLScheme: "pattern"
        )

        let webView = WKWebView(body: view.bounds, configuration: sampleConfiguration)
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)

        webView.navigationDelegate = self

        webView.load(URLRequest(url: URL(string: "pattern://pages/pattern.html")!))
    }
}

extension CustomSchemeViewController: WKNavigationDelegate {
    func webViewWebContentProcessDidTerminate(_ webView: WKWebView) {
        print("webViewWebContentProcessDidTerminate")
    }
}

last class SampleURLSchemeHandler: NSObject, WKURLSchemeHandler {
    personal func submit(_ physique: String, mimeType: String, urlSchemeTask: WKURLSchemeTask) {
        let physique = Information(physique.utf8)

        let response = URLResponse(
            url: urlSchemeTask.request.url!,
            mimeType: mimeType,
            expectedContentLength: physique.depend,
            textEncodingName: nil
        )

        urlSchemeTask.didReceive(response)
        urlSchemeTask.didReceive(physique)
        urlSchemeTask.didFinish()
    }

    func webView(_ webView: WKWebView, begin urlSchemeTask: WKURLSchemeTask) {
        change urlSchemeTask.request.url?.lastPathComponent {
        case "pattern.html":
            submit("""