1

想知道是否有人可以举例说明如何下载文件以用于此 PDF 阅读器代码?我很新,一直在努力,但我认为是时候看看有经验的眼睛了。谢谢!

//
//  ReaderViewController.m
//  Reader v2.6.0


/////////////////////////////
#import "ReaderConstants.h"
#import "ReaderViewController.h"
#import "ThumbsViewController.h"
#import "ReaderMainToolbar.h"
#import "ReaderMainPagebar.h"
#import "ReaderContentView.h"
#import "ReaderThumbCache.h"
#import "ReaderThumbQueue.h"

#import <MessageUI/MessageUI.h>

@interface ReaderViewController () <UIScrollViewDelegate, UIGestureRecognizerDelegate, MFMailComposeViewControllerDelegate,
                                    ReaderMainToolbarDelegate, ReaderMainPagebarDelegate, ReaderContentViewDelegate, ThumbsViewControllerDelegate>
@end

@implementation ReaderViewController
{
    ReaderDocument *document;

    UIScrollView *theScrollView;

    ReaderMainToolbar *mainToolbar;

    ReaderMainPagebar *mainPagebar;

    NSMutableDictionary *contentViews;

    UIPrintInteractionController *printInteraction;

    NSInteger currentPage;

    CGSize lastAppearSize;

    NSDate *lastHideTime;

    BOOL isVisible;
}

#pragma mark Constants

#define PAGING_VIEWS 3

#define TOOLBAR_HEIGHT 44.0f
#define PAGEBAR_HEIGHT 48.0f

#define TAP_AREA_SIZE 48.0f

#pragma mark Properties

@synthesize delegate;

#pragma mark Support methods

- (void)updateScrollViewContentSize
{
    NSInteger count = [document.pageCount integerValue];

    if (count > PAGING_VIEWS) count = PAGING_VIEWS; // Limit

    CGFloat contentHeight = theScrollView.bounds.size.height;

    CGFloat contentWidth = (theScrollView.bounds.size.width * count);

    theScrollView.contentSize = CGSizeMake(contentWidth, contentHeight);
}

- (void)updateScrollViewContentViews
{
    [self updateScrollViewContentSize]; // Update the content size

    NSMutableIndexSet *pageSet = [NSMutableIndexSet indexSet]; // Page set

    [contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
        ^(id key, id object, BOOL *stop)
        {
            ReaderContentView *contentView = object; [pageSet addIndex:contentView.tag];
        }
    ];

    __block CGRect viewRect = CGRectZero; viewRect.size = theScrollView.bounds.size;

    __block CGPoint contentOffset = CGPointZero; NSInteger page = [document.pageNumber integerValue];

    [pageSet enumerateIndexesUsingBlock: // Enumerate page number set
        ^(NSUInteger number, BOOL *stop)
        {
            NSNumber *key = [NSNumber numberWithInteger:number]; // # key

            ReaderContentView *contentView = [contentViews objectForKey:key];

            contentView.frame = viewRect; if (page == number) contentOffset = viewRect.origin;

            viewRect.origin.x += viewRect.size.width; // Next view frame position
        }
    ];

    if (CGPointEqualToPoint(theScrollView.contentOffset, contentOffset) == false)
    {
        theScrollView.contentOffset = contentOffset; // Update content offset
    }
}

- (void)updateToolbarBookmarkIcon
{
    NSInteger page = [document.pageNumber integerValue];

    BOOL bookmarked = [document.bookmarks containsIndex:page];

    [mainToolbar setBookmarkState:bookmarked]; // Update
}

