37
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Swiftでシステム内蔵辞書を検索する方法

Last updated at Posted at 2014-10-26

OS X 10.8 から,Mac には標準でウィズダム英和/和英辞典が内蔵されています。標準の 辞書.app や,command+control+D で検索できます。

Swift で書いている OS X 用アプリの中からウィズダム英和辞典で検索したいと思い,その方法を検討しました。

Dictionary Services を使えば,辞書の検索自体は可能です。
ただし,特定の辞書を指定して検索するのは,Objective-C でも Private API を使わなければできないようで,現在のところ直接的な方法は公式には用意されていないようです。

そこで,次のような方法を使うことにしました。

  1. 現在の検索辞書の設定を保存する。
  2. 検索辞書の設定を書き換え,ウィズダム英和辞典だけを検索辞書に指定する。
  3. DCSCopyTextDefinition を使って辞書を検索して意味を取得する。
  4. 検索辞書の設定を復元する。

このように,ユーザの検索辞書設定を一時的に変更して辞書検索を行い,すぐに元に戻すことで,特定の辞書を指定して検索を行うことが可能となります。

DictionaryServiceManager.swift
import Foundation

class DictionaryServiceManager {
    private let AppleGlobalDomainName = "Apple Global Domain"
    private let DictionaryServicesKey = "com.apple.DictionaryServices"
    private let ActiveDictionariesKey = "DCSActiveDictionaries"

    private var globalDomain: [String:Any]? { UserDefaults.standard.persistentDomain(forName: AppleGlobalDomainName) }
    private var dictionaryPreferences: [String:AnyObject]? { self.globalDomain?[DictionaryServicesKey] as! [String:AnyObject]? }
    private var currentDictionaryList: [String]? { self.dictionaryPreferences?[ActiveDictionariesKey] as! [String]? }

    private func setUserDictPreferences(_ activeDictionaries: [String]) {
        if var currentPref = self.dictionaryPreferences {
            currentPref[ActiveDictionariesKey] = activeDictionaries as AnyObject
            if var gDomain = self.globalDomain {
                gDomain[DictionaryServicesKey] = currentPref
                UserDefaults.standard.setPersistentDomain(gDomain, forName: AppleGlobalDomainName)
            }
        }
    }

    func lookUp(_ word: String, inDictionary dictionaryPath: String) -> String? {
        let currentPrefs = self.currentDictionaryList
        self.setUserDictPreferences([dictionaryPath])

        let range = CFRangeMake(0, word.utf16.count)
        let result = DCSCopyTextDefinition(nil, word as CFString, range)?.takeRetainedValue() as String?

        if let currentPrefs = currentPrefs {
            self.setUserDictPreferences(currentPrefs)
        }

        return result
    }
}

これを使えば,たとえば次のようにしてウィズダム英和辞典を検索できます。

DictionaryServiceManager-Test.swift
let wisdomPath: String
if #available(macOS 13, *) {
    wisdomPath = "/System/Library/AssetsV2/com_apple_MobileAsset_DictionaryServices_dictionaryOSX/c47eada3a1cc3269ef6d8120a6cc20c7dcf70355.asset/AssetData/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
} else if #available(macOS 12, *) {
    wisdomPath = "/System/Library/AssetsV2/com_apple_MobileAsset_DictionaryServices_dictionaryOSX/b3bf6ae48c39f29f7ca1b7410a60eece625c5fc3.asset/AssetData/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
} else if #available(macOS 11, *) {
    wisdomPath = "/System/Library/AssetsV2/com_apple_MobileAsset_DictionaryServices_dictionaryOSX/eda7c0d385d0ccb68e97b60251d63e9e2633b466.asset/AssetData/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
} else if #available(macOS 10.15, *) {
    wisdomPath = "/System/Library/AssetsV2/com_apple_MobileAsset_DictionaryServices_dictionaryOSX/7725cba5b321a8308a603a40ac808699175c4aae.asset/AssetData/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
} else if #available(macOS 10.14, *) {
    wisdomPath = "/System/Library/Assets/com_apple_MobileAsset_DictionaryServices_dictionaryOSX/c15aa908a684112f63017e47bb6b289e99977135.asset/AssetData/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
} else if #available(macOS 10.13, *) {
    wisdomPath = "/System/Library/Assets/com_apple_MobileAsset_DictionaryServices_dictionaryOSX/65c5f4f22827dba6b0a6bc85755863317890953b.asset/AssetData/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
} else {
    wisdomPath = "/Library/Dictionaries/Sanseido The WISDOM English-Japanese Japanese-English Dictionary.dictionary"
}

// "swift" の意味を取得
let word = "swift"
if let content = DictionaryServiceManager().lookUp(word, inDictionary: wisdomPath) {
    print(content)
} else {
    print("NOT FOUND")
}
37
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?