Finder, QuickLook, Spotlight und UTI Durcheinander

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Finder, QuickLook, Spotlight und UTI Durcheinander

    Hallo zusammen,

    ich bastele immer noch an meinem SIDPlay Projekt (GitHub) und habe mal ein paar Fragen zum Thema UTI. Meine SIDPlay App beinhaltet neben der App auch einen QLPreview und einen Spotlight Importer.
    Solange SIDPlay das einzige Programm ist, was .sid Dateien registriert, läuft auch alles, ich kann über Spotlight nach Titeln, Autoren, usw. suchen, und im Finder mittels der Leertaste Quicklook aufrufen. Aber wenn eine andere App installiert wird, die auch .sid Dateien unterstützt, geht da gar nichts mehr. Neue .sid werden nicht mehr indiziert, Quicklook geht nicht mehr und das Icon der .sid Dateien ändert sich.
    Aber warum?
    Ich deklariere in der info.plist die Dokumente wie folgt:

    XML-Quellcode

    1. <key>CFBundleDocumentTypes</key>
    2. <array>
    3. <dict>
    4. <key>CFBundleTypeExtensions</key>
    5. <array>
    6. <string>sid</string>
    7. </array>
    8. <key>CFBundleTypeIconFile</key>
    9. <string>psid.icns</string>
    10. <key>CFBundleTypeMIMETypes</key>
    11. <array>
    12. <string>audio/prs.sid</string>
    13. </array>
    14. <key>CFBundleTypeName</key>
    15. <string>PSID music file</string>
    16. <key>CFBundleTypeOSTypes</key>
    17. <array>
    18. <string>PSID</string>
    19. </array>
    20. <key>CFBundleTypeRole</key>
    21. <string>Viewer</string>
    22. <key>LSHandlerRank</key>
    23. <string>Default</string>
    24. <key>LSItemContentTypes</key>
    25. <array>
    26. <string>org.sidmusic.sidtune</string>
    27. </array>
    28. <key>LSTypeIsPackage</key>
    29. <false/>
    30. <key>NSPersistentStoreTypeKey</key>
    31. <string>Binary</string>
    32. </dict>
    33. <dict>
    34. <key>CFBundleTypeExtensions</key>
    35. <array>
    36. <string>prg</string>
    37. </array>
    38. <key>CFBundleTypeName</key>
    39. <string>PRG file</string>
    40. <key>CFBundleTypeRole</key>
    41. <string>Viewer</string>
    42. <key>LSHandlerRank</key>
    43. <string>Alternate</string>
    44. <key>LSTypeIsPackage</key>
    45. <false/>
    46. <key>NSPersistentStoreTypeKey</key>
    47. <string>Binary</string>
    48. </dict>
    49. </array>
    50. <key>UTExportedTypeDeclarations</key>
    51. <array>
    52. <dict>
    53. <key>UTTypeConformsTo</key>
    54. <array>
    55. <string>public.data</string>
    56. <string>public.audio</string>
    57. <string>public.audiovisual-content</string>
    58. <string>public.content</string>
    59. <string>public.message</string>
    60. </array>
    61. <key>UTTypeDescription</key>
    62. <string>SID tune</string>
    63. <key>UTTypeIdentifier</key>
    64. <string>org.sidmusic.sidtune</string>
    65. <key>UTTypeReferenceURL</key>
    66. <string>http://www.sidmusic.org/sidplay/mac/</string>
    67. <key>UTTypeTagSpecification</key>
    68. <dict>
    69. <key>com.apple.ostype</key>
    70. <string>PSID</string>
    71. <key>public.filename-extension</key>
    72. <array>
    73. <string>sid</string>
    74. </array>
    75. <key>public.mime-type</key>
    76. <string>audio/prs.sid</string>
    77. </dict>
    78. </dict>
    79. </array>
    Alles anzeigen

    Die andere App definiert Document Type und UTI so:

    XML-Quellcode

    1. <dict>
    2. <key>CFBundleTypeExtensions</key>
    3. <array>
    4. <string>sid</string>
    5. </array>
    6. <key>CFBundleTypeIconSystemGenerated</key>
    7. <integer>1</integer>
    8. <key>CFBundleTypeName</key>
    9. <string>Commodore 64 SID</string>
    10. <key>CFBundleTypeRole</key>
    11. <string>Editor</string>
    12. <key>LSHandlerRank</key>
    13. <string>Alternate</string>
    14. <key>LSItemContentTypes</key>
    15. <array>
    16. <string>pl.rabidus.RetroDebugger.SID</string>
    17. </array>
    18. </dict>
    19. <dict>
    20. <key>UTTypeConformsTo</key>
    21. <array>
    22. <string>public.data</string>
    23. </array>
    24. <key>UTTypeDescription</key>
    25. <string>Commodore 64 SID</string>
    26. <key>UTTypeIcons</key>
    27. <dict>
    28. <key>UTTypeIconText</key>
    29. <string>SID</string>
    30. </dict>
    31. <key>UTTypeIdentifier</key>
    32. <string>pl.rabidus.RetroDebugger.SID</string>
    33. <key>UTTypeReferenceURL</key>
    34. <string>https://github.com/slajerek/RetroDebugger</string>
    35. <key>UTTypeTagSpecification</key>
    36. <dict>
    37. <key>public.filename-extension</key>
    38. <array>
    39. <string>sid</string>
    40. </array>
    41. <key>public.mime-type</key>
    42. <array>
    43. <string>application/octet-stream</string>
    44. </array>
    45. </dict>
    46. </dict>
    Alles anzeigen

    Wonach sortiert dann der Finder?
    Was ist ausschlaggebend, dass die eine Zuordnung durch eine andere überschrieben wird, sprich welche App bei den Zuordnungen Priorität bekommt?
    --
    Wer ist dieser Root und warum gehören ihm alle meine Dateien??

    SIDplay5 for macOS on GitHub
  • Alexco schrieb:

    Aber wenn eine andere App installiert wird, die auch .sid Dateien unterstützt, geht da gar nichts mehr.
    Willkommen zu einer Problematik, die mich mittlerweile seit 15 Jahren auf macOS und iOS begleitet!

    Zunächst ein kurzer Disclaimer: Mein Kenntnisstand basiert auf Feedbacks zu Bugreports, TSI-Tickets, Internet-Recherche und eigenen Erfahrungen (aka "Try & Error"): Ich bin für jede Ergänzung oder Korrektur dankbar, da ich auch fortwährend mit diesem Thema kämpfe.

    Apple hat mit dem Konstrukt der hierarchischen UTIs - basierend auf Dateimerkmalen wie Namenserweiterung, MIME-Type etc. - ein akademisch interessantes, aber leider theoretisches Konzept entwickelt, das in der Realität an zwei Punkten krankt:
    1. Dateien mit unterschiedlichen Formaten teilen sich die gleichen Namenserweiterungen, werden aber dem gleichen UTI zugeordnet. Dies war noch besser, als die Launch Services den File Creator Code berücksichtigten (der zusammen mit dem Datei-Typ in den HFS-Attributen stand). Mit Zuge der Annäherung an andere Betriebssysteme (die Dateitypen rein auf Basis der Namenserweiterung identifizieren) ging dieser Vorteil aber verloren. In diesem Fall schlagen Thumbnails / Previews, Meta-Daten und auch ein Öffnen mit der App regelmäßig fehl, wenn Dateien ohne Content-Type vorliegen (z. B. von anderen OS).
    2. Mangels einer zentralen Registrierungsstelle vergeben App-Entwickler auch bei gleichem Dateiformat unterschiedliche UTIs. Das ist eigentlich vollkommener Humbug: Die UTI definiert ja nicht die App, sondern das Format. Eigentlich sollte der Urheber eines Dateiformates einen eineindeutigen UTI unter Nutzung einer "reverse domain name conversion" benennen und alle dieses Format lesende Apps nutzen diesen. In Realität fühlt sich jeder Entwickler berufen, in seiner App einen eigenen UIT zu definieren und vergrößert damit das Chaos.
    Zu Deiner konkreten Situation:

    Ich verstehe Dich so, dass bei Dir der zweite Fall vorliegt: Die beiden Apps verarbeiten das gleiche Dateiformat, richtig? Dann kannst Du in Deinen Plugins einfach den "fremden" UTI importieren, so dass sich QL-Generator und MD-Importer zuständig fühlen - bis der nächste Entwickler einen neuen UTI für .sid einführt, dann musst Du wieder nachziehen etc. pp. Das funktioniert, solange die anderen Apps nicht selber Quick Look Plugins ausliefern (oder Du mit system-seitig definierten UTIs kollidierst): Quick Look erlaubt keine Priorisierung der gefundenen Plugins und es ist willkürlich, welches zur Anzeige herangezogen wird. Mein entsprechender Bug-Report ist seit >10 Jahren offen und wird es wohl auch bleiben.

    Bzgl. der standardmäßig öffnenden App scheint für die Launch Services die Installationsreihenfolge ausschlaggebend zu sein, solange eine Datei noch keinen Content-Type hat (vgl. kMDItemContentType von mdls). Ansonsten zieht der UTI des Content-Types, kann aber vom Benutzer per "Open with..." - "Always open with..." überstimmt werden. Als Entwickler hat Du darauf keinen Einfluss.

    Puh, ich komme vom Hölzchen auf's Stöckchen - und höre mal besser auf. Bei Fragen fragen ... Du merkst, das Thema treibt mich um. Und an alle: Wie oben geschrieben gerne korrigieren / ergänzen: Ich bin über jeden Wissensgewinn dankbar!

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von MyMattes ()

  • Hallo Mattes,

    herzlichen Dank für die Antwort, auch wenn sie etwas ernüchternt ist.

    MyMattes schrieb:

    Ich verstehe Dich so, dass bei Dir der zweite Fall vorliegt: Die beiden Apps verarbeiten das gleiche Dateiformat, richtig? Dann kannst Du in Deinen Plugins einfach den "fremden" UTI importieren, so dass sich QL-Generator und MD-Importer zuständig fühlen - bis der nächste Entwickler einen neuen UTI für .sid einführt, dann musst Du wieder nachziehen etc. pp. Das funktioniert, solange die anderen Apps nicht selber Quick Look Plugins ausliefern (oder Du mit system-seitig definierten UTIs kollidierst): Quick Look erlaubt keine Priorisierung der gefundenen Plugins und es ist willkürlich, welches zur Anzeige herangezogen wird. Mein entsprechender Bug-Report ist seit >10 Jahren offen und wird es wohl auch bleiben.
    Ja, richtig. Beide Apps können .sid Dateien laden und abspielen. UTI Importieren heißt dann, in der info.plist über UTImportedTypeDeclarations, richtig?
    Muss ich dann genau die Definition nehmen (conforms to, usw.), wie in der anderen App? Oder reicht es erst mal, eine einfache Definition dort zu hinterlegen?

    Was mich hier nahezu wahnsinnig macht, ist die Willkürlichkeit, mit der das stattfindet:
    • Ich installiere meine App (SIDPlay), nutze diese ganz normal. Die Suche in der "SID Mediathek" hängt dabei von dem Spotlight Plugin ab, sprich ich nutze die Attribute ausgiebig

    • Dann installiere ich eine andere App, die rein zufällig auch .sid Dateien nutzen kann, und meine App geht gar nicht mehr
      • Im Finder wird einfach so die Standard-App von meiner umgebogen. Warum zum Teufel?
      • Damit funktioniert mein Quicklook Plugin auch nicht mehr, denn das hängt im App Bundle
      • Und neue .sid Dateien werde nicht mehr von meinem Spotlight Plugin indiziert (da geänderte UTI) und tauchen somit auch nicht in der Suche auf
    Wie soll ich denn sowas nachvollziehen und abfangen oder gar einem Nutzer erklären?
    --
    Wer ist dieser Root und warum gehören ihm alle meine Dateien??

    SIDplay5 for macOS on GitHub
  • Alexco schrieb:

    UTI Importieren heißt dann, in der info.plist über UTImportedTypeDeclarations, richtig?
    Muss ich dann genau die Definition nehmen (conforms to, usw.), wie in der anderen App? Oder reicht es erst mal, eine einfache Definition dort zu hinterlegen?
    Hier der aktuelle Stand in meiner App - nach dem historischen Post habe ich dann doch UTIs importiert, um unabhängig von einer Installation der Fremd-App deren Dateien öffnen zu können:

    In der App's info.plist hier ein Beispiel mit der Erweiterung .jef: Ich definiere die App im CFBundleDocumentTypes für einen Content-Type als Editor / Owner, für drei andere (fremde) als Viewer / Default. Analog gibt es eine exportierte und drei importierte UTIs, die ich vollständig definiere - keine Ahnung, ob weniger reichen würde:

    XML-Quellcode: App info.plist

    1. <key>CFBundleDocumentTypes</key>
    2. <array>
    3. <dict>
    4. <key>CFBundleTypeIconFile</key>
    5. <string>DocIcon</string>
    6. <key>CFBundleTypeName</key>
    7. <string>JEFFile</string>
    8. <key>CFBundleTypeRole</key>
    9. <string>Editor</string>
    10. <key>LSHandlerRank</key>
    11. <string>Owner</string>
    12. <key>LSItemContentTypes</key>
    13. <array>
    14. <string>com.janome.jef</string>
    15. </array>
    16. <key>LSTypeIsPackage</key>
    17. <integer>0</integer>
    18. <key>NSDocumentClass</key>
    19. <string>STBDocument</string>
    20. </dict>
    21. <dict>
    22. <key>CFBundleTypeIconFile</key>
    23. <string>DocIcon</string>
    24. <key>CFBundleTypeName</key>
    25. <string>JEFFile</string>
    26. <key>CFBundleTypeRole</key>
    27. <string>Viewer</string>
    28. <key>LSHandlerRank</key>
    29. <string>Default</string>
    30. <key>LSItemContentTypes</key>
    31. <array>
    32. <string>com.britonleap.jef</string>
    33. <string>net.vsmsoftware.true.jef</string>
    34. <string>com.drawstitch.stitchfile.jef</string>
    35. </array>
    36. <key>LSTypeIsPackage</key>
    37. <integer>0</integer>
    38. <key>NSDocumentClass</key>
    39. <string>STBDocument</string>
    40. </dict>
    41. </array>
    42. <key>UTExportedTypeDeclarations</key>
    43. <array>
    44. <dict>
    45. <key>UTTypeConformsTo</key>
    46. <array>
    47. <string>public.data</string>
    48. </array>
    49. <key>UTTypeDescription</key>
    50. <string>Janome JEF File</string>
    51. <key>UTTypeIconName</key>
    52. <string>DocJEF.icns</string>
    53. <key>UTTypeIdentifier</key>
    54. <string>com.janome.jef</string>
    55. <key>UTTypeReferenceURL</key>
    56. <string>http://www.janome.com/</string>
    57. <key>UTTypeTagSpecification</key>
    58. <dict>
    59. <key>public.filename-extension</key>
    60. <array>
    61. <string>jef</string>
    62. </array>
    63. </dict>
    64. </dict>
    65. </array>
    66. <key>UTImportedTypeDeclarations</key>
    67. <array>
    68. <dict>
    69. <key>UTTypeConformsTo</key>
    70. <array>
    71. <string>public.data</string>
    72. </array>
    73. <key>UTTypeDescription</key>
    74. <string>Janome JEF File</string>
    75. <key>UTTypeIconName</key>
    76. <string>generic</string>
    77. <key>UTTypeIdentifier</key>
    78. <string>com.britonleap.jef</string>
    79. <key>UTTypeReferenceURL</key>
    80. <string>http://www.janome.com/</string>
    81. <key>UTTypeTagSpecification</key>
    82. <dict>
    83. <key>public.filename-extension</key>
    84. <array>
    85. <string>jef</string>
    86. </array>
    87. </dict>
    88. </dict>
    89. <dict>
    90. <key>UTTypeConformsTo</key>
    91. <array>
    92. <string>public.data</string>
    93. </array>
    94. <key>UTTypeDescription</key>
    95. <string>Janome JEF File</string>
    96. <key>UTTypeIconName</key>
    97. <string>generic</string>
    98. <key>UTTypeIdentifier</key>
    99. <string>net.vsmsoftware.true.jef</string>
    100. <key>UTTypeReferenceURL</key>
    101. <string>http://www.janome.com/</string>
    102. <key>UTTypeTagSpecification</key>
    103. <dict>
    104. <key>public.filename-extension</key>
    105. <array>
    106. <string>jef</string>
    107. </array>
    108. </dict>
    109. </dict>
    110. <dict>
    111. <key>UTTypeConformsTo</key>
    112. <array>
    113. <string>public.data</string>
    114. </array>
    115. <key>UTTypeDescription</key>
    116. <string>DrawStitch JEF File</string>
    117. <key>UTTypeIconName</key>
    118. <string>generic</string>
    119. <key>UTTypeIdentifier</key>
    120. <string>com.drawstitch.stitchfile.jef</string>
    121. <key>UTTypeReferenceURL</key>
    122. <string>http://www.drawstitch.com/</string>
    123. <key>UTTypeTagSpecification</key>
    124. <dict>
    125. <key>public.filename-extension</key>
    126. <array>
    127. <string>jef</string>
    128. </array>
    129. </dict>
    130. </dict>
    131. </array>
    Alles anzeigen
    Bei den Plugins ist es etwas übersichtlicher: Hier gibt es nur eine Rolle für alle UITs, "QLGenerator" bzw. "MDImporter", der alle Content-Types beinhaltet.

    XML-Quellcode: Plugin info.plist

    1. <key>CFBundleDocumentTypes</key>
    2. <array>
    3. <dict>
    4. <key>CFBundleTypeRole</key>
    5. <string>QLGenerator</string>
    6. <key>LSItemContentTypes</key>
    7. <array>
    8. <string>com.janome.jef</string>
    9. <string>com.britonleap.jef</string>
    10. <string>net.vsmsoftware.true.jef</string>
    11. <string>com.drawstitch.stitchfile.jef</string>
    12. </array>
    13. </dict>
    14. </array>
    15. <key>UTImportedTypeDeclarations</key>
    16. <array>
    17. <dict>
    18. <key>UTTypeConformsTo</key>
    19. <array>
    20. <string>public.data</string>
    21. </array>
    22. <key>UTTypeDescription</key>
    23. <string>Janome JEF File</string>
    24. <key>UTTypeIconName</key>
    25. <string>generic</string>
    26. <key>UTTypeIdentifier</key>
    27. <string>com.janome.jef</string>
    28. <key>UTTypeReferenceURL</key>
    29. <string>http://www.janome.com/</string>
    30. <key>UTTypeTagSpecification</key>
    31. <dict>
    32. <key>public.filename-extension</key>
    33. <array>
    34. <string>jef</string>
    35. </array>
    36. </dict>
    37. </dict>
    38. </array>
    Alles anzeigen
    Korrektur: Übrigens bemerke ich gerade, dass ich bei den Plugins nur meine eigenen UTIs importiere - insofern ist meine obige Aussage nicht korrekt: Nicht die UTIs müssen alle importiert, sondern die entsprechenden Content-Types als LSItemContentTypes aufgeführt werden. Sorry für den Schnitzer...

    Einfach ist anders, Mattes

    Edit: Die App hat übrigens 11 exportierte und 29 importierte UTIs bei 20 Dokument-Typen ... und ich habe sicher nicht alle Apps auf dem Schirm, die "meine" Dateiformate schreiben... 8|
    Diese Seite bleibt aus technischen Gründen unbedruckt.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von MyMattes ()

  • Hallo Mattes,

    danke für die vielen Tipps und sorry für die späte Antwort.
    Bei Deinem Plugin importierst Du Deine eigene UTI, ich habe da momentan noch Export stehen. Warum also ein Import?

    Und ich hatte irgendwo mal gelesen, dass die info.plist von Plugins in einer App nicht zuverlässig vom Launcher gelesen werden, weshalb man besser alles bei der App definiert.
    Hast Du da Erfahrungen diesbezüglich?

    Grüße,
    Alexander
    --
    Wer ist dieser Root und warum gehören ihm alle meine Dateien??

    SIDplay5 for macOS on GitHub
  • Alles gut, kein Stress :)

    Alexco schrieb:

    Bei Deinem Plugin importierst Du Deine eigene UTI, ich habe da momentan noch Export stehen. Warum also ein Import?
    Meine Logik war, dass die Plugins ja "nur" UTIs konsumieren, die von einem anderen Bundle definiert / exportiert werden: Der Haupt-App. Ganz ehrlich glaube ich aber nicht, dass es in diesem Kontext von Apps mit enthaltenen Plugin irgendeinen Unterschied macht.

    Hier der entsprechende Kommentar von Apple

    Apple schrieb:

    An imported UTI declaration is used to declare a type that the bundle does not own, but would like to see available on the system. For example, say a video-editing program creates files using a proprietary format whose UTI is declared in its application bundle. If you are writing an application or plugin that can read such files, you must make sure that the system knows about the proprietary UTI, even if the actual video-editing application is not available. To do so, your application should redeclare the UTI in its own bundle but mark it as an imported declaration
    Ich würde die info.plists immer vollständig definieren - was wolltest Du denn nur in der App machen? Mein Konstrukt läuft nun seit Jahren problemlos (bzw. nur mit den genannten Problemen bzgl. Kollisionen mit anderen Apps bzw. System-UTIs), basiert aber auch viel auf Try & Error: Offizielle Dokumentationen, aber auch Google fand ich nur bedingt hilfreich...

    Mattes
    Diese Seite bleibt aus technischen Gründen unbedruckt.
  • MyMattes schrieb:

    Ich würde die info.plists immer vollständig definieren - was wolltest Du denn nur in der App machen?
    Ic.h wollte da nur das Nötigste definieren, also Endung, UTI und "conforms to". Keine vollständige Definition mit Icon usw.
    Habe das jetzt mal testweise so gemacht und bisher sehe da auch noch keine Probleme.
    --
    Wer ist dieser Root und warum gehören ihm alle meine Dateien??

    SIDplay5 for macOS on GitHub