I have searched a lot to find a solution to delete section's in a UICollectionView
but all the proposed solutions leading to a crash.
The code is I have used is:
[categoryCollection performBatchUpdates:^{
NSIndexSet *indexSet=[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, keys.count-1)];
[categoryCollection deleteSections:indexSet];
} completion:nil];
Update:
#implementation BooksLayout
- (void)prepareLayout {
// Registers my decoration views.
[self registerClass:[ShelfView class] forDecorationViewOfKind:[ShelfView kind]];
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForDecorationViewOfKind:(NSString *)decorationViewKind atIndexPath:(NSIndexPath *)indexPath {
// Prepare some variables.
NSIndexPath *nextIndexPath = [NSIndexPath indexPathForItem:indexPath.row+1 inSection:indexPath.section];
UICollectionViewLayoutAttributes *cellAttributes = [self layoutAttributesForItemAtIndexPath:indexPath];
UICollectionViewLayoutAttributes *nextCellAttributes = [self layoutAttributesForItemAtIndexPath:nextIndexPath];
UICollectionViewLayoutAttributes *layoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForDecorationViewOfKind:decorationViewKind withIndexPath:indexPath];
CGRect baseFrame = cellAttributes.frame;
CGRect nextFrame = nextCellAttributes.frame;
CGFloat strokeWidth = 8;
CGFloat spaceToNextItem = 0;
if (nextFrame.origin.y == baseFrame.origin.y)
spaceToNextItem = (nextFrame.origin.x - baseFrame.origin.x - baseFrame.size.width);
// Positions the horizontal line for this item.
layoutAttributes.frame = CGRectMake(10,
baseFrame.origin.y + baseFrame.size.height,
300,
strokeWidth);
layoutAttributes.zIndex = 1;
return layoutAttributes;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray *baseLayoutAttributes = [super layoutAttributesForElementsInRect:rect];
NSMutableArray * layoutAttributes = [baseLayoutAttributes mutableCopy];
for (UICollectionViewLayoutAttributes *thisLayoutItem in baseLayoutAttributes) {
if (thisLayoutItem.representedElementCategory == UICollectionElementCategoryCell) {
UICollectionViewLayoutAttributes *newHorizontalLayoutItem = [self layoutAttributesForDecorationViewOfKind:[ShelfView kind] atIndexPath:thisLayoutItem.indexPath];
[layoutAttributes addObject:newHorizontalLayoutItem];
}
}
return layoutAttributes;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
if([sortString isEqualToString:#"title"]){
NSArray *keys=[bookObj.orderedBooks allKeys];
keys = [keys sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)];
return [[bookObj.orderedBooks objectForKey:[keys objectAtIndex:section]] count];
}
else
return bookObj.booksArray.count;
}
Related
My Apple TV app lists a collection of PDFs, and clicking one draws it on the screen. For some reason, though, it exits the app completely when someone hits the < / Menu button on the Apple TV Remote. What is going on to cause it to do that?
Up first is the code where it pulls up the list of all the PDFs, followed by the code for displaying the PDF.
-(void)viewDidLoad {
[super viewDidLoad];
self.definesPresentationContext = YES; // know where you want UISearchController to be displayed
}
- (void)viewWillAppear:(BOOL)animated {
if (self.searchControllerWasActive) {
self.searchController.active = self.searchControllerWasActive;
_searchControllerWasActive = NO;
if (self.searchControllerSearchFieldWasFirstResponder) {
[self.searchController.searchBar becomeFirstResponder];
_searchControllerSearchFieldWasFirstResponder = NO;
}
}
NSBundle *bundle = [NSBundle mainBundle];
self.files = [bundle pathsForResourcesOfType:#"pdf" inDirectory:#"AIMPDF"];
NSString *documentsDirectoryPath = [self.files objectAtIndex:thepath.row];
self.title = #"Devo Songs";
self.filenames = [[documentsDirectoryPath lastPathComponent] stringByDeletingPathExtension];
NSLog(#"%#", filenames);
NSMutableArray *names = [NSMutableArray arrayWithCapacity:[self.files count]];
for (NSString *path in self.files) {
[names addObject:[[path lastPathComponent] stringByDeletingPathExtension]];
}
self.files = names;
self.files = [names sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
self.tableView.backgroundColor = [UIColor whiteColor];
self.parentViewController.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"iphonebackground.png"]];
[super viewDidLoad];
[super viewWillAppear:animated];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar {
[searchBar resignFirstResponder];
}
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
// update the filtered array based on the search text
NSString *searchText = searchController.searchBar.text;
NSMutableArray *searchResults2 = [self.files mutableCopy];
// strip out all the leading and trailing spaces
NSString *strippedString = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
// break up the search terms (separated by spaces)
NSArray *searchItems = nil;
if (strippedString.length > 0) {
searchItems = [strippedString componentsSeparatedByString:#" "];
}
// build all the "AND" expressions for each value in the searchString
//
NSMutableArray *andMatchPredicates = [NSMutableArray array];
for (NSString *searchString in searchItems) {
NSPredicate *sPredicate =
[NSPredicate predicateWithFormat:#"SELF contains[c] %#", searchString];
[searchResults2 filterUsingPredicate:sPredicate];
// at this OR predicate to our master AND predicate
// NSCompoundPredicate *orMatchPredicates = [NSCompoundPredicate orPredicateWithSubpredicates:searchItemsPredicate];
//[andMatchPredicates addObject:orMatchPredicates];
}
// match up the fields of the Product object
// NSCompoundPredicate *finalCompoundPredicate =
//[NSCompoundPredicate andPredicateWithSubpredicates:andMatchPredicates];
//searchResults2 = [[searchResults filteredArrayUsingPredicate:finalCompoundPredicate] mutableCopy];
// hand over the filtered results to our search results table
APLResultsTableController *tableController = (APLResultsTableController *)self.searchController.searchResultsController;
tableController.filteredProducts = searchResults2;
[tableController.tableView reloadData];
}
- (void)handleSearchForTerm:(NSString *)searchTerm
{
[self setSavedSearchTerm:searchTerm];
if ([self searchResults] == nil)
{
NSMutableArray *array = [[NSMutableArray alloc] init];
[self setSearchResults:array];
array = nil;
}
[[self searchResults] removeAllObjects];
if ([[self savedSearchTerm] length] != 0)
{
for (NSString *currentString in [self files])
{
if ([currentString rangeOfString:searchTerm options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[[self searchResults] addObject:currentString];
}
}
}
}- (void)viewDidUnload
{
[super viewDidUnload];
// Save the state of the search UI so that it can be restored if the view is re-created.
[self setSavedSearchTerm:[[[self searchDisplayController] searchBar] text]];
[self setSearchResults:nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
// The device is an iPad running iPhone 3.2 or later.
return YES;
}
else
{
// The device is an iPhone or iPod touch.
return YES;
}
#else
// iPhone simulator
return YES;
#endif
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
NSInteger rows;
rows = [[self files] count];
return rows;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *filename = [[[self.files objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension];
NSInteger row = [indexPath row];
NSString *contentForThisRow = nil;
contentForThisRow = filename;
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
[[cell textLabel] setText:contentForThisRow];
cell.textLabel.font = [UIFont fontWithName:#"Helvetica Neue" size:90];
cell.textLabel.textColor = [UIColor blackColor];
cell.backgroundColor = [UIColor lightGrayColor];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
return 80;
}
else {
return 120;
}
}
- (void)tableView:(UITableView *)tableView didUpdateFocusInContext:(UITableViewFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
//this gives you the indexpath of the focused cell
NSIndexPath *nextIndexPath = [context nextFocusedIndexPath];
NSLog(#"Do Something");
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedCountry = (tableView == self.tableView) ?
self.files[indexPath.row] : self.resultsTableController.filteredProducts[indexPath.row];
[self performSegueWithIdentifier:#"ShowSong" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"ShowSong"])
{
NSLog(#"Selecting %#", self.selectedCountry);
FirstViewController* userViewController = [segue destinationViewController];
userViewController.selectedCountry = self.selectedCountry;
//if you need to pass data to the next controller do it here
}
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc. that aren't in use.
}
- (void)dealloc {
}
#end
And now the code for opening:
#implementation FirstViewController
- (CGPDFDocumentRef)openPDFLocal:(NSString *)pdfURL {
NSURL* NSUrl = [NSURL fileURLWithPath:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDFURL:(NSString *)pdfURL {
NSURL* NSUrl= [NSURL URLWithString:pdfURL];
return [self openPDF:NSUrl];
}
- (CGPDFDocumentRef)openPDF:(NSURL*)NSUrl {
CFURLRef url = (CFURLRef)CFBridgingRetain(NSUrl);
CGPDFDocumentRef myDocument;
myDocument = CGPDFDocumentCreateWithURL(url);
if (myDocument == NULL) {
NSLog(#"can't open %#", NSUrl);
CFRelease (url);
return nil;
}
CFRelease (url);
if (CGPDFDocumentGetNumberOfPages(myDocument) == 0) {
CGPDFDocumentRelease(myDocument);
return nil;
}
return myDocument;
}
- (void)drawDocument:(CGPDFDocumentRef)pdfDocument
{
// Get the total number of pages for the whole PDF document
int totalPages= (int)CGPDFDocumentGetNumberOfPages(pdfDocument);
self.pages = totalPages;
NSMutableArray *pageImages = [[NSMutableArray alloc] init];
// Iterate through the pages and add each page image to an array
for (int i = 1; i <= totalPages; i++) {
// Get the first page of the PDF document
CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocument, i);
CGRect pageRect = CGPDFPageGetBoxRect(page, kCGPDFMediaBox);
// Begin the image context with the page size
// Also get the grapgics context that we will draw to
UIGraphicsBeginImageContext(pageRect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Rotate the page, so it displays correctly
CGContextTranslateCTM(context, 0.0, pageRect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextConcatCTM(context, CGPDFPageGetDrawingTransform(page, kCGPDFMediaBox, pageRect, 0, true));
// Draw to the graphics context
CGContextDrawPDFPage(context, page);
// Get an image of the graphics context
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[pageImages addObject:image];
}
// Set the image of the PDF to the current view
[self addImagesToScrollView:pageImages];
}
-(void)addImagesToScrollView:(NSMutableArray*)imageArray {
int heigth = 0;
for (UIImage *image in imageArray) {
UIImageView *imgView = [[UIImageView alloc] initWithImage:image];
imgView.frame=CGRectMake(200, heigth, 1520, 1080);
[_scrollView addSubview:imgView];
heigth += imgView.frame.size.height;
}
}
-(void)viewDidLayoutSubviews {
NSLog(#"%ld", (long)self.pages);
_scrollView.contentSize = CGSizeMake(1920, 1080*self.pages);
}
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"DOCUMENTS%#", self.selectedCountry);
NSString *testing = [self.selectedCountry stringByAppendingString:#".pdf"];
//This is passed in from a tableview after selecting the PDF needed.
_scrollView.panGestureRecognizer.allowedTouchTypes = #[ #(UITouchTypeIndirect) ];
NSString *Documents = [[NSBundle mainBundle] pathForResource:self.selectedCountry ofType:#"pdf" inDirectory:#"AIMPDF"];
NSLog(#"OKOKOK%#", Documents);
NSURL *url = [NSURL fileURLWithPath:Documents];
self.view.backgroundColor = [UIColor blackColor];
CGPDFDocumentRef pdfDocument = [self openPDF:url];
[self drawDocument:pdfDocument];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
In your case the searching view controller stays on the top level of your app that's why the app is closed by pressing Menu button instead of returning to your start screen. On tvOS you should not use UISearchController directly and call
[self.searchController.searchBar becomeFirstResponder]; or self.searchController.active = YES; to present searching because it breaks a stacked view hierarchy that allows you to navigate upper by presented view controllers.
On Apple TV, people typically navigate by moving through stacked screens of content. Each screen may present entry points to other screens, and provides a way — through the remote — to return to the previous screen or main menu.
https://developer.apple.com/design/human-interface-guidelines/tvos/app-architecture/navigation/
There is UISearchContainerViewController view controller that manages the presentation of search results in your interface and you can use it for searching:
In tvOS, rather than push a UISearchController onto a navigation controller’s stack or use one as a child of another container view controller, embed an instance of this class and let it manage the presentation of the search controller’s content. https://developer.apple.com/documentation/uikit/uisearchcontainerviewcontroller
For instance:
UITableViewController* searchTableViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"SearchTableViewController"];
UISearchController* searchController = [[UISearchController alloc] initWithSearchResultsController:searchTableViewController];
searchController.delegate = self;
searchController.searchResultsUpdater = self;
searchController.searchBar.delegate = self;
self.searchContainerViewController = [[UISearchContainerViewController alloc] initWithSearchController:searchController];
// Show searching
[self presentViewController:self.searchContainerViewController animated:YES completion:nil];
I have a UITableView and his datasource is an NSMutableArray declared in my interface:
#property (strong, nonatomic) NSMutableArray *arrElements;
Now I implemented a simple "load more" in this way:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
//only if i have others results i will call load more
if([self.items_amount integerValue] > self.arrElements.count) {
if(DEBUG_MODE == 1) {
NSLog(#"Load more");
}
//get start param from array size and call load more
NSNumber *start = [NSNumber numberWithInteger:([self.arrElements count]+1)];
NSArray *passParams = [NSArray arrayWithObjects:self.menuItem,start,[NSNumber numberWithInteger:NUM_RESULTS_FOR_PAGE], nil];
[self performSelector:#selector(loadMore:) withObject:passParams afterDelay:0.1];
}
}
}
and this is my loadMore method:
//load more elements
- (void)loadMore:(NSArray *)arrParams {
//(MenuItem *)menuItem startingFrom:(NSNumber *)start numResults:(NSNumber *)results;
MenuItem *menuItem = [arrParams objectAtIndex:0];
NSNumber *start = [arrParams objectAtIndex:1];
NSNumber *results = [arrParams objectAtIndex:2];
if(DEBUG_MODE == 1) {
NSLog(#"Before load more %lu", (unsigned long)[self.arrElements count]);
}
//call API and parse it
WebServicesClient *restClient = [[WebServicesClient alloc] init];
NSData *data = [restClient callWorkAPI:[menuItem pathAPI] inLanguage:[[NSLocale preferredLanguages] objectAtIndex:0] withLat:self.latitude withLng:self.longitude startingFrom:start numRows:results];
for(Work* work in [[restClient parseWorks:data] objectForKey:#"items"]) {
[self.arrElements addObject:work];
}
if(DEBUG_MODE == 1) {
NSLog(#"After load more %lu", (unsigned long)[self.arrElements count]);
}
[self.tableElem reloadData];
}
And this is my custom cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier;
CellIdentifier = #"HomeCell";
HomeCell *cell = (HomeCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(!cell) {
cell = [[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
Work *work = (Work *)[[self arrElements] objectAtIndex:indexPath.row];
cell.backgroundColor = [UIColor clearColor];
cell.labelTitleItem.text = [work title];
cell.labelSubtitleItem.text = #"my category"
//if exists image
if([[work image] isKindOfClass:[NSString class]] && [[work image] length] > 0) {
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSData * data = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString:[work image]]];
if ( data == nil )
return;
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageItem.image = [UIImage imageWithData: data];
});
});
} else {
//remove image setting height to 0
[cell.imageItem setFrame:CGRectMake(cell.imageItem.frame.origin.x, cell.imageItem.frame.origin.y, cell.imageItem.frame.size.width, 0)];
}
if([[work distance] isKindOfClass:[NSString class]]) {
[cell.imagePriority setBackgroundColor:[UIColor lightGrayColor]];
cell.labelDistanceItem.text = [self convertDistance:[work distance]];
cell.labelDistanceItem.textColor = [UIColor whiteColor];
} else {
//remove image setting height to 0
[cell.imagePriority setFrame:CGRectMake(cell.imagePriority.frame.origin.x, cell.imagePriority.frame.origin.y, cell.imagePriority.frame.size.width, 0)];
//remove label distance setting height to 0
[cell.labelSubtitleItem setFrame:CGRectMake(cell.labelSubtitleItem.frame.origin.x, cell.labelSubtitleItem.frame.origin.y, cell.labelSubtitleItem.frame.size.width, 0)];
}
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self arrElements] count];
}
Now the problem is that after reloadData i lose the text of a UILabel (my category) of my CustomCell
please, Any suggests?
I've had similar problems with TalbeViews. Try using the method
- (void) tableView:(UITableView *)tableView willDisplayCell:(RCGameTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
to add the elements that you want. Keep the cell initialization that you do at the beginning of cellForRowAtIndexPath, but then return the cell right after and set the background color, labels, images, etc. in the willDisplayCell delegate function I mentioned.
I have referred NSOutlineview from this link. I dynamically load all values as based on selected values. Here i struct a issue while getting paths.
Like, Folder path. (eg.: D:/NewFolder/Test/blah/blah1
In same I need to get the full path selected child from parent. In the image, i selected
Project. so I need the path should be get like as follows,
/Test/New Folder/Untitled/Project
My code is
- (IBAction) ButtonClick:(id)sender
{
self.treeoutlineview.delegate = self;
self.treeoutlineview.dataSource = self;
NSString *roots = #"/";
NSIndexPath *indexPath = nil;
indexPath = [NSIndexPath indexPathWithIndex:[contents count]];
TreeNode *node = [[TreeNode alloc] init];
[node TitleSet:roots];
[self.treeController insertObject:node atArrangedObjectIndexPath:indexPath];
}
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
childItem = item;
return childItem;
}
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
noofchildren = 0;
return noofchildren;
}
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
return YES;
}
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
valueforcolumn = nil;
}
- (BOOL)outlineView:(NSOutlineView *)ov shouldSelectItem:(id)item {
{
rec = #"New Folder|Test|Backup|Project";
NSArray *arr = [rec componentsSeparatedByString:#"|"];
[loadChildValues removeAllObjects];
NSIndexPath *indexPath = nil;
if (![self.treeController selectionIndexPath])
{
indexPath = [NSIndexPath indexPathWithIndex:[contents count]];
}
else
{
if ([[[self.treeController selectedObjects] objectAtIndex:0] isLeaf])
{
NSBeep();
return;
}
indexPath = [self.treeController selectionIndexPath];
indexPath = [indexPath indexPathByAddingIndex:[[[[self.treeController selectedObjects] objectAtIndex:0] children] count]];
}
for (int i = 2; i< [arr count]; i++) {
[loadChildValues addObject:[arr objectAtIndex:i]];
TreeNode *node = [[TreeNode alloc] init];
[node TitleSet:[arr objectAtIndex:i]];
[self.treeController insertObject:node atArrangedObjectIndexPath:indexPath];
}
}
How i do this. Any body pls help to resolve this. Thanks in Advance.
I did it. I have did the following code. any one need, use this code.
In first step u need to get Indexpath of item
- (IBAction)RefreshTree:(id)sender {
NSIndexPath *indexPath = nil;
if (![self.treeController selectionIndexPath]) {
indexPath = [NSIndexPath indexPathWithIndex:[contents count]];
}
else {
if ([[[self.treeController selectedObjects] objectAtIndex:0] isLeaf]) {
NSBeep();
NSIndexPath *selectedfiler_indexPath = [[[self.treeController selectedNodes] objectAtIndex:0] indexPath];
[self selectValue:selectedfiler_indexPath];
}
else
{
indexPath = [self.treeController selectionIndexPath];
[self selectValue:indexPath];
}
}
}
- (void) selectValue : (NSIndexPath *) indexpath
{
NSMutableArray *dummyval = [[NSMutableArray alloc] init];
NSTreeNode *firstSelectedNode = [[self.treeController selectedNodes] objectAtIndex:0];
NSString *getsel = [firstSelectedNode representedObject];
[dummyval addObject:getsel];
int i = 0;
NSInteger j = [[firstSelectedNode indexPath]length];
while (i < j) {
firstSelectedNode = [firstSelectedNode parentNode];
if (i < j -1)
{
NSString *st = [firstSelectedNode representedObject];
[dummyval addObject:[NSString stringWithFormat:#"%#",st]];
}
i++;
}
NSArray *reversedArray = [[dummyval reverseObjectEnumerator] allObjects];
NSString *ret_path=[reversedArray componentsJoinedByString:#"/"];
ret_path = [ret_path substringWithRange:NSMakeRange(1, [ret_path length] - 1)];
NSLog("%#",ret_path);
}
Output is : Test/New Folder/Untitled/Project
My iOS app populates an SQLlite database (using FMDB) from a web query. There is a UITableView to display this data. Since I started writing the app the size of this db has exploded to about 10,000 records.
My current design is to load the data in an array from the db and then use that in the UITableView. It works, and I have the alphabetized index on the right hand side of the screen for the user to quickly access the data.
The problem of course is it takes 15-20 seconds to load the array. I originally designed this to load every time the user hits the UITableView, but that means 15-20 seconds every time.
Is there a way to only load some of the data in the UITableView while keeping the search functionality and the index?
Can/should I load the array once and reuse it? I have tried but I can't seem to get that work.
As a last resort, I could switch to CoreData but I really don't want to switch horses in midstream.
UITableView implementation:
#import "ContactViewController.h"
#import "ContactDetailViewController.h"
#interface ContactViewController ()
#end
#implementation ContactViewController {
NSMutableArray *_contacts;
UISearchDisplayController *searchController;
BOOL isSearching;
}
- (void)awakeFromNib {
if ([[UIDevice currentDevice] userInterfaceIdiom] ==
UIUserInterfaceIdiomPad) {
self.clearsSelectionOnViewWillAppear = NO;
self.preferredContentSize = CGSizeMake(320.0, 600.0);
}
[super awakeFromNib];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Get array of employees and sections
_contacts = [ContactsDatabase getContacts];
self.sections = [ContactsDatabase getSections:_contacts];
// Set up Search
self.searchDisplayController.displaysSearchBarInNavigationBar = YES;
self.filteredContacts = [NSMutableArray array];
searchController.delegate = self;
searchController.searchResultsDataSource = self;
isSearching = FALSE;
// iPad
// self.dtailViewController = (detailViewController
// *)[[self.splitViewController.viewControllers lastObject]
// topViewController];
// Set the back bar button
UIBarButtonItem *backButton =
[[UIBarButtonItem alloc] initWithTitle:#"Contacts"
style:UIBarButtonItemStylePlain
target:nil
action:nil];
self.navigationItem.backBarButtonItem = backButton;
}
#pragma mark - Table View
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section {
NSInteger tmpRows;
if (tableView == self.searchDisplayController.searchResultsTableView) {
tmpRows = [self.filteredContacts count];
} else {
tmpRows = [[self.sections
valueForKey:[[[self.sections allKeys]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:section]] count];
}
return tmpRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
if (isSearching) {
contact *thisContact = [self.filteredContacts objectAtIndex:indexPath.row];
cell.textLabel.text = thisContact.cmpNme;
} else {
contact *thisContact = [[self.sections
valueForKey:[[[self.sections allKeys]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:indexPath.section]]
objectAtIndex:indexPath.row];
cell.textLabel.text = thisContact.cmpNme;
}
return cell;
}
#pragma mark - Table Sections
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSInteger tmpCount;
if (isSearching) {
tmpCount = 1;
} else {
tmpCount = [[self.sections allKeys] count];
}
return tmpCount;
}
- (NSString *)tableView:(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section {
NSString *tmpString;
if (tableView == self.searchDisplayController.searchResultsTableView) {
tmpString = nil;
} else {
tmpString = [[[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:section];
}
return tmpString;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showContactDetail"]) {
contact *dtlContact;
if (isSearching) {
dtlContact = [self.filteredContacts
objectAtIndex:self.searchDisplayController.searchResultsTableView
.indexPathForSelectedRow.row];
} else {
dtlContact = [[self.sections
valueForKey:[[[self.sections allKeys]
sortedArrayUsingSelector:
#selector(localizedCaseInsensitiveCompare:)]
objectAtIndex:[self.tableView indexPathForSelectedRow]
.section]]
objectAtIndex:[self.tableView indexPathForSelectedRow].row];
}
self.contactDetailViewController.detailItem = dtlContact;
[[segue destinationViewController] setDetailItem:dtlContact];
}
}
#pragma mark - Right side bar alphabetical index
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
NSArray *tmpTitle;
if (isSearching) {
tmpTitle = nil;
} else {
tmpTitle = [[self.sections allKeys]
sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
return tmpTitle;
}
#pragma mark - Search methods
- (void)searchDisplayControllerWillBeginSearch:
(UISearchDisplayController *)controller {
isSearching = TRUE;
self.searchDisplayController.searchBar.showsCancelButton = YES;
[self.tableView reloadSectionIndexTitles];
}
- (void)searchDisplayControllerDidEndSearch:
(UISearchDisplayController *)controller {
isSearching = FALSE;
self.searchDisplayController.searchBar.showsCancelButton = NO;
[self.tableView reloadSectionIndexTitles];
}
- (void)filterContentForSearchText:(NSString *)searchText
scope:(NSString *)scope {
[self.filteredContacts removeAllObjects];
NSPredicate *predicate =
[NSPredicate predicateWithFormat:#"cmpNme contains[c] %#", searchText];
NSArray *tempArray = [_contacts filteredArrayUsingPredicate:predicate];
// Move to filtered array
self.filteredContacts = [NSMutableArray arrayWithArray:tempArray];
self.sections = [ContactsDatabase getSections:_contacts];
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller
shouldReloadTableForSearchString:(NSString *)searchString {
isSearching = TRUE;
[self
filterContentForSearchText:searchString
scope:[self.searchDisplayController.searchBar
.scopeButtonTitles
objectAtIndex:
self.searchDisplayController.searchBar
.selectedScopeButtonIndex]];
return YES;
}
#end
getContacts methods
+ (NSMutableArray *)getContacts {
id tmpDatabasePath = [(AppDelegate *)
[[UIApplication sharedApplication] delegate] databasePathContacts];
NSMutableArray *tmpContacts;
tmpContacts = [[NSMutableArray alloc] init];
FMDatabase *db = [FMDatabase databaseWithPath:tmpDatabasePath];
[db open];
FMResultSet *results =
[db executeQuery:#"SELECT * FROM contacts ORDER by cmpNme"];
while ([results next]) {
contact *thisContact = [contact new];
thisContact.cmpNme = [results stringForColumn:#"cmpNme"];
thisContact.fstNme = [results stringForColumn:#"fstNme"];
thisContact.lstNme = [results stringForColumn:#"lstNme"];
thisContact.cntTyp = [results stringForColumn:#"cnttyp"];
NSString *tst = [results stringForColumn:#"phnNbr"];
thisContact.phnNbr = [NSNumber numberWithInt:[tst intValue]];
thisContact.adr1 = [results stringForColumn:#"adr1"];
thisContact.adr2 = [results stringForColumn:#"adr2"];
thisContact.cty = [results stringForColumn:#"cty"];
thisContact.ste = [results stringForColumn:#"ste"];
tst = [results stringForColumn:#"zip"];
thisContact.zip = [NSNumber numberWithInt:[tst intValue]];
thisContact.ema = [results stringForColumn:#"ema"];
tst = [results stringForColumn:#"id"];
thisContact.id = [NSNumber numberWithInt:[tst intValue]];
[tmpContacts addObject:thisContact];
}
[db close];
return tmpCon
Wondering if anyone could give an example of how to dowload files for use with this PDF Reader code? I am very new and have been hacking away at it but I think it's time for some experienced eyes. thanks!
//
// 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
}