- (void)showDocumentPage:(NSInteger)page
{
    if (page != currentPage) // Only if different
    {
        NSInteger minValue; NSInteger maxValue;
        NSInteger maxPage = [document.pageCount integerValue];
        NSInteger minPage = 1;

        if ((page < minPage) || (page > maxPage)) return;

        if (maxPage <= PAGING_VIEWS) // Few pages
        {
            minValue = minPage;
            maxValue = maxPage;
        }
        else // Handle more pages
        {
            minValue = (page - 1);
            maxValue = (page + 1);

            if (minValue < minPage)
                {minValue++; maxValue++;}
            else
                if (maxValue > maxPage)
                    {minValue--; maxValue--;}
        }

        NSMutableIndexSet *newPageSet = [NSMutableIndexSet new];

        NSMutableDictionary *unusedViews = [contentViews mutableCopy];

        CGRect viewRect = CGRectZero; viewRect.size = theScrollView.bounds.size;

        for (NSInteger number = minValue; number <= maxValue; number++)
        {
            NSNumber *key = [NSNumber numberWithInteger:number]; // # key

            ReaderContentView *contentView = [contentViews objectForKey:key];

            if (contentView == nil) // Create a brand new document content view
            {
                NSURL *fileURL = document.fileURL; NSString *phrase = document.password; // Document properties

                contentView = [[ReaderContentView alloc] initWithFrame:viewRect fileURL:fileURL page:number password:phrase];

                [theScrollView addSubview:contentView]; [contentViews setObject:contentView forKey:key];

                contentView.message = self; [newPageSet addIndex:number];
            }
            else // Reposition the existing content view
            {
                contentView.frame = viewRect; [contentView zoomReset];

                [unusedViews removeObjectForKey:key];
            }

            viewRect.origin.x += viewRect.size.width;
        }

        [unusedViews enumerateKeysAndObjectsUsingBlock: // Remove unused views
            ^(id key, id object, BOOL *stop)
            {
                [contentViews removeObjectForKey:key];

                ReaderContentView *contentView = object;

                [contentView removeFromSuperview];
            }
        ];

        unusedViews = nil; // Release unused views

        CGFloat viewWidthX1 = viewRect.size.width;
        CGFloat viewWidthX2 = (viewWidthX1 * 2.0f);

        CGPoint contentOffset = CGPointZero;

        if (maxPage >= PAGING_VIEWS)
        {
            if (page == maxPage)
                contentOffset.x = viewWidthX2;
            else
                if (page != minPage)
                    contentOffset.x = viewWidthX1;
        }
        else
            if (page == (PAGING_VIEWS - 1))
                contentOffset.x = viewWidthX1;

        if (CGPointEqualToPoint(theScrollView.contentOffset, contentOffset) == false)
        {
            theScrollView.contentOffset = contentOffset; // Update content offset
        }

        if ([document.pageNumber integerValue] != page) // Only if different
        {
            document.pageNumber = [NSNumber numberWithInteger:page]; // Update page number
        }

        NSURL *fileURL = document.fileURL; NSString *phrase = document.password; NSString *guid = document.guid;

        if ([newPageSet containsIndex:page] == YES) // Preview visible page first
        {
            NSNumber *key = [NSNumber numberWithInteger:page]; // # key

            ReaderContentView *targetView = [contentViews objectForKey:key];

            [targetView showPageThumb:fileURL page:page password:phrase guid:guid];

            [newPageSet removeIndex:page]; // Remove visible page from set
        }

        [newPageSet enumerateIndexesWithOptions:NSEnumerationReverse usingBlock: // Show previews
            ^(NSUInteger number, BOOL *stop)
            {
                NSNumber *key = [NSNumber numberWithInteger:number]; // # key

                ReaderContentView *targetView = [contentViews objectForKey:key];

                [targetView showPageThumb:fileURL page:number password:phrase guid:guid];
            }
        ];

        newPageSet = nil; // Release new page set

        [mainPagebar updatePagebar]; // Update the pagebar display

        [self updateToolbarBookmarkIcon]; // Update bookmark

        currentPage = page; // Track current page number
    }
}

- (void)showDocument:(id)object
{
    [self updateScrollViewContentSize]; // Set content size

    [self showDocumentPage:[document.pageNumber integerValue]];

    document.lastOpen = [NSDate date]; // Update last opened date

    isVisible = YES; // iOS present modal bodge
}

#pragma mark UIViewController methods

