Làm cách nào để liên kết các loại tệp với ứng dụng iPhone?


318

Về chủ đề liên kết ứng dụng iPhone của bạn với các loại tệp.

Trong câu hỏi thông tin này, tôi đã học được rằng các ứng dụng có thể được liên kết với các giao thức URL tùy chỉnh.

Đó là gần một năm trước và kể từ đó Apple đã giới thiệu 'Hỗ trợ tài liệu' tiến thêm một bước và cho phép các ứng dụng liên kết với các loại tệp. Có rất nhiều thảo luận trong tài liệu về cách thiết lập ứng dụng của bạn để khởi chạy các ứng dụng phù hợp khác khi nó gặp một loại tệp không xác định. Điều này có nghĩa là hiệp hội không hoạt động tốt cho bất kỳ ứng dụng nào, như giao thức URL đã đăng ký.

Điều này dẫn tôi đến câu hỏi: các ứng dụng hệ thống như Safari hoặc Mail đã triển khai hệ thống này để chọn các ứng dụng liên quan hay chúng sẽ không làm gì, như trước đây?

Câu trả lời:


408

Xử lý loại tệp là mới với iPhone OS 3.2 và khác với các lược đồ URL tùy chỉnh đã tồn tại. Bạn có thể đăng ký ứng dụng của mình để xử lý các loại tài liệu cụ thể và bất kỳ ứng dụng nào sử dụng bộ điều khiển tài liệu đều có thể xử lý các tài liệu này cho ứng dụng của riêng bạn.

Ví dụ: Phân tử ứng dụng của tôi (có mã nguồn khả dụng) xử lý các loại tệp .pdb và .pdb.gz, nếu nhận được qua email hoặc trong một ứng dụng được hỗ trợ khác.

Để đăng ký hỗ trợ, bạn sẽ cần phải có một cái gì đó như sau trong Info.plist của bạn:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array>
            <string>Document-molecules-320.png</string>
            <string>Document-molecules-64.png</string>
        </array>
        <key>CFBundleTypeName</key>
        <string>Molecules Structure File</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.sunsetlakesoftware.molecules.pdb</string>
            <string>org.gnu.gnu-zip-archive</string>
        </array>
    </dict>
</array>

Hai hình ảnh được cung cấp sẽ được sử dụng làm biểu tượng cho các loại được hỗ trợ trong Mail và các ứng dụng khác có khả năng hiển thị tài liệu. Các LSItemContentTypeschìa khóa cho phép bạn cung cấp một loạt các loại định danh Uniform (UTIs) mà ứng dụng của bạn có thể mở. Để biết danh sách các UTI do hệ thống xác định, hãy xem Tham khảo số nhận dạng loại thống nhất của Apple . Thậm chí nhiều chi tiết hơn về UTI có thể được tìm thấy trong Tổng quan về Số nhận dạng loại thống nhất của Apple . Những hướng dẫn này nằm trong trung tâm dành cho nhà phát triển Mac, vì khả năng này đã được chuyển qua Mac.

Một trong những UTI được sử dụng trong ví dụ trên là do hệ thống xác định, nhưng cái còn lại là UTI dành riêng cho ứng dụng. UTI dành riêng cho ứng dụng sẽ cần phải được xuất để các ứng dụng khác trên hệ thống có thể được biết về nó. Để làm điều này, bạn sẽ thêm một phần vào Info.plist của bạn như sau:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.plain-text</string>
            <string>public.text</string>
        </array>
        <key>UTTypeDescription</key>
        <string>Molecules Structure File</string>
        <key>UTTypeIdentifier</key>
        <string>com.sunsetlakesoftware.molecules.pdb</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pdb</string>
            <key>public.mime-type</key>
            <string>chemical/x-pdb</string>
        </dict>
    </dict>
</array>

Ví dụ cụ thể này xuất com.sunsetlakesoftware.molecules.pdbUTI với phần mở rộng tệp .pdb, tương ứng với loại MIME chemical/x-pdb.

Với vị trí này, ứng dụng của bạn sẽ có thể xử lý các tài liệu được đính kèm vào email hoặc từ các ứng dụng khác trên hệ thống. Trong Mail, bạn có thể chạm và giữ để hiển thị danh sách các ứng dụng có thể mở tệp đính kèm cụ thể.

Khi tệp đính kèm được mở, ứng dụng của bạn sẽ được khởi động và bạn sẽ cần xử lý việc xử lý tệp này trong -application:didFinishLaunchingWithOptions:phương thức ủy nhiệm ứng dụng của bạn . Dường như các tệp được tải theo cách này từ Thư được sao chép vào thư mục Tài liệu của ứng dụng của bạn trong thư mục con tương ứng với hộp thư điện tử mà chúng gửi đến. Bạn có thể lấy URL cho tệp này trong phương thức ủy nhiệm của ứng dụng bằng mã như sau:

NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];

Lưu ý rằng đây là cách tiếp cận tương tự mà chúng tôi đã sử dụng để xử lý các lược đồ URL tùy chỉnh. Bạn có thể tách URL tệp khỏi những người khác bằng cách sử dụng mã như sau:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}

9
Cần lưu ý rằng -application:didFinishLaunchingWithOptions:trong ứng dụng, đại biểu chỉ được gọi nếu ứng dụng của bạn không được chạy nền khi ứng dụng được mở để xử lý tệp.
memmons


4
Chúng ta cũng nên sử dụng - (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)urltrên iOS 4+
Dmitry

1
Còn khóa 'CFBundleTypeExtensions' thì sao? Đoạn mã của bạn dường như không đặt nó. Có cần thiết không?
Bram

3
Tôi cũng đã thử tất cả các phương pháp được cung cấp ở đây và các nơi khác, nhưng tôi vẫn đang cố gắng để có được các tệp PNG mở. Tôi đang làm việc với iOS 7. Ở một số nơi họ nói rằng vấn đề này bắt đầu với ios 6. Có đúng không? Chúng tôi không thể mở tệp png trong hộp thoại "Mở trong" bằng ios 7?
Kumar Aditya

24

Ngoài câu trả lời tuyệt vời của Brad, tôi đã phát hiện ra rằng (ít nhất là trên iOS 4.2.1) khi mở tệp tùy chỉnh từ ứng dụng Thư, ứng dụng của bạn sẽ không bị hủy hoặc thông báo nếu tệp đính kèm đã được mở trước đó. Cửa sổ bật lên "mở bằng" xuất hiện, nhưng không làm gì cả.

Điều này dường như được khắc phục bằng cách (di chuyển) tệp từ thư mục Hộp thư đến. Một cách tiếp cận an toàn dường như là cả hai (tái) di chuyển tệp khi nó được mở (in -(BOOL)application:openURL:sourceApplication:annotation:) cũng như đi qua thư mục Documents / Hộp thư đến, xóa tất cả các mục, ví dụ như trong applicationDidBecomeActive:. Đó có thể là tất cả cần thiết để có được ứng dụng ở trạng thái sạch một lần nữa, trong trường hợp lần nhập trước đó gây ra sự cố hoặc bị gián đoạn.


6
Tôi không thấy hành vi này. Nếu ứng dụng của tôi được chạy nền, -(BOOL)application:openURL:sourceApplication:annotation:luôn được gọi, ngay cả đối với các tệp đính kèm đã được mở. Mỗi lần thêm tệp đính kèm được mở, một số được thêm vào tên tệp và được tăng lên thành duy nhất - test.text, test-1.txt, test-2.txt, v.v.
memmons

Thư mục Hộp thư đến của tôi trống, nhưng tôi có nút "Mở trong" không phản hồi trong Safari mà bạn nói đến. Nhiều năm trước, ứng dụng của tôi đã hoạt động tốt, nhưng đột nhiên nó ngừng hoạt động. Tôi nghi ngờ Apple đã thay đổi một cái gì đó trong Safari.
Bram

18

CẢNH BÁO LỚN: Thực hiện MỘT PERCENT HÀNG NGÀY chắc chắn rằng tiện ích mở rộng của bạn chưa được gắn với một số loại mime.

Về cơ bản, chúng tôi đã sử dụng tiện ích mở rộng '.icz' cho các tệp tùy chỉnh của mình và Safari sẽ không bao giờ cho phép bạn mở chúng nói rằng "Safari không thể mở tệp này." không có vấn đề gì chúng tôi đã làm hoặc đã thử với các công cụ UT ở trên.

Cuối cùng, tôi nhận ra rằng có một số hàm UT * C bạn có thể sử dụng để khám phá nhiều thứ khác nhau và trong khi .icz đưa ra câu trả lời đúng (ứng dụng của chúng tôi):

Trong ứng dụng đã tải ở đầu, chỉ cần làm điều này ...

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, 
                                                                   (CFStringRef)@"icz", 
                                                                   NULL);
CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

và đặt dấu ngắt sau dòng đó và xem UTI và ur là gì - trong trường hợp của chúng tôi, đó là định danh của chúng tôi như chúng tôi muốn) và url url (ur) đang chỉ vào thư mục ứng dụng của chúng tôi.

Nhưng loại MIME mà Dropbox cung cấp cho chúng tôi liên kết của chúng tôi, bạn có thể kiểm tra bằng cách thực hiện, ví dụ:

