zoukankan      html  css  js  c++  java
  • QLPreviewController来预览文件

    Mac OS系统有一个很方便的功能就是文件预览,在Finder中选中一个文件,按下空格键就能够预览其中的内容。支持图片、文档、视频等类型。在iOS4.0系统中,官方SDK提供了一个QLPreviewController,使用它就可以让我们的App在iPhone/iPad中直接预览各个文件了。官方的开发文档中说明其支持的文件类型有:

    1. iWork文档
    2. 微软Office97以上版本的文档
    3. RTF文档
    4. PDF文件
    5. 图片文件
    6. 文本文件和CSV文件

    使用方法也很简单,在Frameworks中添加QuickLook.framework,直接alloc出一个QLPreviewController对象,用presentModalViewController方法把它调出来即可。要指定QLPreviewController预览那个文件,只要直接实现它的代理方法previewItemAtIndex,返回一个NSURL对象即可:

    - (id)previewController:(QLPreviewController *)previewController previewItemAtIndex:(NSInteger)idx
    {   
    return [NSURL fileURLWithPath:[NSString stringWithFormat:@“%@/Documents/files/%@”, NSHomeDirectory(), [fileList objectAtIndex:currentIndex]]];
    }


    官方程序如下

    1.

    DITableViewController.h

    #import <UIKit/UIKit.h>

    #import <QuickLook/QuickLook.h>

     #import "DirectoryWatcher.h"

     @interface DITableViewController : UITableViewController <QLPreviewControllerDataSource,

                                                              QLPreviewControllerDelegate,

                                                              DirectoryWatcherDelegate,

                                                              UIDocumentInteractionControllerDelegate> {

     

        DirectoryWatcher *docWatcher;

        NSMutableArray *documentURLs;

        UIDocumentInteractionController *docInteractionController;

    }

     @property (nonatomic, retain) DirectoryWatcher *docWatcher;

    @property (nonatomic, retain) NSMutableArray *documentURLs;

    @property (nonatomic, retain) UIDocumentInteractionController *docInteractionController;

    @end

    DITableViewController.m文件

    #import "DITableViewController.h"

    @interface DITableViewController (private)

    - (NSString *)applicationDocumentsDirectory;

    @end

     static NSString* documents[] =

        {   @"Text Document.txt",

            @"Image Document.jpg",

            @"PDF Document.pdf",

            @"HTML Document.html"

        };

    #define NUM_DOCS 4

    #define kRowHeight 58.0f

    @implementation DITableViewController

     @synthesize docWatcher, documentURLs, docInteractionController;

    #pragma mark -

    #pragma mark View Controller

     - (void)setupDocumentControllerWithURL:(NSURL *)url

    {

        if (self.docInteractionController == nil)

        {

            self.docInteractionController = [UIDocumentInteractionControllerinteractionControllerWithURL:url];

            self.docInteractionController.delegate = self;

        }

        else

        {

            self.docInteractionController.URL = url;

        }

    }

    - (void)viewDidLoad {

        [superviewDidLoad];

            // start monitoring the document directory…

        self.docWatcher = [DirectoryWatcherwatchFolderWithPath:[selfapplicationDocumentsDirectory] delegate:self];

        self.documentURLs = [NSMutableArrayarray];

        // scan for existing documents

        [selfdirectoryDidChange:self.docWatcher];

    }

     - (void)viewDidUnload {

        self.documentURLs = nil;

        self.docWatcher = nil;

    }

     - (void)dealloc {

        [documentURLsrelease];

        [docWatcherrelease];

        [super dealloc];

    }

     - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation

    {

        returnYES;

    }

     #pragma mark -

    #pragma mark UITableViewDataSource

     - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    {

        return 2;

    }

     - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {

        if (section == 0)

        {

            return NUM_DOCS;

        }

        else

        {

            return self.documentURLs.count;

        }

    }

     - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section

    {

        NSString *title = nil;

        if (section == 0)

            title = @"Example Documents";

        else

        {

            if (self.documentURLs.count > 0)

                title = @"Documents folder";

        }

        return title;

    }

    - (NSString *)formattedFileSize:(unsigned long long)size

    {

    NSString *formattedStr = nil;

        if (size == 0) 

    formattedStr = @"Empty";

    else 

    if (size > 0 && size < 1024) 

    formattedStr = [NSString stringWithFormat:@"%qu bytes", size];

            else 

                if (size >= 1024 && size < pow(1024, 2)) 

                    formattedStr = [NSString stringWithFormat:@"%.1f KB", (size / 1024.)];

                else 

                    if (size >= pow(1024, 2) && size < pow(1024, 3))

                        formattedStr = [NSString stringWithFormat:@"%.2f MB", (size / pow(1024, 2))];

                    else 

                        if (size >= pow(1024, 3)) 

                            formattedStr = [NSString stringWithFormat:@"%.3f GB", (size / pow(1024, 3))];

     

    return formattedStr;

    }

    // if we installed a custom UIGestureRecognizer (i.e. long-hold), then this would be called

    - (void)handleLongPress:(UILongPressGestureRecognizer *)longPressGesture

    {

        if (longPressGesture.state == UIGestureRecognizerStateBegan)

        {

            NSIndexPath *cellIndexPath = [self.tableView indexPathForRowAtPoint:[longPressGesture locationInView:self.tableView]];

     

    NSURL *fileURL;

    if (cellIndexPath.section == 0)

    fileURL = [NSURLfileURLWithPath:[[NSBundlemainBundle] pathForResource:documents[cellIndexPath.row] ofType:nil]];

    else

    fileURL = [self.documentURLs objectAtIndex:cellIndexPath.row];

    self.docInteractionController.URL = fileURL;

     

    [self.docInteractionControllerpresentOptionsMenuFromRect:longPressGesture.view.frame

                                                               inView:longPressGesture.view

                                                             animated:YES];

        }

    }

    - (UITableViewCell *)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    {

        static NSString *cellIdentifier = @"cellID";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

           if (!cell)

        {

            cell = [[[UITableViewCellalloc] initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:cellIdentifier] autorelease];

            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

        }

         NSURL *fileURL;

        if (indexPath.section == 0)

        {

            // first section is our build-in documents

        fileURL = [NSURLfileURLWithPath:[[NSBundlemainBundle] pathForResource:documents[indexPath.row] ofType:nil]];

        }

        else

        {

            // second section is the contents of the Documents folder

    fileURL = [self.documentURLs objectAtIndex:indexPath.row];

        }

    [selfsetupDocumentControllerWithURL:fileURL];

        // layout the cell

        cell.textLabel.text = [[fileURL path] lastPathComponent];

        NSInteger iconCount = [docInteractionController.iconscount];

        if (iconCount > 0)

        {

            cell.imageView.image = [docInteractionController.icons objectAtIndex:iconCount - 1];

        }

        NSError *error;

        NSString *fileURLString = [self.docInteractionController.URL path];

        NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:fileURLString error:&error];

        NSInteger fileSize = [[fileAttributes objectForKey:NSFileSize] intValue];

        cell.detailTextLabel.text = [NSStringstringWithFormat:@"%@ - %@",

                                     [self formattedFileSize:fileSize], docInteractionController.UTI];

         // attach to our view any gesture recognizers that the UIDocumentInteractionController provides

        //cell.imageView.userInteractionEnabled = YES;

        //cell.contentView.gestureRecognizers = self.docInteractionController.gestureRecognizers;

        //

        // or

        // add a custom gesture recognizer in lieu of using the canned ones

        UILongPressGestureRecognizer *longPressGesture =

        [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];

        [cell.imageView addGestureRecognizer:longPressGesture];

        cell.imageView.userInteractionEnabled = YES;    // this is by default NO, so we need to turn it on

        [longPressGesture release];

         return cell;

    }

     - (CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    {

        returnkRowHeight;

    }

     #pragma mark -

    #pragma mark UITableView delegate

     - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    {

        // three ways to present a preview:

        // 1. Don't implement this method and simply attach the canned gestureRecognizers to the cell

        //

        // 2. Don't use canned gesture recognizers and simply use UIDocumentInteractionController's

        //      presentPreviewAnimated: to get a preview for the document associated with this cell

        //

        // 3. Use the QLPreviewController to give the user preview access to the document associated

        //      with this cell and all the other documents as well.

        

        // for case 2 use this, allowing UIDocumentInteractionController to handle the preview:

        /*

        NSURL *fileURL;

        if (indexPath.section == 0)

        {

            fileURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:documents[indexPath.row] ofType:nil]];

        }

        else

        {

            fileURL = [self.documentURLs objectAtIndex:indexPath.row];

        }

        [self setupDocumentControllerWithURL:fileURL];

        [self.docInteractionController presentPreviewAnimated:YES];

        */

        // for case 3 we use the QuickLook APIs directly to preview the document -

        QLPreviewController *previewController = [[QLPreviewControlleralloc] init];

        previewController.dataSource = self;

        previewController.delegate = self;

        // start previewing the document at the current section index

        previewController.currentPreviewItemIndex = indexPath.row;

        [[selfnavigationController] pushViewController:previewController animated:YES];

        [previewController release];

    }

     #pragma mark -

    #pragma mark UIDocumentInteractionControllerDelegate

     - (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)interactionController

    {

        returnself;

    }

     #pragma mark -

    #pragma mark QLPreviewControllerDataSource

     

    // Returns the number of items that the preview controller should preview

    - (NSInteger)numberOfPreviewItemsInPreviewController:(QLPreviewController *)previewController

    {

        NSInteger numToPreview = 0;

        NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];

        if (selectedIndexPath.section == 0)

            numToPreview = NUM_DOCS;

        else

            numToPreview = self.documentURLs.count;

         return numToPreview;

    }

     - (void)previewControllerDidDismiss:(QLPreviewController *)controller

    {

        // if the preview dismissed (done button touched), use this method to post-process previews

    }

     // returns the item that the preview controller should preview

    - (id)previewController:(QLPreviewController *)previewController previewItemAtIndex:(NSInteger)idx

    {

        NSURL *fileURL = nil;

        NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];

        if (selectedIndexPath.section == 0)

        {

            fileURL = [NSURLfileURLWithPath:[[NSBundlemainBundle] pathForResource:documents[idx] ofType:nil]];

            //fileURL = [NSURL URLWithString:[NSString stringWithFormat:@"http://vr.tudou.com/v2proxy/v2.m3u8?it=5903919&st=2"]];//http://www.tudou.com/programs/view/R-FTzWszxS0/?resourceId=0_06_02_99?fr=2

        }

        else

        {

            fileURL = [self.documentURLs objectAtIndex:idx];

        }

        return fileURL;

    }

     #pragma mark -

    #pragma mark File system support

     - (NSString *)applicationDocumentsDirectory

    {

    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

    }

     - (void)directoryDidChange:(DirectoryWatcher *)folderWatcher {

    [self.documentURLsremoveAllObjects];    // clear out the old docs and start over

     NSString *documentsDirectoryPath = [self applicationDocumentsDirectory];

     NSArray *documentsDirectoryContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:documentsDirectoryPath error:NULL];

     for (NSString* curFileName in [documentsDirectoryContents objectEnumerator]) {

     

    NSString *filePath = [documentsDirectoryPath stringByAppendingPathComponent:curFileName];

    NSURL *fileURL = [NSURL fileURLWithPath:filePath];

    BOOL isDirectory;

            [[NSFileManagerdefaultManager] fileExistsAtPath:filePath isDirectory:&isDirectory];

             // proceed to add the document URL to our list (ignore the "Inbox" folder)

            if (!(isDirectory && [curFileName isEqualToString: @"Inbox"]))

            {

                [self.documentURLs addObject:fileURL];

            }

    }

    [self.tableViewreloadData];

    }

    @end

     

    2.

    DirectoryWatcher.h 文件

    #import <Foundation/Foundation.h>

     @classDirectoryWatcher;

     @protocol DirectoryWatcherDelegate <NSObject>

    @required

    - (void)directoryDidChange:(DirectoryWatcher *)folderWatcher;

    @end

     @interface DirectoryWatcher : NSObject  {

     

    id <DirectoryWatcherDelegate> delegate;

        int dirFD;

        int kq;

        CFFileDescriptorRef dirKQRef;

    }

    @property (nonatomic, assign) id <DirectoryWatcherDelegate> delegate;

     + (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id<DirectoryWatcherDelegate>)watchDelegate;

    - (void)invalidate;

    @end

    DirectoryWatcher.m 文件

    #import "DirectoryWatcher.h"

     #include <sys/types.h>

    #include <sys/event.h>

    #include <sys/time.h>

    #include <fcntl.h>

    #include <unistd.h>

     #import <CoreFoundation/CoreFoundation.h>

     @interface DirectoryWatcher (DirectoryWatcherPrivate)

    - (BOOL)startMonitoringDirectory:(NSString *)dirPath;

    - (void)kqueueFired;

    @end

     #pragma mark -

     @implementation DirectoryWatcher

     @synthesize delegate;

     - (id)init {

    self= [superinit];

    delegate = NULL;

     dirFD = -1;

        kq = -1;

    dirKQRef = NULL;

     returnself;

    }

     - (void)dealloc {

    [selfinvalidate];

    [superdealloc];

    }

     + (DirectoryWatcher *)watchFolderWithPath:(NSString *)watchPath delegate:(id)watchDelegate {

    DirectoryWatcher *retVal = NULL;

    if ((watchDelegate != NULL) && (watchPath != NULL)) {

    DirectoryWatcher *tempManager = [[[DirectoryWatcheralloc] init] autorelease];

    tempManager.delegate = watchDelegate;

    if ([tempManager startMonitoringDirectory: watchPath]) {

    // Everything appears to be in order, so return the DirectoryWatcher.  

    // Otherwise we'll fall through and return NULL.

    retVal = tempManager;

    }

    }

    return retVal;

    }

     - (void)invalidate {

    if (dirKQRef != NULL) {

    CFFileDescriptorInvalidate(dirKQRef);

    CFRelease(dirKQRef);

    dirKQRef = NULL;

    // We don't need to close the kq, CFFileDescriptorInvalidate closed it instead.

    // Change the value so no one thinks it's still live.

    kq = -1;

    }

    if(dirFD != -1) {

    close(dirFD);

    dirFD = -1;

    }

    }

    @end

     #pragma mark -

     @implementation DirectoryWatcher (DirectoryWatcherPrivate)

     - (void)kqueueFired {

        assert(kq >= 0);

        struct kevent   event;

        struct timespec timeout = {0, 0};

        int             eventCount;

        eventCount = kevent(kq, NULL, 0, &event, 1, &timeout);

        assert((eventCount >= 0) && (eventCount < 2));

        // call our delegate of the directory change

        [delegatedirectoryDidChange:self];

        CFFileDescriptorEnableCallBacks(dirKQRef, kCFFileDescriptorReadCallBack);

    }

     static void KQCallback(CFFileDescriptorRef kqRef, CFOptionFlags callBackTypes, void *info) {

        DirectoryWatcher *obj;

        obj = (DirectoryWatcher *)info;

        assert([obj isKindOfClass:[DirectoryWatcherclass]]);

        assert(kqRef == obj->dirKQRef);

        assert(callBackTypes == kCFFileDescriptorReadCallBack);

      [obj kqueueFired];

    }

     - (BOOL)startMonitoringDirectory:(NSString *)dirPath {

    // Double initializing is not going to work...

    if ((dirKQRef == NULL) && (dirFD == -1) && (kq == -1)) {

    // Open the directory we're going to watch

    dirFD = open([dirPath fileSystemRepresentation], O_EVTONLY);

    if (dirFD >= 0) {

    // Create a kqueue for our event messages...

    kq = kqueue();

    if (kq >= 0) {

    struct kevent eventToAdd;

    eventToAdd.ident  = dirFD;

    eventToAdd.filter = EVFILT_VNODE;

    eventToAdd.flags  = EV_ADD | EV_CLEAR;

    eventToAdd.fflags = NOTE_WRITE;

    eventToAdd.data   = 0;

    eventToAdd.udata  = NULL;

     int errNum = kevent(kq, &eventToAdd, 1, NULL, 0, NULL);

    if (errNum == 0) {

    CFFileDescriptorContext context = { 0, self, NULL, NULL, NULL };

    CFRunLoopSourceRef      rls;

     // Passing true in the third argument so CFFileDescriptorInvalidate will close kq.

    dirKQRef = CFFileDescriptorCreate(NULL, kq, true, KQCallback, &context);

    if (dirKQRef != NULL) {

    rls = CFFileDescriptorCreateRunLoopSource(NULL, dirKQRef, 0);

    if (rls != NULL) {

    CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode);

    CFRelease(rls);

    CFFileDescriptorEnableCallBacks(dirKQRef, kCFFileDescriptorReadCallBack);

     // If everything worked, return early and bypass shutting things down

    return YES;

    }

    // Couldn't create a runloop source, invalidate and release the CFFileDescriptorRef

    CFFileDescriptorInvalidate(dirKQRef);

                            CFRelease(dirKQRef);

    dirKQRef = NULL;

    }

    }

    // kq is active, but something failed, close the handle...

    close(kq);

    kq = -1;

    }

    // file handle is open, but something failed, close the handle...

    close(dirFD);

    dirFD = -1;

    }

    }

    returnNO;

    }

    @end

     

  • 相关阅读:
    程序猿也爱学英语(上),有图有真相
    New Year's resolution for 2016
    Got the Best Employee of the year 2015 Star Award
    AngularJs项目文件以及文件夹结构
    完成AngularJS with MVC 5, Web API 2项目
    两则新闻引发的思考
    关于招聘的最新信息
    架构师面试更新版
    2015新加坡总统府
    关于2014年的旅行
  • 原文地址:https://www.cnblogs.com/jiangshiyong/p/2821357.html
Copyright © 2011-2022 走看看