- (id)initWithReaderDocument:(ReaderDocument *)object
{
    id reader = nil; // ReaderViewController object

    if ((object != nil) && ([object isKindOfClass:[ReaderDocument class]]))
    {
        if ((self = [super initWithNibName:nil bundle:nil])) // Designated initializer
        {
            NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];

            [notificationCenter addObserver:self selector:@selector(applicationWill:) name:UIApplicationWillTerminateNotification object:nil];

            [notificationCenter addObserver:self selector:@selector(applicationWill:) name:UIApplicationWillResignActiveNotification object:nil];

            [object updateProperties]; document = object; // Retain the supplied ReaderDocument object for our use

            [ReaderThumbCache touchThumbCacheWithGUID:object.guid]; // Touch the document thumb cache directory

            reader = self; // Return an initialized ReaderViewController object
        }
    }

    return reader;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    assert(document != nil); // Must have a valid ReaderDocument

    self.view.backgroundColor = [UIColor scrollViewTexturedBackgroundColor];

    CGRect viewRect = self.view.bounds; // View controller's view bounds

    theScrollView = [[UIScrollView alloc] initWithFrame:viewRect]; // All

    theScrollView.scrollsToTop = NO;
    theScrollView.pagingEnabled = YES;
    theScrollView.delaysContentTouches = NO;
    theScrollView.showsVerticalScrollIndicator = NO;
    theScrollView.showsHorizontalScrollIndicator = NO;
    theScrollView.contentMode = UIViewContentModeRedraw;
    theScrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    theScrollView.backgroundColor = [UIColor clearColor];
    theScrollView.userInteractionEnabled = YES;
    theScrollView.autoresizesSubviews = NO;
    theScrollView.delegate = self;

    [self.view addSubview:theScrollView];

    CGRect toolbarRect = viewRect;
    toolbarRect.size.height = TOOLBAR_HEIGHT;

    mainToolbar = [[ReaderMainToolbar alloc] initWithFrame:toolbarRect document:document]; // At top

    mainToolbar.delegate = self;

    [self.view addSubview:mainToolbar];

    CGRect pagebarRect = viewRect;
    pagebarRect.size.height = PAGEBAR_HEIGHT;
    pagebarRect.origin.y = (viewRect.size.height - PAGEBAR_HEIGHT);

    mainPagebar = [[ReaderMainPagebar alloc] initWithFrame:pagebarRect document:document]; // At bottom

    mainPagebar.delegate = self;

    [self.view addSubview:mainPagebar];

    UITapGestureRecognizer *singleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
    singleTapOne.numberOfTouchesRequired = 1; singleTapOne.numberOfTapsRequired = 1; singleTapOne.delegate = self;
    [self.view addGestureRecognizer:singleTapOne];

    UITapGestureRecognizer *doubleTapOne = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
    doubleTapOne.numberOfTouchesRequired = 1; doubleTapOne.numberOfTapsRequired = 2; doubleTapOne.delegate = self;
    [self.view addGestureRecognizer:doubleTapOne];

    UITapGestureRecognizer *doubleTapTwo = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
    doubleTapTwo.numberOfTouchesRequired = 2; doubleTapTwo.numberOfTapsRequired = 2; doubleTapTwo.delegate = self;
    [self.view addGestureRecognizer:doubleTapTwo];

    [singleTapOne requireGestureRecognizerToFail:doubleTapOne]; // Single tap requires double tap to fail

    contentViews = [NSMutableDictionary new]; lastHideTime = [NSDate date];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if (CGSizeEqualToSize(lastAppearSize, CGSizeZero) == false)
    {
        if (CGSizeEqualToSize(lastAppearSize, self.view.bounds.size) == false)
        {
            [self updateScrollViewContentViews]; // Update content views
        }

        lastAppearSize = CGSizeZero; // Reset view size tracking
    }
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    if (CGSizeEqualToSize(theScrollView.contentSize, CGSizeZero)) // First time
    {
        [self performSelector:@selector(showDocument:) withObject:nil afterDelay:0.02];
    }

#if (READER_DISABLE_IDLE == TRUE) // Option

    [UIApplication sharedApplication].idleTimerDisabled = YES;

#endif // end of READER_DISABLE_IDLE Option
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];

    lastAppearSize = self.view.bounds.size; // Track view size

#if (READER_DISABLE_IDLE == TRUE) // Option

    [UIApplication sharedApplication].idleTimerDisabled = NO;

#endif // end of READER_DISABLE_IDLE Option
}

- (void)viewDidDisappear:(BOOL)animated
{
    [super viewDidDisappear:animated];
}

- (void)viewDidUnload
{
#ifdef DEBUG
    NSLog(@"%s", __FUNCTION__);
#endif

    mainToolbar = nil; mainPagebar = nil;

    theScrollView = nil; contentViews = nil; lastHideTime = nil;

    lastAppearSize = CGSizeZero; currentPage = 0;

    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return YES;
}

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
    if (isVisible == NO) return; // iOS present modal bodge

    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad)
    {
        if (printInteraction != nil) [printInteraction dismissAnimated:NO];
    }
}

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
{
    if (isVisible == NO) return; // iOS present modal bodge

    [self updateScrollViewContentViews]; // Update content views

    lastAppearSize = CGSizeZero; // Reset view size tracking
}