$ curl -D headers THEURLGOESHERE > /dev/null
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 27393  100 27393    0     0  24983      0  0:00:01  0:00:01 --:--:-- 28926
$ cat headers
HTTP/1.1 200 OK
accept-ranges: bytes
cache-control: max-age=0
content-disposition: attachment; filename="123.icz"
Content-Type: text/calendar
Date: Fri, 24 May 2013 17:41:28 GMT
etag: 872926d
pragma: public
Server: nginx
x-dropbox-request-id: 13bd327248d90fde
X-RequestId: bf9adc56934eff0bfb68a01d526eba1f
x-server-response-time: 379
Content-Length: 27393
Connection: keep-alive

Kiểu nội dung là những gì chúng ta muốn. Dropbox tuyên bố đây là một mục nhập văn bản / lịch. Tuyệt quá. Nhưng trong trường hợp của tôi, tôi ĐÃ TRỞ THÀNH văn bản / lịch vào các loại mime của ứng dụng và nó vẫn không hoạt động. Thay vào đó, khi tôi cố gắng lấy UTI và gói url cho mô hình văn bản / lịch,

NSString * UTI = (NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
                                                                   (CFStringRef)@"text/calendar", 
                                                                   NULL);

CFURLRef ur =UTTypeCopyDeclaringBundleURL(UTI);

Tôi thấy "com.apple.ical.ics" là UTI và "... / MobileCoreTypes.bundle /" là URL gói. Không phải ứng dụng của chúng tôi, mà là Apple. Vì vậy, tôi thử đưa com.apple.ical.ics vào LSItemContentTypes cùng với chính tôi và vào UTConformsTo trong xuất, nhưng không được.

Vì vậy, về cơ bản, nếu Apple nghĩ rằng tại một thời điểm nào đó, Apple muốn xử lý một số loại tệp (có thể được tạo 10 năm sau khi ứng dụng của bạn hoạt động, hãy nhớ bạn), bạn sẽ phải thay đổi tiện ích mở rộng vì họ sẽ không cho phép bạn xử lý loại tập tin.


Cảm ơn cảnh báo hữu ích!
RockSolid

0

Để xử lý bất kỳ loại tệp nào cho APP của riêng tôi, tôi sử dụng cấu hình này cho CFBundleDocumentTypes:

    <key>CFBundleDocumentTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeName</key>
            <string>IPA</string>
            <key>LSItemContentTypes</key>
            <array>
                <string>public.item</string>
                <string>public.content</string>
                <string>public.data</string>
                <string>public.database</string>
                <string>public.composite-content</string>
                <string>public.contact</string>
                <string>public.archive</string>
                <string>public.url-name</string>
                <string>public.text</string>
                <string>public.plain-text</string>
                <string>public.source-code</string>
                <string>public.executable</string>
                <string>public.script</string>
                <string>public.shell-script</string>
                <string>public.xml</string>
                <string>public.symlink</string>
                <string>org.gnu.gnu-zip-archve</string>
                <string>org.gnu.gnu-tar-archive</string>
                <string>public.image</string>
                <string>public.movie</string>
                <string>public.audiovisual-​content</string>
                <string>public.audio</string>
                <string>public.directory</string>
                <string>public.folder</string>
                <string>com.apple.bundle</string>
                <string>com.apple.package</string>
                <string>com.apple.plugin</string>
                <string>com.apple.application-​bundle</string>
                <string>com.pkware.zip-archive</string>
                <string>public.filename-extension</string>
                <string>public.mime-type</string>
                <string>com.apple.ostype</string>
                <string>com.apple.nspboard-typ</string>
                <string>com.adobe.pdf</string>
                <string>com.adobe.postscript</string>
                <string>com.adobe.encapsulated-​postscript</string>
                <string>com.adobe.photoshop-​image</string>
                <string>com.adobe.illustrator.ai-​image</string>
                <string>com.compuserve.gif</string>
                <string>com.microsoft.word.doc</string>
                <string>com.microsoft.excel.xls</string>
                <string>com.microsoft.powerpoint.​ppt</string>
                <string>com.microsoft.waveform-​audio</string>
                <string>com.microsoft.advanced-​systems-format</string>
                <string>com.microsoft.advanced-​stream-redirector</string>
                <string>com.microsoft.windows-​media-wmv</string>
                <string>com.microsoft.windows-​media-wmp</string>
                <string>com.microsoft.windows-​media-wma</string>
                <string>com.apple.keynote.key</string>
                <string>com.apple.keynote.kth</string>
                <string>com.truevision.tga-image</string>
            </array>
            <key>CFBundleTypeIconFiles</key>
            <array>
                <string>Icon-76@2x</string>
            </array>
        </dict>
    </array>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.