Как добавить CoreSpotlight в приложение macOS на Swift — индексирование CoreSpotlight

Как заставить CoreSpotlight индексировать приложение Mac?

Я не могу понять, как заставить мое приложение macOS индексироваться с помощью CoreSpotlight.

  1. Есть ли какая-то конфигурация, настройка Info.plist или возможность, которую мне нужно включить, чтобы она отображалась в результатах поиска Spotlight на Mac?
  2. Я делаю что-то неправильно? Ни один из примеров iOS, которые я конвертировал из iOS в macOS, мне не подходит.
  3. Я ожидаю увидеть свое приложение «TestSpotlight» в результатах поиска, но в Spotlight ничего не вижу.

import SwiftUI
import CoreSpotlight

@main
struct TestSpotlightApp: App {
    @NSApplicationDelegateAdaptor(AppDelegate.self) var delegate
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, NSApplicationDelegate {
    
    var searchableItems = [CSSearchableItem]()
    
    func addSearchableTerms() {
        let itemSet = CSSearchableItemAttributeSet(contentType: .content)
        let timerTitle = "10 min timer"
        let identifier = "com.myapp.timers.10min"
        itemSet.title = timerTitle
        itemSet.contentDescription = timerTitle
        itemSet.keywords = ["timer", "minute", "10", "ten"]
        itemSet.identifier = identifier
        itemSet.duration = NSNumber(integerLiteral: 10 * 60)
        
        let searchableItem = CSSearchableItem(uniqueIdentifier:identifier, domainIdentifier: "timers", attributeSet: itemSet)
        searchableItems.append(searchableItem)
        
        // TODO: Add more timers programmatically
        
        CSSearchableIndex.default().indexSearchableItems(searchableItems) { (error) in
            if let error = error {
                // handle failure
                print(error)
            } else {
                print("Indexed: \(self.searchableItems)")
            }
        }
    }
    
    func applicationDidFinishLaunching(_ notification: Notification) {
        addSearchableTerms()
    }
}

Использованная литература:

  1. Индексирование контента с помощью Core Spotlight
  2. Индексирование CoreSpotlight не работает

Клавиши plist необходимы, когда вы используете NSUserActivity для поиска Spotlight. Проверьте свой contentType, который вы передаете, .content — это общий тип, возможно, вы хотите использовать более конкретные типы. И вы всегда можете перестроить индекс Spotlight, чтобы убедиться, что он актуален.

ATV 31.05.2024 11:39

Хорошо, если я установлю let itemSet = CSSearchableItemAttributeSet(contentType: .text) и добавлю itemSet.textContent = "10 minute timer", я увижу, что он появится как документ. Но я хочу, чтобы оно отображалось как приложение, чтобы я мог открыть глубокую ссылку на результат таймера.

Paul Solt 11.07.2024 17:43
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
55
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я понял, как заставить это работать, установив CSSearchableItemAttributeSet(contentType:) на что-то другое. Кажется, оба .application и .text работают. Спасибо @ATV

import Cocoa
import CoreSpotlight

@main
class AppDelegate: NSObject, NSApplicationDelegate {
    var searchableItems: [String : CSSearchableItem] = [:]
    
    func addSearchTerm(identifier: String, title: String, duration: Int, keywords: [String]) {
        let itemSet = CSSearchableItemAttributeSet(contentType: .application) // or use .text
        itemSet.title = title
        itemSet.contentDescription = title
        itemSet.keywords = keywords
        itemSet.identifier = identifier
        //        itemSet.textContent = title
        itemSet.duration = NSNumber(integerLiteral: duration)
        
        let searchableItem = CSSearchableItem(uniqueIdentifier:identifier, domainIdentifier: "timers", attributeSet: itemSet)
        searchableItems[identifier] = searchableItem
    }
    
    func addSearchableTerms() {
        addSearchTerm(identifier: "com.paulsolt.SpotlightTimer.10min", title: "10 minute timer", duration: 10 * 60, keywords: ["min"])
        addSearchTerm(identifier: "com.paulsolt.SpotlightTimer.3min", title: "3 minute timer", duration: 3 * 60, keywords: ["min"])
        addSearchTerm(identifier: "com.paulsolt.SpotlightTimer.4min", title: "4 minute timer", duration: 4 * 60, keywords: ["min"])
        // TODO: Add more timers programmatically
        
        CSSearchableIndex.default().indexSearchableItems(Array(searchableItems.values)) { (error) in
            if let error = error {
                // handle failure
                print(error)
            } else {
                print("Indexed: \(self.searchableItems)")
            }
        }
    }
    
    func applicationDidFinishLaunching(_ aNotification: Notification) {
        addSearchableTerms()
    }
    
    func application(_ application: NSApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([any NSUserActivityRestoring]) -> Void) -> Bool {
        if userActivity.activityType == CSSearchableItemActionType,
           let identifier = userActivity.userInfo?[CSSearchableItemActivityIdentifier] as? String {
            handleSearchableItem(withIdentifier: identifier)
            return true
        }
        return false
    }
    
    func handleSearchableItem(withIdentifier identifier: String) {
        if let item = searchableItems[identifier],
           let duration = item.attributeSet.duration?.intValue {
            self.startTimer(duration: duration)
        } else {
            print("Duration not found in attributes")
        }
    }
    
    func startTimer(duration: Int) {
        // Your code to start the timer with the specified duration
        print("Starting timer for \(duration) seconds")
    }
}

Элемент будет ниже в списке в разделе «Другое» или «Документы», и только при взаимодействии он будет продвигаться по службе.

Мне интересно, имеет ли смысл вместо этого использовать NSUserActivity, но мне не удалось заставить это работать.

Хотя это работает, мне не нравится такое поведение. Было бы неплохо получить что-то вроде того, как Apple предоставляет результаты калькулятора, чтобы их можно было отображать как лучший результат. Я не знаю, возможно ли это. Я думаю, что глобальное сочетание клавиш может быть лучше, чем поиск Spotlight.

Paul Solt 11.07.2024 20:30

Другие вопросы по теме