/*
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    //if (isVisible == NO) return; // iOS present modal bodge

    //if (fromInterfaceOrientation == self.interfaceOrientation) return;
}
*/

- (void)didReceiveMemoryWarning
{
#ifdef DEBUG
    NSLog(@"%s", __FUNCTION__);
#endif

    [super didReceiveMemoryWarning];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark UIScrollViewDelegate methods

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    __block NSInteger page = 0;

    CGFloat contentOffsetX = scrollView.contentOffset.x;

    [contentViews enumerateKeysAndObjectsUsingBlock: // Enumerate content views
        ^(id key, id object, BOOL *stop)
        {
            ReaderContentView *contentView = object;

            if (contentView.frame.origin.x == contentOffsetX)
            {
                page = contentView.tag; *stop = YES;
            }
        }
    ];

    if (page != 0) [self showDocumentPage:page]; // Show the page
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
    [self showDocumentPage:theScrollView.tag]; // Show page

    theScrollView.tag = 0; // Clear page number tag
}

#pragma mark UIGestureRecognizerDelegate methods

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)recognizer shouldReceiveTouch:(UITouch *)touch
{
    if ([touch.view isKindOfClass:[UIScrollView class]]) return YES;

    return NO;
}

#pragma mark UIGestureRecognizer action methods

- (void)decrementPageNumber
{
    if (theScrollView.tag == 0) // Scroll view did end
    {
        NSInteger page = [document.pageNumber integerValue];
        NSInteger maxPage = [document.pageCount integerValue];
        NSInteger minPage = 1; // Minimum

        if ((maxPage > minPage) && (page != minPage))
        {
            CGPoint contentOffset = theScrollView.contentOffset;

            contentOffset.x -= theScrollView.bounds.size.width; // -= 1

            [theScrollView setContentOffset:contentOffset animated:YES];

            theScrollView.tag = (page - 1); // Decrement page number
        }
    }
}

- (void)incrementPageNumber
{
    if (theScrollView.tag == 0) // Scroll view did end
    {
        NSInteger page = [document.pageNumber integerValue];
        NSInteger maxPage = [document.pageCount integerValue];
        NSInteger minPage = 1; // Minimum

        if ((maxPage > minPage) && (page != maxPage))
        {
            CGPoint contentOffset = theScrollView.contentOffset;

            contentOffset.x += theScrollView.bounds.size.width; // += 1

            [theScrollView setContentOffset:contentOffset animated:YES];

            theScrollView.tag = (page + 1); // Increment page number
        }
    }
}

- (void)handleSingleTap:(UITapGestureRecognizer *)recognizer
{
    if (recognizer.state == UIGestureRecognizerStateRecognized)
    {
        CGRect viewRect = recognizer.view.bounds; // View bounds

        CGPoint point = [recognizer locationInView:recognizer.view];

        CGRect areaRect = CGRectInset(viewRect, TAP_AREA_SIZE, 0.0f); // Area

        if (CGRectContainsPoint(areaRect, point)) // Single tap is inside the area
        {
            NSInteger page = [document.pageNumber integerValue]; // Current page #

            NSNumber *key = [NSNumber numberWithInteger:page]; // Page number key

            ReaderContentView *targetView = [contentViews objectForKey:key];

            id target = [targetView processSingleTap:recognizer]; // Target

            if (target != nil) // Handle the returned target object
            {
                if ([target isKindOfClass:[NSURL class]]) // Open a URL
                {
                    NSURL *url = (NSURL *)target; // Cast to a NSURL object

                    if (url.scheme == nil) // Handle a missing URL scheme
                    {
                        NSString *www = url.absoluteString; // Get URL string

                        if ([www hasPrefix:@"www"] == YES) // Check for 'www' prefix
                        {
                            NSString *http = [NSString stringWithFormat:@"http://%@", www];

                            url = [NSURL URLWithString:http]; // Proper http-based URL
                        }
                    }

                    if ([[UIApplication sharedApplication] openURL:url] == NO)
                    {
                        #ifdef DEBUG
                            NSLog(@"%s '%@'", __FUNCTION__, url); // Bad or unknown URL
                        #endif
                    }
                }
                else // Not a URL, so check for other possible object type
                {
                    if ([target isKindOfClass:[NSNumber class]]) // Goto page
                    {
                        NSInteger value = [target integerValue]; // Number

                        [self showDocumentPage:value]; // Show the page
                    }
                }
            }
            else // Nothing active tapped in the target content view
            {
                if ([lastHideTime timeIntervalSinceNow] < -0.75) // Delay since hide
                {
                    if ((mainToolbar.hidden == YES) || (mainPagebar.hidden == YES))
                    {
                        [mainToolbar showToolbar]; [mainPagebar showPagebar]; // Show
                    }
                }
            }

            return;
        }

        CGRect nextPageRect = viewRect;
        nextPageRect.size.width = TAP_AREA_SIZE;
        nextPageRect.origin.x = (viewRect.size.width - TAP_AREA_SIZE);

        if (CGRectContainsPoint(nextPageRect, point)) // page++ area
        {
            [self incrementPageNumber]; return;
        }

        CGRect prevPageRect = viewRect;
        prevPageRect.size.width = TAP_AREA_SIZE;

        if (CGRectContainsPoint(prevPageRect, point)) // page-- area
        {
            [self decrementPageNumber]; return;
        }
    }
}

- (void)handleDoubleTap:(UITapGestureRecognizer *)recognizer
{
    if (recognizer.state == UIGestureRecognizerStateRecognized)
    {
        CGRect viewRect = recognizer.view.bounds; // View bounds

        CGPoint point = [recognizer locationInView:recognizer.view];

        CGRect zoomArea = CGRectInset(viewRect, TAP_AREA_SIZE, TAP_AREA_SIZE);

        if (CGRectContainsPoint(zoomArea, point)) // Double tap is in the zoom area
        {
            NSInteger page = [document.pageNumber integerValue]; // Current page #

            NSNumber *key = [NSNumber numberWithInteger:page]; // Page number key

            ReaderContentView *targetView = [contentViews objectForKey:key];

            switch (recognizer.numberOfTouchesRequired) // Touches count
            {
                case 1: // One finger double tap: zoom ++
                {
                    [targetView zoomIncrement]; break;
                }

                case 2: // Two finger double tap: zoom --
                {
                    [targetView zoomDecrement]; break;
                }
            }

            return;
        }

        CGRect nextPageRect = viewRect;
        nextPageRect.size.width = TAP_AREA_SIZE;
        nextPageRect.origin.x = (viewRect.size.width - TAP_AREA_SIZE);

        if (CGRectContainsPoint(nextPageRect, point)) // page++ area
        {
            [self incrementPageNumber]; return;
        }

        CGRect prevPageRect = viewRect;
        prevPageRect.size.width = TAP_AREA_SIZE;

        if (CGRectContainsPoint(prevPageRect, point)) // page-- area
        {
            [self decrementPageNumber]; return;
        }
    }
}

#pragma mark ReaderContentViewDelegate methods

- (void)contentView:(ReaderContentView *)contentView touchesBegan:(NSSet *)touches
{
    if ((mainToolbar.hidden == NO) || (mainPagebar.hidden == NO))
    {
        if (touches.count == 1) // Single touches only
        {
            UITouch *touch = [touches anyObject]; // Touch info

            CGPoint point = [touch locationInView:self.view]; // Touch location

            CGRect areaRect = CGRectInset(self.view.bounds, TAP_AREA_SIZE, TAP_AREA_SIZE);

            if (CGRectContainsPoint(areaRect, point) == false) return;
        }

        [mainToolbar hideToolbar]; [mainPagebar hidePagebar]; // Hide

        lastHideTime = [NSDate date];
    }
}

#pragma mark ReaderMainToolbarDelegate methods

- (void)tappedInToolbar:(ReaderMainToolbar *)toolbar doneButton:(UIButton *)button
{
#if (READER_STANDALONE == FALSE) // Option

    [document saveReaderDocument]; // Save any ReaderDocument object changes

    [[ReaderThumbQueue sharedInstance] cancelOperationsWithGUID:document.guid];

    [[ReaderThumbCache sharedInstance] removeAllObjects]; // Empty the thumb cache

    if (printInteraction != nil) [printInteraction dismissAnimated:NO]; // Dismiss

    if ([delegate respondsToSelector:@selector(dismissReaderViewController:)] == YES)
    {
        [delegate dismissReaderViewController:self]; // Dismiss the ReaderViewController
    }
    else // We have a "Delegate must respond to -dismissReaderViewController: error"
    {
        NSAssert(NO, @"Delegate must respond to -dismissReaderViewController:");
    }

#endif // end of READER_STANDALONE Option
}
4

0 回答 0