diff --git a/DemoClasses/Flickr/FlickrSearcgTVC.h b/DemoClasses/Flickr/FlickrSearcgTVC.h new file mode 100644 index 0000000..8614d6c --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearcgTVC.h @@ -0,0 +1,16 @@ +// +// FlickrSearcgTVC.h +// hjlib +// +// Created by markj on 1/5/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import + + +@interface FlickrSearcgTVC : UITableViewController { + +} + +@end diff --git a/DemoClasses/Flickr/FlickrSearcgTVC.m b/DemoClasses/Flickr/FlickrSearcgTVC.m new file mode 100644 index 0000000..01b00f4 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearcgTVC.m @@ -0,0 +1,157 @@ +// +// FlickrSearcgTVC.m +// hjlib +// +// Created by markj on 1/5/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import "FlickrSearcgTVC.h" + + +@implementation FlickrSearcgTVC + +/* +- (id)initWithStyle:(UITableViewStyle)style { + // Override initWithStyle: if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad. + if (self = [super initWithStyle:style]) { + } + return self; +} +*/ + +/* +- (void)viewDidLoad { + [super viewDidLoad]; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; +} +*/ + +/* +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; +} +*/ +/* +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; +} +*/ +/* +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; +} +*/ +/* +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; +} +*/ + +/* +// Override to allow orientations other than the default portrait orientation. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + // Return YES for supported orientations + return (interfaceOrientation == UIInterfaceOrientationPortrait); +} +*/ + +- (void)didReceiveMemoryWarning { + // Releases the view if it doesn't have a superview. + [super didReceiveMemoryWarning]; + + // Release any cached data, images, etc that aren't in use. +} + +- (void)viewDidUnload { + // Release any retained subviews of the main view. + // e.g. self.myOutlet = nil; +} + + +#pragma mark Table view methods + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +// Customize the number of rows in the table view. +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 0; +} + + +// Customize the appearance of table view cells. +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + // Set up the cell... + + return cell; +} + + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + // Navigation logic may go here. Create and push another view controller. + // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil]; + // [self.navigationController pushViewController:anotherViewController]; + // [anotherViewController release]; +} + + +/* +// Override to support conditional editing of the table view. +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the specified item to be editable. + return YES; +} +*/ + + +/* +// Override to support editing the table view. +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Delete the row from the data source + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES]; + } + else if (editingStyle == UITableViewCellEditingStyleInsert) { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } +} +*/ + + +/* +// Override to support rearranging the table view. +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { +} +*/ + + +/* +// Override to support conditional rearranging of the table view. +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the item to be re-orderable. + return YES; +} +*/ + + +- (void)dealloc { + [super dealloc]; +} + + +@end + diff --git a/DemoClasses/Flickr/FlickrSearcgTVC.xib b/DemoClasses/Flickr/FlickrSearcgTVC.xib new file mode 100644 index 0000000..ae61189 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearcgTVC.xib @@ -0,0 +1,471 @@ + + + + 784 + 10C540 + 740 + 1038.25 + 458.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 62 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + + + IBFirstResponder + + + + 292 + + YES + + + 290 + {320, 44} + + NO + 3 + YES + + + + {320, 416} + + + 3 + MQA + + NO + YES + NO + + + NO + + NO + 1 + 0 + YES + 44 + 22 + 22 + + + + + + + YES + + + view + + + + 5 + + + + dataSource + + + + 6 + + + + delegate + + + + 7 + + + + searchBar + + + + 10 + + + + searchDisplayController + + + + 11 + + + + searchContentsController + + + + 12 + + + + searchResultsDataSource + + + + 13 + + + + searchResultsDelegate + + + + 14 + + + + delegate + + + + 15 + + + + delegate + + + + 16 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + YES + + + + + + 8 + + + + + 9 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 4.IBEditorWindowLastContentRect + 4.IBPluginDependency + 8.IBPluginDependency + + + YES + FlickrSearcgTVC + UIResponder + {{692, 217}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 16 + + + + YES + + FlickrSearcgTVC + UITableViewController + + IBProjectSource + Classes/FlickrSearcgTVC.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIResponder + NSObject + + + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UITableView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITableView.h + + + + UITableViewController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITableViewController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ../hjlib.xcodeproj + 3 + 3.1 + + diff --git a/DemoClasses/Flickr/FlickrSearch.h b/DemoClasses/Flickr/FlickrSearch.h new file mode 100644 index 0000000..95f5d77 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearch.h @@ -0,0 +1,28 @@ +// +// FlickrDownload.h +// Postcard +// +// Created by markj on 2/16/09. +// Copyright 2009 Mark Johnson. All rights reserved. +// + +#import + + +@interface FlickrSearch : NSObject { + + NSMutableArray* searchResults; + NSMutableArray* imageURLs; + NSMutableArray* imageTitles; + NSMutableArray* thumbnailViews; + NSMutableArray* owners; + NSXMLParser* parser; + +} + +@property (nonatomic, retain) NSMutableArray* searchResults; + +- (void) imageSearch:(NSString*)searchString; + + +@end diff --git a/DemoClasses/Flickr/FlickrSearch.m b/DemoClasses/Flickr/FlickrSearch.m new file mode 100644 index 0000000..6f45534 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearch.m @@ -0,0 +1,156 @@ +// +// FlickrDownload.m +// Postcard +// +// Created by markj on 2/16/09. +// Copyright 2009 Mark Johnson. All rights reserved. +// + +#import "FlickrSearch.h" + + +@implementation FlickrSearch + +@synthesize searchResults; + + +- (id) init { + [super init]; + imageURLs = [NSMutableArray arrayWithCapacity:100]; + [imageURLs retain]; + imageURLs = [NSMutableArray arrayWithCapacity:100]; + [imageURLs retain]; + imageTitles = [NSMutableArray arrayWithCapacity:100]; + [imageTitles retain]; + thumbnailViews = [NSMutableArray arrayWithCapacity:100]; + [thumbnailViews retain]; + + return self; +} + +- (void) dealloc { + [imageURLs release]; + [imageTitles release]; + [thumbnailViews release]; + [parser release]; + [super dealloc]; + +} + +- (int) numberOfImages { + return [imageURLs count]; +} + +- (void) imageSearch:(NSString*)searchString { + + + [imageURLs removeAllObjects]; + [imageTitles removeAllObjects]; + [thumbnailViews removeAllObjects]; + + NSMutableString* urls = [NSMutableString stringWithCapacity:200]; + [urls appendString:@"http://api.flickr.com/services/rest/?"]; + [urls appendString:@"method=flickr.photos.search&"]; + [urls appendString:@"api_key=c4ee04d591412ab308c95ed9bb1b3c99&"]; + [urls appendString:@"license=7,4,2,1,5&"]; + [urls appendString:@"perPage=40&"]; + [urls appendString:@"media=photos&"]; + [urls appendString:@"text="]; + [urls appendString:[searchString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; + + NSURL* url = [NSURL URLWithString:urls]; + //NSLog(@"URL: %@",url); + + //NSURLRequest* request = [NSURLRequest requestWithURL:url]; + //NSURLResponse* response; + //NSError* error; + //NSData* replyData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; + //NSString* replyString = [[NSString alloc] initWithBytes:[replyData bytes] length:[replyData length] encoding:NSUTF8StringEncoding]; + //NSLog(@"reply: %@",replyString); + //[replyString release]; + + + self.searchResults = [[[NSMutableArray alloc] initWithCapacity:100] autorelease]; + parser = [[NSXMLParser alloc] initWithContentsOfURL:url]; + [parser setDelegate:self]; + [parser parse]; +} + + +- (void) appendToURLString:(NSMutableString*)url urlParam:(NSString*)param forKey:(NSString*)key fromDict:(NSDictionary*)dict { + + [url appendString:param]; + [url appendString:@"="]; + [url appendString:[dict objectForKey:key]]; + [url appendString:@"&"]; +} + +- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName + namespaceURI:(NSString *)namespaceURI + qualifiedName:(NSString *)qualifiedName + attributes:(NSDictionary *)attributeDict { + + if ([elementName isEqualToString:@"photo"]) { + [searchResults addObject:attributeDict]; + } + + /* + NSString* title=[attributeDict objectForKey:@"title"]; + NSString* owner=[attributeDict objectForKey:@"owner"]; + + [imageTitles addObject:title]; + NSMutableString* url = [NSMutableString stringWithString:@"http://farm"]; + [url appendString:[attributeDict objectForKey:@"farm"]]; + [url appendString:@".static.flickr.com/"]; + [url appendString:[attributeDict objectForKey:@"server"]]; + [url appendString:@"/"]; + [url appendString:[attributeDict objectForKey:@"id"]]; + [url appendString:@"_"]; + [url appendString:[attributeDict objectForKey:@"secret"]]; + [imageURLs addObject:url]; + + UIView* view = [[[UIView alloc] init] autorelease]; + view.tag=999; + //CGRect rect = CGRectMake(0.0, 0.0, 320.0, 150); + //view.bounds=rect; + //view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; + + [thumbnailViews addObject:view]; + */ + +} + + +- (NSURL*)thumbnailURLAtIndex:(int)index { + NSMutableString* urls = [NSMutableString stringWithString:[imageURLs objectAtIndex:index]]; + [urls appendString:@"_s.jpg"]; + NSURL* url = [NSURL URLWithString:urls]; + return url; +} + +- (NSURL*)imageURLAtIndex:(int)index { + NSMutableString* urls = [NSMutableString stringWithString:[imageURLs objectAtIndex:index]]; + [urls appendString:@".jpg"]; + NSURL* url = [NSURL URLWithString:urls]; + return url; +} + +- (NSData*)loadThumbnailDataAtIndex:(int)index { + NSMutableString* urls = [NSMutableString stringWithString:[imageURLs objectAtIndex:index]]; + [urls appendString:@"_s.jpg"]; + NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urls]]; + return data; +} + +- (UIImage*)loadThumbnailImageAtIndex:(int)index { + return [UIImage imageWithData:[self loadThumbnailDataAtIndex:index]]; +} + +- (UIView*)thumbnailViewAtIndex:(int)index { + return [thumbnailViews objectAtIndex:index]; +} + + + + +@end diff --git a/DemoClasses/Flickr/FlickrSearchRes.h b/DemoClasses/Flickr/FlickrSearchRes.h new file mode 100644 index 0000000..2c1f592 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearchRes.h @@ -0,0 +1,25 @@ +// +// FlickrPhoto.h +// hjlib +// +// Created by markj on 1/5/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import + + +@interface FlickrSearchRes : NSObject { + +} + ++(NSString*)photoId:(NSDictionary*)searchRes; ++(NSString*)ownerId:(NSDictionary*)searchRes; ++(NSString*)title:(NSDictionary*)searchRes; ++(NSString*)imageUrlBase:(NSDictionary*)searchRes; ++(NSString*)image75pxUrl:(NSDictionary*)searchRes; ++(NSString*)image500pxUrl:(NSDictionary*)searchRes; ++(NSString*)ownerImageURL:(NSDictionary*)searchRes; + + +@end diff --git a/DemoClasses/Flickr/FlickrSearchRes.m b/DemoClasses/Flickr/FlickrSearchRes.m new file mode 100644 index 0000000..5adc5df --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearchRes.m @@ -0,0 +1,62 @@ +// +// FlickrPhoto.m +// hjlib +// +// Created by markj on 1/5/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import "FlickrSearchRes.h" + + +@implementation FlickrSearchRes + ++(NSString*)photoId:(NSDictionary*)searchRes { + return [searchRes objectForKey:@"id"]; +} + ++(NSString*)ownerId:(NSDictionary*)searchRes { + return [searchRes objectForKey:@"owner"]; +} + ++(NSString*)title:(NSDictionary*)searchRes { + return [searchRes objectForKey:@"title"]; +} + ++(NSString*)imageUrlBase:(NSDictionary*)searchRes { + NSMutableString* url = [NSMutableString stringWithString:@"http://farm"]; + [url appendString:[searchRes objectForKey:@"farm"]]; + [url appendString:@".static.flickr.com/"]; + [url appendString:[searchRes objectForKey:@"server"]]; + [url appendString:@"/"]; + [url appendString:[searchRes objectForKey:@"id"]]; + [url appendString:@"_"]; + [url appendString:[searchRes objectForKey:@"secret"]]; + return url; +} + ++(NSString*)image75pxUrl:(NSDictionary*)searchRes { + return [NSString stringWithFormat:@"%@_s.jpg",[FlickrSearchRes imageUrlBase:searchRes]]; +} + ++(NSString*)image500pxUrl:(NSDictionary*)searchRes { + return [NSString stringWithFormat:@"%@.jpg",[FlickrSearchRes imageUrlBase:searchRes]]; +} + + ++(NSString*)ownerImageURL:(NSDictionary*)searchRes { + NSMutableString* url = [NSMutableString stringWithString:@"http://farm"]; + [url appendString:[searchRes objectForKey:@"farm"]]; + [url appendString:@".static.flickr.com/"]; + [url appendString:[searchRes objectForKey:@"server"]]; + [url appendString:@"/"]; + [url appendString:[searchRes objectForKey:@"buddyicons"]]; + [url appendString:@"/"]; + [url appendString:[searchRes objectForKey:@"owner"]]; + [url appendString:@".jpg"]; + return url; +} + + + +@end diff --git a/DemoClasses/Flickr/FlickrSearchTVC.h b/DemoClasses/Flickr/FlickrSearchTVC.h new file mode 100644 index 0000000..7f3a6e3 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearchTVC.h @@ -0,0 +1,24 @@ +// +// FlickrSearchTVC.h +// hjlib +// +// Created by markj on 1/5/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import +#include "FlickrSearch.h" +#import "HJObjManager.h" + + +@interface FlickrSearchTVC : UITableViewController { + + FlickrSearch* flickrSearch; + //UISearchContentsController* searchController; + + HJObjManager* objMan; +} + +@property (nonatomic, retain) FlickrSearch* flickrSearch; + +@end diff --git a/DemoClasses/Flickr/FlickrSearchTVC.m b/DemoClasses/Flickr/FlickrSearchTVC.m new file mode 100644 index 0000000..6143fd4 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearchTVC.m @@ -0,0 +1,114 @@ +// +// FlickrSearchTVC.m +// hjlib +// +// Created by markj on 1/5/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import "FlickrSearchTVC.h" +#import "FlickrSearchRes.h" +#import "HJObjManager.h" +#import "HJManagedImageV.h" + + +@implementation FlickrSearchTVC + +@synthesize flickrSearch; + + +- (void)viewDidLoad { + [super viewDidLoad]; + self.flickrSearch = [[[FlickrSearch alloc] init] autorelease]; + self.tableView.rowHeight = 80; + + // Create the object manager + objMan = [[HJObjManager alloc] init]; + + // Create a file cache for the object manager to use + // A real app might do this durring startup, allowing the object manager and cache to be shared by several screens + NSString* cacheDirectory = [NSHomeDirectory() stringByAppendingString:@"/Library/Caches/imgcache/flickr/"] ; + HJMOFileCache* fileCache = [[[HJMOFileCache alloc] initWithRootPath:cacheDirectory] autorelease]; + objMan.fileCache = fileCache; + + // Have the file cache trim itself down to a size & age limit, so it doesn't grow forever + fileCache.fileCountLimit = 100; + fileCache.fileAgeLimit = 60*60*24*7; //1 week + [fileCache trimCacheUsingBackgroundThread]; + +} + + +- (void)dealloc { + [objMan release]; + [super dealloc]; +} + + + +#pragma mark Table view methods + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +// Customize the number of rows in the table view. +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + int n = [flickrSearch.searchResults count]; + return n; +} + + +// Customize the appearance of table view cells. +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + HJManagedImageV* mi; + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + + //Create a managed image view and add it to the cell (layout is very naieve) + mi = [[[HJManagedImageV alloc] initWithFrame:CGRectMake(243,2,75,75)] autorelease]; + mi.tag = 999; + [cell addSubview:mi]; + + } else { + //Get a reference to the managed image view that was already in the recycled cell, and clear it + mi = (HJManagedImageV*)[cell viewWithTag:999]; + [mi clear]; + } + + NSDictionary* searchRes = [flickrSearch.searchResults objectAtIndex:indexPath.row]; + NSString* title = [FlickrSearchRes title:searchRes]; + cell.textLabel.text = title; + + //set the URL that we want the managed image view to load + mi.url = [NSURL URLWithString:[FlickrSearchRes image75pxUrl:searchRes]]; + + //tell the object manager to manage the managed image view, + //this causes the cached image to display, or the image to be loaded, cached, and displayed + [objMan manage:mi]; + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + NSLog(@"didSelectRow"); +} + + + +- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { + [searchBar resignFirstResponder]; + [flickrSearch imageSearch:searchBar.text]; + //[searchBar.searchContentsController setActive:NO animated:YES]; + [self.tableView reloadData]; +} + + + + +@end + diff --git a/DemoClasses/Flickr/FlickrSearchTVC.xib b/DemoClasses/Flickr/FlickrSearchTVC.xib new file mode 100644 index 0000000..841e801 --- /dev/null +++ b/DemoClasses/Flickr/FlickrSearchTVC.xib @@ -0,0 +1,414 @@ + + + + 784 + 10C540 + 740 + 1038.25 + 458.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 62 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + + + IBFirstResponder + + + + 292 + + YES + + + 290 + {320, 44} + + NO + 3 + YES + + + + {320, 460} + + + 3 + MQA + + NO + YES + NO + + NO + 1 + 0 + YES + 44 + 22 + 22 + + + + + + YES + + + view + + + + 5 + + + + dataSource + + + + 6 + + + + delegate + + + + 7 + + + + delegate + + + + 16 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + YES + + + + + + 8 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 4.IBEditorWindowLastContentRect + 4.IBPluginDependency + 8.IBPluginDependency + + + YES + FlickrSearchTVC + UIResponder + {{671, 504}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 16 + + + + YES + + FlickrSearchTVC + UITableViewController + + IBProjectSource + Classes/FlickrSearchTVC.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIResponder + NSObject + + + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UITableView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITableView.h + + + + UITableViewController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITableViewController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ../hjlib.xcodeproj + 3 + 3.1 + + diff --git a/DemoClasses/HJCacheAppDelegate.h b/DemoClasses/HJCacheAppDelegate.h new file mode 100644 index 0000000..dc1328c --- /dev/null +++ b/DemoClasses/HJCacheAppDelegate.h @@ -0,0 +1,21 @@ +// +// HJCacheAppDelegate.h +// HJCache +// +// Created by Mark Johnson on 1/15/11. +// Copyright 2011 na. All rights reserved. +// + +#import + +@interface HJCacheAppDelegate : NSObject { + + UIWindow *window; + UINavigationController *navigationController; +} + +@property (nonatomic, retain) IBOutlet UIWindow *window; +@property (nonatomic, retain) IBOutlet UINavigationController *navigationController; + +@end + diff --git a/DemoClasses/HJCacheAppDelegate.m b/DemoClasses/HJCacheAppDelegate.m new file mode 100644 index 0000000..e3c6845 --- /dev/null +++ b/DemoClasses/HJCacheAppDelegate.m @@ -0,0 +1,109 @@ +// +// HJCacheAppDelegate.m +// HJCache +// +// Created by Mark Johnson on 1/15/11. +// Copyright 2011 na. All rights reserved. +// + +#import "HJCacheAppDelegate.h" +#import "RootViewController.h" +#import "FlickrSearchTVC.h" +#import "HJCircularBuffer.h" +#import "HJWeakMutableArray.h" +#import "ImgTVC.h" + + +@implementation HJCacheAppDelegate + +@synthesize window; +@synthesize navigationController; + + +#pragma mark - +#pragma mark Application lifecycle + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + + + //[HJCircularBuffer test]; + //[HJWeakMutableArray test]; + + //************************************************************* + // uncomment one of the view controllers below to demo HJManObj + + // this simple demo shows managed images being used to load, cache, and show images from Flickr + FlickrSearchTVC* flickrTVC = [[[FlickrSearchTVC alloc] initWithNibName:@"FlickrSearchTVC" + bundle:nil] autorelease]; + navigationController = [[UINavigationController alloc] initWithRootViewController:flickrTVC]; + + // this simple demo shows how managed images can be shared and reused in the same table + //ImgTVC* imgTVC = [[[ImgTVC alloc] initWithNibName:@"ImgTVC" bundle:nil] autorelease]; + //navigationController = [[UINavigationController alloc] initWithRootViewController:imgTVC]; + + //************************************************************* + + [window addSubview:navigationController.view]; + [window makeKeyAndVisible]; + + return YES; +} + + +- (void)applicationWillResignActive:(UIApplication *)application { + /* + Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. + Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + */ +} + + +- (void)applicationDidEnterBackground:(UIApplication *)application { + /* + Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. + If your application supports background execution, called instead of applicationWillTerminate: when the user quits. + */ +} + + +- (void)applicationWillEnterForeground:(UIApplication *)application { + /* + Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background. + */ +} + + +- (void)applicationDidBecomeActive:(UIApplication *)application { + /* + Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. + */ +} + + +- (void)applicationWillTerminate:(UIApplication *)application { + /* + Called when the application is about to terminate. + See also applicationDidEnterBackground:. + */ +} + + +#pragma mark - +#pragma mark Memory management + +- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { + /* + Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later. + */ +} + + +- (void)dealloc { + [navigationController release]; + [window release]; + [super dealloc]; +} + + +@end + diff --git a/DemoClasses/ImageTable/Content.h b/DemoClasses/ImageTable/Content.h new file mode 100644 index 0000000..c59ec89 --- /dev/null +++ b/DemoClasses/ImageTable/Content.h @@ -0,0 +1,33 @@ +// +// Content.h +// hjlib +// +// Created by markj on 1/25/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import + + + + +@interface Content : NSObject { + + NSString* contentID; + NSString* text; + NSURL* imgURL; + NSString* imgID; + + +} + +@property (nonatomic, retain) NSString* contentID; +@property (nonatomic, retain) NSString* text; +@property (nonatomic, retain) NSURL* imgURL; +@property (nonatomic, retain) NSString* imgID; + + ++(Content*) makeNextContent; + + +@end diff --git a/DemoClasses/ImageTable/Content.m b/DemoClasses/ImageTable/Content.m new file mode 100644 index 0000000..183c794 --- /dev/null +++ b/DemoClasses/ImageTable/Content.m @@ -0,0 +1,40 @@ +// +// Content.m +// hjlib +// +// Created by markj on 1/25/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import "Content.h" + + +@implementation Content + +@synthesize contentID, text, imgURL, imgID; + +static int nextContentID = 0; + + ++(Content*) makeNextContent { + + nextContentID++; + int imgNum = (rand()%3); + //NSLog(@"imgNum %i",imgNum); + + Content* c = [[[Content alloc] init] autorelease]; + c.contentID = [NSString stringWithFormat:@"%i",nextContentID]; + c.text = [NSString stringWithFormat:@"Content %@ img %i",c.contentID, imgNum]; + c.imgID = [NSString stringWithFormat:@"%i",imgNum]; + + NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:[NSString stringWithFormat:@"%i.png",imgNum]]; + NSURL* url = [NSURL fileURLWithPath:path]; + + c.imgURL = url; + + return c; +} + + + +@end diff --git a/DemoClasses/ImageTable/ImgCell.h b/DemoClasses/ImageTable/ImgCell.h new file mode 100644 index 0000000..be80732 --- /dev/null +++ b/DemoClasses/ImageTable/ImgCell.h @@ -0,0 +1,24 @@ +// +// ImgCell.h +// hjlib +// +// Created by markj on 1/25/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import +#import "HJManagedImageV.h" + + +@interface ImgCell : UITableViewCell { + + IBOutlet UILabel* text1; + IBOutlet HJManagedImageV* img; + +} + +@property (nonatomic, retain) UILabel* text1; +@property (nonatomic, retain) HJManagedImageV* img; + + +@end diff --git a/DemoClasses/ImageTable/ImgCell.m b/DemoClasses/ImageTable/ImgCell.m new file mode 100644 index 0000000..7b0b4f1 --- /dev/null +++ b/DemoClasses/ImageTable/ImgCell.m @@ -0,0 +1,16 @@ +// +// ImgCell.m +// hjlib +// +// Created by markj on 1/25/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import "ImgCell.h" + + +@implementation ImgCell + +@synthesize text1, img; + +@end diff --git a/DemoClasses/ImageTable/ImgCell.xib b/DemoClasses/ImageTable/ImgCell.xib new file mode 100644 index 0000000..996ec2d --- /dev/null +++ b/DemoClasses/ImageTable/ImgCell.xib @@ -0,0 +1,428 @@ + + + + 784 + 10C540 + 740 + 1038.25 + 458.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 62 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + + + IBFirstResponder + + + + 292 + + YES + + + 256 + + YES + + + 292 + {{1, 1}, {42, 42}} + + + 3 + MQA + + 2 + + + NO + + + + 292 + {{57, 2}, {226, 21}} + + NO + YES + NO + Label + + 1 + MCAwIDAAA + + + 1 + 10 + + + {320, 43} + + + 3 + MCAwAA + + NO + YES + 4 + YES + + + {320, 44} + + + 1 + MSAxIDEAA + + NO + 1 + + ImgCell + + + + + YES + + + img + + + + 6 + + + + text1 + + + + 7 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 3 + + + YES + + + + + + + 4 + + + + + 5 + + + + + + + YES + + YES + -2.CustomClassName + 3.CustomClassName + 3.IBEditorWindowLastContentRect + 3.IBPluginDependency + 4.IBPluginDependency + 5.CustomClassName + 5.IBPluginDependency + + + YES + UIResponder + ImgCell + {{734, 790}, {320, 44}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + HJManagedImageV + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 7 + + + + YES + + HJManagedImageV + UIView + + YES + + YES + callbackOnCancel + callbackOnSetImage + oid + + + YES + id + id + id + + + + IBProjectSource + Classes/HJManagedImageV.h + + + + ImgCell + UITableViewCell + + YES + + YES + img + text1 + + + YES + HJManagedImageV + UILabel + + + + IBProjectSource + Classes/ImgCell.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UILabel + UIView + + IBFrameworkSource + UIKit.framework/Headers/UILabel.h + + + + UIResponder + NSObject + + + + UITableViewCell + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITableViewCell.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + ../hjlib.xcodeproj + 3 + 3.1 + + diff --git a/DemoClasses/ImageTable/ImgTVC.h b/DemoClasses/ImageTable/ImgTVC.h new file mode 100644 index 0000000..f8f3efa --- /dev/null +++ b/DemoClasses/ImageTable/ImgTVC.h @@ -0,0 +1,23 @@ +// +// ImgTVC.h +// hjlib +// +// Created by markj on 1/25/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import +#import "HJObjManager.h" + + +@interface ImgTVC : UITableViewController { + + NSMutableArray* content; + HJObjManager* imgMan; + +} + +@property (nonatomic, retain) NSMutableArray* content; +@property (nonatomic, retain) HJObjManager* imgMan; + +@end diff --git a/DemoClasses/ImageTable/ImgTVC.m b/DemoClasses/ImageTable/ImgTVC.m new file mode 100644 index 0000000..46ac69f --- /dev/null +++ b/DemoClasses/ImageTable/ImgTVC.m @@ -0,0 +1,89 @@ +// +// ImgTVC.m +// hjlib +// +// Created by markj on 1/25/10. +// Copyright 2010 Mark Johnson. All rights reserved. +// + +#import "ImgTVC.h" +#import "Content.h" +#import "ImgCell.h" +#import "HJMOFileCache.h" + + +@implementation ImgTVC + +@synthesize content, imgMan; + + + +-(void) viewDidLoad { + self.imgMan = [[[HJObjManager alloc] init] autorelease]; + NSString* cacheDirectory = [NSHomeDirectory() stringByAppendingString:@"/Library/Caches/imgcache/imgtable/"] ; + HJMOFileCache* fileCache = [[[HJMOFileCache alloc] initWithRootPath:cacheDirectory] autorelease]; + self.imgMan.fileCache = fileCache; +} + +#pragma mark Table view methods + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +// Customize the number of rows in the table view. +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + int rows = 20; + + if (self.content==nil) { + self.content = [NSMutableArray arrayWithCapacity:rows]; + for (int i=0; i + + + 784 + 10A394 + 732 + 1027.1 + 430.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 60 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + + + IBFirstResponder + + + + 292 + {320, 460} + + + 3 + MQA + + NO + YES + NO + + NO + 1 + 0 + YES + 44 + 22 + 22 + + + + + YES + + + view + + + + 5 + + + + dataSource + + + + 6 + + + + delegate + + + + 7 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 4 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 4.IBEditorWindowLastContentRect + 4.IBPluginDependency + + + YES + ImgTVC + UIResponder + {{329, 504}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 7 + + + + YES + + ImgTVC + UIViewController + + IBProjectSource + ImgTVC.h + + + + + 0 + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + + 3 + 3.1 + + diff --git a/DemoClasses/RootViewController.h b/DemoClasses/RootViewController.h new file mode 100644 index 0000000..14b490e --- /dev/null +++ b/DemoClasses/RootViewController.h @@ -0,0 +1,14 @@ +// +// RootViewController.h +// HJCache +// +// Created by Mark Johnson on 1/15/11. +// Copyright 2011 na. All rights reserved. +// + +#import + +@interface RootViewController : UITableViewController { +} + +@end diff --git a/DemoClasses/RootViewController.m b/DemoClasses/RootViewController.m new file mode 100644 index 0000000..e20efef --- /dev/null +++ b/DemoClasses/RootViewController.m @@ -0,0 +1,165 @@ +// +// RootViewController.m +// HJCache +// +// Created by Mark Johnson on 1/15/11. +// Copyright 2011 na. All rights reserved. +// + +#import "RootViewController.h" + + +@implementation RootViewController + + +#pragma mark - +#pragma mark View lifecycle + +/* +- (void)viewDidLoad { + [super viewDidLoad]; + + // Uncomment the following line to display an Edit button in the navigation bar for this view controller. + // self.navigationItem.rightBarButtonItem = self.editButtonItem; +} +*/ + +/* +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; +} +*/ +/* +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; +} +*/ +/* +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; +} +*/ +/* +- (void)viewDidDisappear:(BOOL)animated { + [super viewDidDisappear:animated]; +} +*/ + +/* + // Override to allow orientations other than the default portrait orientation. +- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { + // Return YES for supported orientations. + return (interfaceOrientation == UIInterfaceOrientationPortrait); +} + */ + + +#pragma mark - +#pragma mark Table view data source + +// Customize the number of sections in the table view. +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + + +// Customize the number of rows in the table view. +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return 0; +} + + +// Customize the appearance of table view cells. +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + + static NSString *CellIdentifier = @"Cell"; + + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; + } + + // Configure the cell. + + return cell; +} + + +/* +// Override to support conditional editing of the table view. +- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the specified item to be editable. + return YES; +} +*/ + + +/* +// Override to support editing the table view. +- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { + + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Delete the row from the data source. + [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + } + else if (editingStyle == UITableViewCellEditingStyleInsert) { + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. + } +} +*/ + + +/* +// Override to support rearranging the table view. +- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { +} +*/ + + +/* +// Override to support conditional rearranging of the table view. +- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { + // Return NO if you do not want the item to be re-orderable. + return YES; +} +*/ + + +#pragma mark - +#pragma mark Table view delegate + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + + /* + <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil]; + // ... + // Pass the selected object to the new view controller. + [self.navigationController pushViewController:detailViewController animated:YES]; + [detailViewController release]; + */ +} + + +#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)viewDidUnload { + // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. + // For example: self.myOutlet = nil; +} + + +- (void)dealloc { + [super dealloc]; +} + + +@end + diff --git a/HJCache-Info.plist b/HJCache-Info.plist new file mode 100644 index 0000000..3289444 --- /dev/null +++ b/HJCache-Info.plist @@ -0,0 +1,30 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIconFile + + CFBundleIdentifier + com.yourcompany.${PRODUCT_NAME:rfc1034identifier} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + NSMainNibFile + MainWindow + + diff --git a/HJCache.xcodeproj/markj.pbxuser b/HJCache.xcodeproj/markj.pbxuser new file mode 100644 index 0000000..0bacae4 --- /dev/null +++ b/HJCache.xcodeproj/markj.pbxuser @@ -0,0 +1,205 @@ +// !$*UTF8*$! +{ + 1D3623240D0F684500981E51 /* HJCacheAppDelegate.h */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {808, 485}}"; + sepNavSelRange = "{278, 20}"; + sepNavVisRange = "{0, 452}"; + }; + }; + 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {2244, 1728}}"; + sepNavSelRange = "{991, 0}"; + sepNavVisRange = "{394, 1135}"; + }; + }; + 1D6058900D05DD3D006BFB54 /* HJCache */ = { + activeExec = 0; + executables = ( + DD1DED2D12E288B1004C00BD /* HJCache */, + ); + }; + 29B97313FDCFA39411CA2CEA /* Project object */ = { + activeBuildConfigurationName = Debug; + activeExecutable = DD1DED2D12E288B1004C00BD /* HJCache */; + activeTarget = 1D6058900D05DD3D006BFB54 /* HJCache */; + addToTargets = ( + 1D6058900D05DD3D006BFB54 /* HJCache */, + ); + codeSenseManager = DD1DED3F12E288B7004C00BD /* Code sense */; + executables = ( + DD1DED2D12E288B1004C00BD /* HJCache */, + ); + perUserDictionary = { + PBXConfiguration.PBXFileTableDataSource3.PBXFileTableDataSource = { + PBXFileTableDataSourceColumnSortingDirectionKey = "-1"; + PBXFileTableDataSourceColumnSortingKey = PBXFileDataSource_Filename_ColumnID; + PBXFileTableDataSourceColumnWidthsKey = ( + 20, + 485, + 20, + 52, + 43, + 43, + 20, + ); + PBXFileTableDataSourceColumnsKey = ( + PBXFileDataSource_FiletypeID, + PBXFileDataSource_Filename_ColumnID, + PBXFileDataSource_Built_ColumnID, + PBXFileDataSource_ObjectSize_ColumnID, + PBXFileDataSource_Errors_ColumnID, + PBXFileDataSource_Warnings_ColumnID, + PBXFileDataSource_Target_ColumnID, + ); + }; + PBXPerProjectTemplateStateSaveDate = 316836243; + PBXWorkspaceStateSaveDate = 316836243; + }; + perUserProjectItems = { + DD1DEDB312E2B8CE004C00BD /* PBXTextBookmark */ = DD1DEDB312E2B8CE004C00BD /* PBXTextBookmark */; + DD1DEDB412E2B8CE004C00BD /* PBXTextBookmark */ = DD1DEDB412E2B8CE004C00BD /* PBXTextBookmark */; + DD1DEDB512E2B8CE004C00BD /* PBXTextBookmark */ = DD1DEDB512E2B8CE004C00BD /* PBXTextBookmark */; + DD1DEDB612E2B8CE004C00BD /* PBXTextBookmark */ = DD1DEDB612E2B8CE004C00BD /* PBXTextBookmark */; + DD1DEDB712E2B8CE004C00BD /* XCBuildMessageTextBookmark */ = DD1DEDB712E2B8CE004C00BD /* XCBuildMessageTextBookmark */; + DD1DEDB812E2B8CE004C00BD /* PBXTextBookmark */ = DD1DEDB812E2B8CE004C00BD /* PBXTextBookmark */; + DD1DEDD112E2B97D004C00BD /* PBXTextBookmark */ = DD1DEDD112E2B97D004C00BD /* PBXTextBookmark */; + }; + sourceControlManager = DD1DED3E12E288B7004C00BD /* Source Control */; + userBuildSettings = { + }; + }; + DD1DED2D12E288B1004C00BD /* HJCache */ = { + isa = PBXExecutable; + activeArgIndices = ( + ); + argumentStrings = ( + ); + autoAttachOnCrash = 1; + breakpointsEnabled = 0; + configStateDict = { + }; + customDataFormattersEnabled = 1; + dataTipCustomDataFormattersEnabled = 1; + dataTipShowTypeColumn = 1; + dataTipSortType = 0; + debuggerPlugin = GDBDebugging; + disassemblyDisplayState = 0; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + executableSystemSymbolLevel = 0; + executableUserSymbolLevel = 0; + libgmallocEnabled = 0; + name = HJCache; + showTypeColumn = 0; + sourceDirectories = ( + ); + }; + DD1DED3E12E288B7004C00BD /* Source Control */ = { + isa = PBXSourceControlManager; + fallbackIsa = XCSourceControlManager; + isSCMEnabled = 0; + scmConfiguration = { + repositoryNamesForRoots = { + "" = ""; + }; + }; + }; + DD1DED3F12E288B7004C00BD /* Code sense */ = { + isa = PBXCodeSenseManager; + indexTemplatePath = ""; + }; + DD1DED7312E28A52004C00BD /* LICENSE */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {834, 560}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 574}"; + }; + }; + DD1DED7412E28A52004C00BD /* README */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {860, 184}}"; + sepNavSelRange = "{0, 0}"; + sepNavVisRange = "{0, 595}"; + }; + }; + DD1DED7C12E28B37004C00BD /* FlickrSearch.m */ = { + uiCtxt = { + sepNavIntBoundsRect = "{{0, 0}, {1132, 2448}}"; + sepNavSelRange = "{2062, 0}"; + sepNavVisRange = "{1890, 378}"; + }; + }; + DD1DEDB312E2B8CE004C00BD /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = DD1DED7312E28A52004C00BD /* LICENSE */; + name = "LICENSE: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 574; + vrLoc = 0; + }; + DD1DEDB412E2B8CE004C00BD /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = DD1DED7412E28A52004C00BD /* README */; + name = "README: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 595; + vrLoc = 0; + }; + DD1DEDB512E2B8CE004C00BD /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = DD1DED7C12E28B37004C00BD /* FlickrSearch.m */; + name = "FlickrSearch.m: 75"; + rLen = 0; + rLoc = 2062; + rType = 0; + vrLen = 378; + vrLoc = 1890; + }; + DD1DEDB612E2B8CE004C00BD /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1D3623240D0F684500981E51 /* HJCacheAppDelegate.h */; + name = "HJCacheAppDelegate.h: 14"; + rLen = 20; + rLoc = 278; + rType = 0; + vrLen = 452; + vrLoc = 0; + }; + DD1DEDB712E2B8CE004C00BD /* XCBuildMessageTextBookmark */ = { + isa = PBXTextBookmark; + comments = "'navVC' undeclared (first use in this function)"; + fRef = 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */; + fallbackIsa = XCBuildMessageTextBookmark; + rLen = 1; + rLoc = 45; + rType = 1; + }; + DD1DEDB812E2B8CE004C00BD /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */; + name = "HJCacheAppDelegate.m: 42"; + rLen = 0; + rLoc = 1268; + rType = 0; + vrLen = 1205; + vrLoc = 394; + }; + DD1DEDD112E2B97D004C00BD /* PBXTextBookmark */ = { + isa = PBXTextBookmark; + fRef = 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */; + name = "HJCacheAppDelegate.m: 38"; + rLen = 0; + rLoc = 991; + rType = 0; + vrLen = 1135; + vrLoc = 394; + }; +} diff --git a/HJCache.xcodeproj/markj.perspectivev3 b/HJCache.xcodeproj/markj.perspectivev3 new file mode 100644 index 0000000..068f503 --- /dev/null +++ b/HJCache.xcodeproj/markj.perspectivev3 @@ -0,0 +1,1490 @@ + + + + + ActivePerspectiveName + Project + AllowedModules + + + BundleLoadPath + + MaxInstances + n + Module + PBXSmartGroupTreeModule + Name + Groups and Files Outline View + + + BundleLoadPath + + MaxInstances + n + Module + PBXNavigatorGroup + Name + Editor + + + BundleLoadPath + + MaxInstances + n + Module + XCTaskListModule + Name + Task List + + + BundleLoadPath + + MaxInstances + n + Module + XCDetailModule + Name + File and Smart Group Detail Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXBuildResultsModule + Name + Detailed Build Results Viewer + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXProjectFindModule + Name + Project Batch Find Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCProjectFormatConflictsModule + Name + Project Format Conflicts List + + + BundleLoadPath + + MaxInstances + n + Module + PBXBookmarksModule + Name + Bookmarks Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXClassBrowserModule + Name + Class Browser + + + BundleLoadPath + + MaxInstances + n + Module + PBXCVSModule + Name + Source Code Control Tool + + + BundleLoadPath + + MaxInstances + n + Module + PBXDebugBreakpointsModule + Name + Debug Breakpoints Tool + + + BundleLoadPath + + MaxInstances + n + Module + XCDockableInspector + Name + Inspector + + + BundleLoadPath + + MaxInstances + n + Module + PBXOpenQuicklyModule + Name + Open Quickly Tool + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugSessionModule + Name + Debugger + + + BundleLoadPath + + MaxInstances + 1 + Module + PBXDebugCLIModule + Name + Debug Console + + + BundleLoadPath + + MaxInstances + n + Module + XCSnapshotModule + Name + Snapshots Tool + + + BundlePath + /Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources + Description + AIODescriptionKey + DockingSystemVisible + + Extension + perspectivev3 + FavBarConfig + + PBXProjectModuleGUID + DD1DED3D12E288B7004C00BD + XCBarModuleItemNames + + XCBarModuleItems + + + FirstTimeWindowDisplayed + + Identifier + com.apple.perspectives.project.defaultV3 + MajorVersion + 34 + MinorVersion + 0 + Name + All-In-One + Notifications + + OpenEditors + + PerspectiveWidths + + -1 + -1 + + Perspectives + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + action + NSToolbarFlexibleSpaceItem + servicesModuleRefactoring + debugger-fix-and-continue + clean + build + debugger-enable-breakpoints + build-and-go + com.apple.ide.PBXToolbarStopButton + servicesModulebuild + get-info + servicesModuleclasses + NSToolbarFlexibleSpaceItem + com.apple.pbx.toolbar.searchfield + + ControllerClassBaseName + + IconName + WindowOfProject + Identifier + perspective.project + IsVertical + + Layout + + + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C37FBAC04509CD000000102 + 1C37FAAC04509CD000000102 + 1C37FABC05509CD000000102 + 1C37FABC05539CD112110102 + E2644B35053B69B200211256 + 1C37FABC04509CD000100104 + 1CC0EA4004350EF90044410B + 1CC0EA4004350EF90041110B + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CA23ED40692098700951B8B + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + yes + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 211 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 29B97314FDCFA39411CA2CEA + 080E96DDFE201D6D7F000001 + 29B97317FDCFA39411CA2CEA + 19C28FACFE9D520D11CA2CBB + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 10 + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {211, 707}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + + + GeometryConfiguration + + Frame + {{0, 0}, {228, 725}} + GroupTreeTableConfiguration + + MainColumn + 211 + + RubberWindowFrame + 551 233 1090 766 0 0 1680 1028 + + Module + PBXSmartGroupTreeModule + Proportion + 228pt + + + Dock + + + BecomeActive + + ContentConfiguration + + PBXProjectModuleGUID + DD1DED3812E288B7004C00BD + PBXProjectModuleLabel + HJCacheAppDelegate.m + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + DD1DED3912E288B7004C00BD + PBXProjectModuleLabel + HJCacheAppDelegate.m + _historyCapacity + 0 + bookmark + DD1DEDD112E2B97D004C00BD + history + + DD1DEDB312E2B8CE004C00BD + DD1DEDB412E2B8CE004C00BD + DD1DEDB512E2B8CE004C00BD + DD1DEDB612E2B8CE004C00BD + DD1DEDB712E2B8CE004C00BD + + + SplitCount + 1 + + StatusBarVisibility + + XCSharingToken + com.apple.Xcode.CommonNavigatorGroupSharingToken + + GeometryConfiguration + + Frame + {{0, 0}, {857, 517}} + RubberWindowFrame + 551 233 1090 766 0 0 1680 1028 + + Module + PBXNavigatorGroup + Proportion + 517pt + + + Proportion + 203pt + Tabs + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EDF0692099D00951B8B + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{10, 27}, {728, 477}} + + Module + XCDetailModule + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA23EE00692099D00951B8B + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{10, 31}, {603, 297}} + + Module + PBXProjectFindModule + + + ContentConfiguration + + PBXCVSModuleFilterTypeKey + 1032 + PBXProjectModuleGUID + 1CA23EE10692099D00951B8B + PBXProjectModuleLabel + SCM Results + + GeometryConfiguration + + Frame + {{10, 31}, {603, 297}} + + Module + PBXCVSModule + + + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + XCBuildResultsTrigger_Collapse + 1021 + XCBuildResultsTrigger_Open + 1011 + + GeometryConfiguration + + Frame + {{10, 27}, {857, 176}} + RubberWindowFrame + 551 233 1090 766 0 0 1680 1028 + + Module + PBXBuildResultsModule + + + + + Proportion + 857pt + + + Name + Project + ServiceClasses + + XCModuleDock + PBXSmartGroupTreeModule + XCModuleDock + PBXNavigatorGroup + XCDockableTabModule + XCDetailModule + PBXProjectFindModule + PBXCVSModule + PBXBuildResultsModule + + TableOfContents + + DD1DED4D12E28999004C00BD + 1CA23ED40692098700951B8B + DD1DED4E12E28999004C00BD + DD1DED3812E288B7004C00BD + DD1DED4F12E28999004C00BD + 1CA23EDF0692099D00951B8B + 1CA23EE00692099D00951B8B + 1CA23EE10692099D00951B8B + XCMainBuildResultsModuleGUID + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.defaultV3 + + + ChosenToolbarItems + + XCToolbarPerspectiveControl + NSToolbarSeparatorItem + active-combo-popup + NSToolbarFlexibleSpaceItem + servicesModuleRefactoring + clean + build + debugger-enable-breakpoints + build-and-go + com.apple.ide.PBXToolbarStopButton + debugger-restart-executable + debugger-pause + debugger-step-over + debugger-step-into + debugger-step-out + NSToolbarFlexibleSpaceItem + servicesModulebreakpoints + debugger-show-console-window + + ControllerClassBaseName + PBXDebugSessionModule + IconName + DebugTabIcon + Identifier + perspective.debug + IsVertical + + Layout + + + ContentConfiguration + + PBXProjectModuleGUID + 1CCC7628064C1048000F2A68 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {424, 270}} + + Module + PBXDebugCLIModule + Proportion + 270pt + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {395, 213}} + {{395, 0}, {415, 213}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {810, 213}} + {{0, 213}, {810, 225}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1CCC7629064C1048000F2A68 + PBXProjectModuleLabel + Debug + + GeometryConfiguration + + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 7}, {810, 438}} + PBXDebugSessionStackFrameViewKey + + DebugVariablesTableConfiguration + + Name + 120 + Value + 85 + Summary + 185 + + Frame + {{395, 0}, {415, 213}} + + + Module + PBXDebugSessionModule + Proportion + 438pt + + + Name + Debug + ServiceClasses + + XCModuleDock + PBXDebugCLIModule + PBXDebugSessionModule + PBXDebugProcessAndThreadModule + PBXDebugProcessViewModule + PBXDebugThreadViewModule + PBXDebugStackFrameViewModule + PBXNavigatorGroup + + TableOfContents + + DD1DEDB912E2B8CE004C00BD + 1CCC7628064C1048000F2A68 + 1CCC7629064C1048000F2A68 + DD1DEDBA12E2B8CE004C00BD + DD1DEDBB12E2B8CE004C00BD + DD1DEDBC12E2B8CE004C00BD + DD1DEDBD12E2B8CE004C00BD + DD1DEDBE12E2B8CE004C00BD + + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarConfiguration + xcode.toolbar.config.debugV3 + + + PerspectivesBarVisible + + ShelfIsVisible + + SourceDescription + file at '/Developer/Library/PrivateFrameworks/DevToolsInterface.framework/Resources/XCPerspectivesSpecification.xcperspec' + StatusbarIsVisible + + TimeStamp + 0.0 + ToolbarConfigUserDefaultsMinorVersion + 2 + ToolbarDisplayMode + 1 + ToolbarIsVisible + + ToolbarSizeMode + 2 + Type + Perspectives + UpdateMessage + + WindowJustification + 5 + WindowOrderList + + /Users/markj/proj/HJCache/HJCache.xcodeproj + + WindowString + 551 233 1090 766 0 0 1680 1028 + WindowToolsV3 + + + Identifier + windowTool.debugger + Layout + + + Dock + + + ContentConfiguration + + Debugger + + HorizontalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {317, 164}} + {{317, 0}, {377, 164}} + + + VerticalSplitView + + _collapsingFrameDimension + 0.0 + _indexOfCollapsedView + 0 + _percentageOfCollapsedView + 0.0 + isCollapsed + yes + sizes + + {{0, 0}, {694, 164}} + {{0, 164}, {694, 216}} + + + + LauncherConfigVersion + 8 + PBXProjectModuleGUID + 1C162984064C10D400B95A72 + PBXProjectModuleLabel + Debug - GLUTExamples (Underwater) + + GeometryConfiguration + + DebugConsoleDrawerSize + {100, 120} + DebugConsoleVisible + None + DebugConsoleWindowFrame + {{200, 200}, {500, 300}} + DebugSTDIOWindowFrame + {{200, 200}, {500, 300}} + Frame + {{0, 0}, {694, 380}} + RubberWindowFrame + 321 238 694 422 0 0 1440 878 + + Module + PBXDebugSessionModule + Proportion + 100% + + + Proportion + 100% + + + Name + Debugger + ServiceClasses + + PBXDebugSessionModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CD10A99069EF8BA00B06720 + 1C0AD2AB069F1E9B00FABCE6 + 1C162984064C10D400B95A72 + 1C0AD2AC069F1E9B00FABCE6 + + ToolbarConfiguration + xcode.toolbar.config.debugV3 + WindowString + 321 238 694 422 0 0 1440 878 + WindowToolGUID + 1CD10A99069EF8BA00B06720 + WindowToolIsVisible + 0 + + + Identifier + windowTool.build + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528F0623707200166675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD052900623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {500, 215}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 218pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + XCMainBuildResultsModuleGUID + PBXProjectModuleLabel + Build Results + + GeometryConfiguration + + Frame + {{0, 222}, {500, 236}} + RubberWindowFrame + 192 257 500 500 0 0 1280 1002 + + Module + PBXBuildResultsModule + Proportion + 236pt + + + Proportion + 458pt + + + Name + Build Results + ServiceClasses + + PBXBuildResultsModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAA5065D492600B07095 + 1C78EAA6065D492600B07095 + 1CD0528F0623707200166675 + XCMainBuildResultsModuleGUID + + ToolbarConfiguration + xcode.toolbar.config.buildV3 + WindowString + 192 257 500 500 0 0 1280 1002 + + + Identifier + windowTool.find + Layout + + + Dock + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1CDD528C0622207200134675 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1CD0528D0623707200166675 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {781, 167}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXNavigatorGroup + Proportion + 781pt + + + Proportion + 50% + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD0528E0623707200166675 + PBXProjectModuleLabel + Project Find + + GeometryConfiguration + + Frame + {{8, 0}, {773, 254}} + RubberWindowFrame + 62 385 781 470 0 0 1440 878 + + Module + PBXProjectFindModule + Proportion + 50% + + + Proportion + 428pt + + + Name + Project Find + ServiceClasses + + PBXProjectFindModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D57069F1CE1000CFCEE + 1C530D58069F1CE1000CFCEE + 1C530D59069F1CE1000CFCEE + 1CDD528C0622207200134675 + 1C530D5A069F1CE1000CFCEE + 1CE0B1FE06471DED0097A5F4 + 1CD0528E0623707200166675 + + WindowString + 62 385 781 470 0 0 1440 878 + WindowToolGUID + 1C530D57069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.snapshots + Layout + + + Dock + + + Module + XCSnapshotModule + Proportion + 100% + + + Proportion + 100% + + + Name + Snapshots + ServiceClasses + + XCSnapshotModule + + StatusbarIsVisible + Yes + ToolbarConfiguration + xcode.toolbar.config.snapshots + WindowString + 315 824 300 550 0 0 1440 878 + WindowToolIsVisible + Yes + + + Identifier + windowTool.debuggerConsole + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAAC065D492600B07095 + PBXProjectModuleLabel + Debugger Console + + GeometryConfiguration + + Frame + {{0, 0}, {700, 358}} + RubberWindowFrame + 149 87 700 400 0 0 1440 878 + + Module + PBXDebugCLIModule + Proportion + 358pt + + + Proportion + 358pt + + + Name + Debugger Console + ServiceClasses + + PBXDebugCLIModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C530D5B069F1CE1000CFCEE + 1C530D5C069F1CE1000CFCEE + 1C78EAAC065D492600B07095 + + ToolbarConfiguration + xcode.toolbar.config.consoleV3 + WindowString + 149 87 440 400 0 0 1440 878 + WindowToolGUID + 1C530D5B069F1CE1000CFCEE + WindowToolIsVisible + 0 + + + Identifier + windowTool.scm + Layout + + + Dock + + + ContentConfiguration + + PBXProjectModuleGUID + 1C78EAB2065D492600B07095 + PBXProjectModuleLabel + <No Editor> + PBXSplitModuleInNavigatorKey + + Split0 + + PBXProjectModuleGUID + 1C78EAB3065D492600B07095 + + SplitCount + 1 + + StatusBarVisibility + 1 + + GeometryConfiguration + + Frame + {{0, 0}, {452, 0}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + + Module + PBXNavigatorGroup + Proportion + 0pt + + + BecomeActive + 1 + ContentConfiguration + + PBXProjectModuleGUID + 1CD052920623707200166675 + PBXProjectModuleLabel + SCM + + GeometryConfiguration + + ConsoleFrame + {{0, 259}, {452, 0}} + Frame + {{0, 7}, {452, 259}} + RubberWindowFrame + 743 379 452 308 0 0 1280 1002 + TableConfiguration + + Status + 30 + FileName + 199 + Path + 197.09500122070312 + + TableFrame + {{0, 0}, {452, 250}} + + Module + PBXCVSModule + Proportion + 262pt + + + Proportion + 266pt + + + Name + SCM + ServiceClasses + + PBXCVSModule + + StatusbarIsVisible + 1 + TableOfContents + + 1C78EAB4065D492600B07095 + 1C78EAB5065D492600B07095 + 1C78EAB2065D492600B07095 + 1CD052920623707200166675 + + ToolbarConfiguration + xcode.toolbar.config.scmV3 + WindowString + 743 379 452 308 0 0 1280 1002 + + + Identifier + windowTool.breakpoints + IsVertical + 0 + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + PBXBottomSmartGroupGIDs + + 1C77FABC04509CD000000102 + + PBXProjectModuleGUID + 1CE0B1FE06471DED0097A5F4 + PBXProjectModuleLabel + Files + PBXProjectStructureProvided + no + PBXSmartGroupTreeModuleColumnData + + PBXSmartGroupTreeModuleColumnWidthsKey + + 168 + + PBXSmartGroupTreeModuleColumnsKey_v4 + + MainColumn + + + PBXSmartGroupTreeModuleOutlineStateKey_v7 + + PBXSmartGroupTreeModuleOutlineStateExpansionKey + + 1C77FABC04509CD000000102 + + PBXSmartGroupTreeModuleOutlineStateSelectionKey + + + 0 + + + PBXSmartGroupTreeModuleOutlineStateVisibleRectKey + {{0, 0}, {168, 350}} + + PBXTopSmartGroupGIDs + + XCIncludePerspectivesSwitch + 0 + + GeometryConfiguration + + Frame + {{0, 0}, {185, 368}} + GroupTreeTableConfiguration + + MainColumn + 168 + + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + PBXSmartGroupTreeModule + Proportion + 185pt + + + ContentConfiguration + + PBXProjectModuleGUID + 1CA1AED706398EBD00589147 + PBXProjectModuleLabel + Detail + + GeometryConfiguration + + Frame + {{190, 0}, {554, 368}} + RubberWindowFrame + 315 424 744 409 0 0 1440 878 + + Module + XCDetailModule + Proportion + 554pt + + + Proportion + 368pt + + + MajorVersion + 3 + MinorVersion + 0 + Name + Breakpoints + ServiceClasses + + PBXSmartGroupTreeModule + XCDetailModule + + StatusbarIsVisible + 1 + TableOfContents + + 1CDDB66807F98D9800BB5817 + 1CDDB66907F98D9800BB5817 + 1CE0B1FE06471DED0097A5F4 + 1CA1AED706398EBD00589147 + + ToolbarConfiguration + xcode.toolbar.config.breakpointsV3 + WindowString + 315 424 744 409 0 0 1440 878 + WindowToolGUID + 1CDDB66807F98D9800BB5817 + WindowToolIsVisible + 1 + + + Identifier + windowTool.debugAnimator + Layout + + + Dock + + + Module + PBXNavigatorGroup + Proportion + 100% + + + Proportion + 100% + + + Name + Debug Visualizer + ServiceClasses + + PBXNavigatorGroup + + StatusbarIsVisible + 1 + ToolbarConfiguration + xcode.toolbar.config.debugAnimatorV3 + WindowString + 100 100 700 500 0 0 1280 1002 + + + Identifier + windowTool.bookmarks + Layout + + + Dock + + + Module + PBXBookmarksModule + Proportion + 166pt + + + Proportion + 166pt + + + Name + Bookmarks + ServiceClasses + + PBXBookmarksModule + + StatusbarIsVisible + 0 + WindowString + 538 42 401 187 0 0 1280 1002 + + + Identifier + windowTool.projectFormatConflicts + Layout + + + Dock + + + Module + XCProjectFormatConflictsModule + Proportion + 100% + + + Proportion + 100% + + + Name + Project Format Conflicts + ServiceClasses + + XCProjectFormatConflictsModule + + StatusbarIsVisible + 0 + WindowContentMinSize + 450 300 + WindowString + 50 850 472 307 0 0 1440 877 + + + Identifier + windowTool.classBrowser + Layout + + + Dock + + + BecomeActive + 1 + ContentConfiguration + + OptionsSetName + Hierarchy, all classes + PBXProjectModuleGUID + 1CA6456E063B45B4001379D8 + PBXProjectModuleLabel + Class Browser - NSObject + + GeometryConfiguration + + ClassesFrame + {{0, 0}, {369, 96}} + ClassesTreeTableConfiguration + + PBXClassNameColumnIdentifier + 208 + PBXClassBookColumnIdentifier + 22 + + Frame + {{0, 0}, {616, 353}} + MembersFrame + {{0, 105}, {369, 395}} + MembersTreeTableConfiguration + + PBXMemberTypeIconColumnIdentifier + 22 + PBXMemberNameColumnIdentifier + 216 + PBXMemberTypeColumnIdentifier + 94 + PBXMemberBookColumnIdentifier + 22 + + PBXModuleWindowStatusBarHidden2 + 1 + RubberWindowFrame + 597 125 616 374 0 0 1280 1002 + + Module + PBXClassBrowserModule + Proportion + 354pt + + + Proportion + 354pt + + + Name + Class Browser + ServiceClasses + + PBXClassBrowserModule + + StatusbarIsVisible + 0 + TableOfContents + + 1C78EABA065D492600B07095 + 1C78EABB065D492600B07095 + 1CA6456E063B45B4001379D8 + + ToolbarConfiguration + xcode.toolbar.config.classbrowser + WindowString + 597 125 616 374 0 0 1280 1002 + + + Identifier + windowTool.refactoring + IncludeInToolsMenu + 0 + Layout + + + Dock + + + BecomeActive + 1 + GeometryConfiguration + + Frame + {0, 0}, {500, 335} + RubberWindowFrame + {0, 0}, {500, 335} + + Module + XCRefactoringModule + Proportion + 100% + + + Proportion + 100% + + + Name + Refactoring + ServiceClasses + + XCRefactoringModule + + WindowString + 200 200 500 356 0 0 1920 1200 + + + + diff --git a/HJCache.xcodeproj/project.pbxproj b/HJCache.xcodeproj/project.pbxproj new file mode 100755 index 0000000..b9674a6 --- /dev/null +++ b/HJCache.xcodeproj/project.pbxproj @@ -0,0 +1,443 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1D3623260D0F684500981E51 /* HJCacheAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */; }; + 1D60589B0D05DD56006BFB54 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 29B97316FDCFA39411CA2CEA /* main.m */; }; + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; }; + 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD735F0D9D9599002E5188 /* MainWindow.xib */; }; + 28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28C286E00D94DF7D0034E888 /* RootViewController.m */; }; + 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28F335F01007B36200424DE2 /* RootViewController.xib */; }; + DD1DED6812E28A12004C00BD /* HJCircularBuffer.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED5512E28A12004C00BD /* HJCircularBuffer.m */; }; + DD1DED6912E28A12004C00BD /* HJManagedImageV.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED5712E28A12004C00BD /* HJManagedImageV.m */; }; + DD1DED6A12E28A12004C00BD /* HJMOBigFileCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED5A12E28A12004C00BD /* HJMOBigFileCache.m */; }; + DD1DED6B12E28A12004C00BD /* HJMOFileCache.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED5C12E28A12004C00BD /* HJMOFileCache.m */; }; + DD1DED6C12E28A12004C00BD /* HJMOHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED5E12E28A12004C00BD /* HJMOHandler.m */; }; + DD1DED6D12E28A12004C00BD /* HJMOPolicy.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED6012E28A12004C00BD /* HJMOPolicy.m */; }; + DD1DED6E12E28A12004C00BD /* HJMOUserBase.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED6312E28A12004C00BD /* HJMOUserBase.m */; }; + DD1DED6F12E28A12004C00BD /* HJObjManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED6512E28A12004C00BD /* HJObjManager.m */; }; + DD1DED7012E28A12004C00BD /* HJWeakMutableArray.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED6712E28A12004C00BD /* HJWeakMutableArray.m */; }; + DD1DED7512E28A52004C00BD /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = DD1DED7312E28A52004C00BD /* LICENSE */; }; + DD1DED7612E28A52004C00BD /* README in Resources */ = {isa = PBXBuildFile; fileRef = DD1DED7412E28A52004C00BD /* README */; }; + DD1DED8212E28B37004C00BD /* FlickrSearcgTVC.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED7912E28B37004C00BD /* FlickrSearcgTVC.m */; }; + DD1DED8312E28B37004C00BD /* FlickrSearcgTVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD1DED7A12E28B37004C00BD /* FlickrSearcgTVC.xib */; }; + DD1DED8412E28B37004C00BD /* FlickrSearch.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED7C12E28B37004C00BD /* FlickrSearch.m */; }; + DD1DED8512E28B37004C00BD /* FlickrSearchRes.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED7E12E28B37004C00BD /* FlickrSearchRes.m */; }; + DD1DED8612E28B37004C00BD /* FlickrSearchTVC.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED8012E28B37004C00BD /* FlickrSearchTVC.m */; }; + DD1DED8712E28B37004C00BD /* FlickrSearchTVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD1DED8112E28B37004C00BD /* FlickrSearchTVC.xib */; }; + DD1DED9112E28B3E004C00BD /* Content.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED8A12E28B3E004C00BD /* Content.m */; }; + DD1DED9212E28B3E004C00BD /* ImgCell.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED8C12E28B3E004C00BD /* ImgCell.m */; }; + DD1DED9312E28B3E004C00BD /* ImgCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD1DED8D12E28B3E004C00BD /* ImgCell.xib */; }; + DD1DED9412E28B3E004C00BD /* ImgTVC.m in Sources */ = {isa = PBXBuildFile; fileRef = DD1DED8F12E28B3E004C00BD /* ImgTVC.m */; }; + DD1DED9512E28B3E004C00BD /* ImgTVC.xib in Resources */ = {isa = PBXBuildFile; fileRef = DD1DED9012E28B3E004C00BD /* ImgTVC.xib */; }; + DD1DEDC612E2B94D004C00BD /* 0.png in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDBF12E2B94D004C00BD /* 0.png */; }; + DD1DEDC712E2B94D004C00BD /* 1.png in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDC012E2B94D004C00BD /* 1.png */; }; + DD1DEDC812E2B94D004C00BD /* 1.psd in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDC112E2B94D004C00BD /* 1.psd */; }; + DD1DEDC912E2B94D004C00BD /* 2.png in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDC212E2B94D004C00BD /* 2.png */; }; + DD1DEDCA12E2B94D004C00BD /* 3.png in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDC312E2B94D004C00BD /* 3.png */; }; + DD1DEDCB12E2B94D004C00BD /* 4.png in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDC412E2B94D004C00BD /* 4.png */; }; + DD1DEDCC12E2B94D004C00BD /* 5.png in Resources */ = {isa = PBXBuildFile; fileRef = DD1DEDC512E2B94D004C00BD /* 5.png */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D3623240D0F684500981E51 /* HJCacheAppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJCacheAppDelegate.h; sourceTree = ""; }; + 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJCacheAppDelegate.m; sourceTree = ""; }; + 1D6058910D05DD3D006BFB54 /* HJCache.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = HJCache.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 28A0AAE50D9B0CCF005BE974 /* HJCache_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJCache_Prefix.pch; sourceTree = ""; }; + 28AD735F0D9D9599002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; + 28C286DF0D94DF7D0034E888 /* RootViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RootViewController.h; sourceTree = ""; }; + 28C286E00D94DF7D0034E888 /* RootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RootViewController.m; sourceTree = ""; }; + 28F335F01007B36200424DE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; }; + 29B97316FDCFA39411CA2CEA /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + 8D1107310486CEB800E47090 /* HJCache-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "HJCache-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; + DD1DED5412E28A12004C00BD /* HJCircularBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJCircularBuffer.h; sourceTree = ""; }; + DD1DED5512E28A12004C00BD /* HJCircularBuffer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJCircularBuffer.m; sourceTree = ""; }; + DD1DED5612E28A12004C00BD /* HJManagedImageV.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJManagedImageV.h; sourceTree = ""; }; + DD1DED5712E28A12004C00BD /* HJManagedImageV.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJManagedImageV.m; sourceTree = ""; }; + DD1DED5812E28A12004C00BD /* HJManagedImageVDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJManagedImageVDelegate.h; sourceTree = ""; }; + DD1DED5912E28A12004C00BD /* HJMOBigFileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJMOBigFileCache.h; sourceTree = ""; }; + DD1DED5A12E28A12004C00BD /* HJMOBigFileCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJMOBigFileCache.m; sourceTree = ""; }; + DD1DED5B12E28A12004C00BD /* HJMOFileCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJMOFileCache.h; sourceTree = ""; }; + DD1DED5C12E28A12004C00BD /* HJMOFileCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJMOFileCache.m; sourceTree = ""; }; + DD1DED5D12E28A12004C00BD /* HJMOHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJMOHandler.h; sourceTree = ""; }; + DD1DED5E12E28A12004C00BD /* HJMOHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJMOHandler.m; sourceTree = ""; }; + DD1DED5F12E28A12004C00BD /* HJMOPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJMOPolicy.h; sourceTree = ""; }; + DD1DED6012E28A12004C00BD /* HJMOPolicy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJMOPolicy.m; sourceTree = ""; }; + DD1DED6112E28A12004C00BD /* HJMOUser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJMOUser.h; sourceTree = ""; }; + DD1DED6212E28A12004C00BD /* HJMOUserBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJMOUserBase.h; sourceTree = ""; }; + DD1DED6312E28A12004C00BD /* HJMOUserBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJMOUserBase.m; sourceTree = ""; }; + DD1DED6412E28A12004C00BD /* HJObjManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJObjManager.h; sourceTree = ""; }; + DD1DED6512E28A12004C00BD /* HJObjManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJObjManager.m; sourceTree = ""; }; + DD1DED6612E28A12004C00BD /* HJWeakMutableArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HJWeakMutableArray.h; sourceTree = ""; }; + DD1DED6712E28A12004C00BD /* HJWeakMutableArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HJWeakMutableArray.m; sourceTree = ""; }; + DD1DED7312E28A52004C00BD /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; + DD1DED7412E28A52004C00BD /* README */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README; sourceTree = ""; }; + DD1DED7812E28B37004C00BD /* FlickrSearcgTVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlickrSearcgTVC.h; sourceTree = ""; }; + DD1DED7912E28B37004C00BD /* FlickrSearcgTVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlickrSearcgTVC.m; sourceTree = ""; }; + DD1DED7A12E28B37004C00BD /* FlickrSearcgTVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlickrSearcgTVC.xib; sourceTree = ""; }; + DD1DED7B12E28B37004C00BD /* FlickrSearch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlickrSearch.h; sourceTree = ""; }; + DD1DED7C12E28B37004C00BD /* FlickrSearch.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlickrSearch.m; sourceTree = ""; }; + DD1DED7D12E28B37004C00BD /* FlickrSearchRes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlickrSearchRes.h; sourceTree = ""; }; + DD1DED7E12E28B37004C00BD /* FlickrSearchRes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlickrSearchRes.m; sourceTree = ""; }; + DD1DED7F12E28B37004C00BD /* FlickrSearchTVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FlickrSearchTVC.h; sourceTree = ""; }; + DD1DED8012E28B37004C00BD /* FlickrSearchTVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FlickrSearchTVC.m; sourceTree = ""; }; + DD1DED8112E28B37004C00BD /* FlickrSearchTVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = FlickrSearchTVC.xib; sourceTree = ""; }; + DD1DED8912E28B3E004C00BD /* Content.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Content.h; sourceTree = ""; }; + DD1DED8A12E28B3E004C00BD /* Content.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Content.m; sourceTree = ""; }; + DD1DED8B12E28B3E004C00BD /* ImgCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImgCell.h; sourceTree = ""; }; + DD1DED8C12E28B3E004C00BD /* ImgCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImgCell.m; sourceTree = ""; }; + DD1DED8D12E28B3E004C00BD /* ImgCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImgCell.xib; sourceTree = ""; }; + DD1DED8E12E28B3E004C00BD /* ImgTVC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImgTVC.h; sourceTree = ""; }; + DD1DED8F12E28B3E004C00BD /* ImgTVC.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImgTVC.m; sourceTree = ""; }; + DD1DED9012E28B3E004C00BD /* ImgTVC.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ImgTVC.xib; sourceTree = ""; }; + DD1DEDBF12E2B94D004C00BD /* 0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 0.png; path = Images/0.png; sourceTree = ""; }; + DD1DEDC012E2B94D004C00BD /* 1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 1.png; path = Images/1.png; sourceTree = ""; }; + DD1DEDC112E2B94D004C00BD /* 1.psd */ = {isa = PBXFileReference; lastKnownFileType = file; name = 1.psd; path = Images/1.psd; sourceTree = ""; }; + DD1DEDC212E2B94D004C00BD /* 2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 2.png; path = Images/2.png; sourceTree = ""; }; + DD1DEDC312E2B94D004C00BD /* 3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 3.png; path = Images/3.png; sourceTree = ""; }; + DD1DEDC412E2B94D004C00BD /* 4.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 4.png; path = Images/4.png; sourceTree = ""; }; + DD1DEDC512E2B94D004C00BD /* 5.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = 5.png; path = Images/5.png; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 080E96DDFE201D6D7F000001 /* DemoClasses */ = { + isa = PBXGroup; + children = ( + DD1DED8812E28B3E004C00BD /* ImageTable */, + DD1DED7712E28B37004C00BD /* Flickr */, + 28C286DF0D94DF7D0034E888 /* RootViewController.h */, + 28C286E00D94DF7D0034E888 /* RootViewController.m */, + 1D3623240D0F684500981E51 /* HJCacheAppDelegate.h */, + 1D3623250D0F684500981E51 /* HJCacheAppDelegate.m */, + ); + path = DemoClasses; + sourceTree = ""; + }; + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* HJCache.app */, + ); + name = Products; + sourceTree = ""; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + DD1DED5312E28A12004C00BD /* HJCacheClasses */, + 080E96DDFE201D6D7F000001 /* DemoClasses */, + 29B97315FDCFA39411CA2CEA /* Other Sources */, + DD1DEDB212E2B8BA004C00BD /* Images */, + 29B97317FDCFA39411CA2CEA /* Resources */, + DD1DED7312E28A52004C00BD /* LICENSE */, + DD1DED7412E28A52004C00BD /* README */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = ""; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 28A0AAE50D9B0CCF005BE974 /* HJCache_Prefix.pch */, + 29B97316FDCFA39411CA2CEA /* main.m */, + ); + name = "Other Sources"; + sourceTree = ""; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + 28F335F01007B36200424DE2 /* RootViewController.xib */, + 28AD735F0D9D9599002E5188 /* MainWindow.xib */, + 8D1107310486CEB800E47090 /* HJCache-Info.plist */, + ); + name = Resources; + sourceTree = ""; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + DD1DED5312E28A12004C00BD /* HJCacheClasses */ = { + isa = PBXGroup; + children = ( + DD1DED5412E28A12004C00BD /* HJCircularBuffer.h */, + DD1DED5512E28A12004C00BD /* HJCircularBuffer.m */, + DD1DED5612E28A12004C00BD /* HJManagedImageV.h */, + DD1DED5712E28A12004C00BD /* HJManagedImageV.m */, + DD1DED5812E28A12004C00BD /* HJManagedImageVDelegate.h */, + DD1DED5912E28A12004C00BD /* HJMOBigFileCache.h */, + DD1DED5A12E28A12004C00BD /* HJMOBigFileCache.m */, + DD1DED5B12E28A12004C00BD /* HJMOFileCache.h */, + DD1DED5C12E28A12004C00BD /* HJMOFileCache.m */, + DD1DED5D12E28A12004C00BD /* HJMOHandler.h */, + DD1DED5E12E28A12004C00BD /* HJMOHandler.m */, + DD1DED5F12E28A12004C00BD /* HJMOPolicy.h */, + DD1DED6012E28A12004C00BD /* HJMOPolicy.m */, + DD1DED6112E28A12004C00BD /* HJMOUser.h */, + DD1DED6212E28A12004C00BD /* HJMOUserBase.h */, + DD1DED6312E28A12004C00BD /* HJMOUserBase.m */, + DD1DED6412E28A12004C00BD /* HJObjManager.h */, + DD1DED6512E28A12004C00BD /* HJObjManager.m */, + DD1DED6612E28A12004C00BD /* HJWeakMutableArray.h */, + DD1DED6712E28A12004C00BD /* HJWeakMutableArray.m */, + ); + path = HJCacheClasses; + sourceTree = ""; + }; + DD1DED7712E28B37004C00BD /* Flickr */ = { + isa = PBXGroup; + children = ( + DD1DED7812E28B37004C00BD /* FlickrSearcgTVC.h */, + DD1DED7912E28B37004C00BD /* FlickrSearcgTVC.m */, + DD1DED7A12E28B37004C00BD /* FlickrSearcgTVC.xib */, + DD1DED7B12E28B37004C00BD /* FlickrSearch.h */, + DD1DED7C12E28B37004C00BD /* FlickrSearch.m */, + DD1DED7D12E28B37004C00BD /* FlickrSearchRes.h */, + DD1DED7E12E28B37004C00BD /* FlickrSearchRes.m */, + DD1DED7F12E28B37004C00BD /* FlickrSearchTVC.h */, + DD1DED8012E28B37004C00BD /* FlickrSearchTVC.m */, + DD1DED8112E28B37004C00BD /* FlickrSearchTVC.xib */, + ); + path = Flickr; + sourceTree = ""; + }; + DD1DED8812E28B3E004C00BD /* ImageTable */ = { + isa = PBXGroup; + children = ( + DD1DED8912E28B3E004C00BD /* Content.h */, + DD1DED8A12E28B3E004C00BD /* Content.m */, + DD1DED8B12E28B3E004C00BD /* ImgCell.h */, + DD1DED8C12E28B3E004C00BD /* ImgCell.m */, + DD1DED8D12E28B3E004C00BD /* ImgCell.xib */, + DD1DED8E12E28B3E004C00BD /* ImgTVC.h */, + DD1DED8F12E28B3E004C00BD /* ImgTVC.m */, + DD1DED9012E28B3E004C00BD /* ImgTVC.xib */, + ); + path = ImageTable; + sourceTree = ""; + }; + DD1DEDB212E2B8BA004C00BD /* Images */ = { + isa = PBXGroup; + children = ( + DD1DEDBF12E2B94D004C00BD /* 0.png */, + DD1DEDC012E2B94D004C00BD /* 1.png */, + DD1DEDC112E2B94D004C00BD /* 1.psd */, + DD1DEDC212E2B94D004C00BD /* 2.png */, + DD1DEDC312E2B94D004C00BD /* 3.png */, + DD1DEDC412E2B94D004C00BD /* 4.png */, + DD1DEDC512E2B94D004C00BD /* 5.png */, + ); + name = Images; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* HJCache */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "HJCache" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = HJCache; + productName = HJCache; + productReference = 1D6058910D05DD3D006BFB54 /* HJCache.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "HJCache" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + en, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* HJCache */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */, + 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */, + DD1DED7512E28A52004C00BD /* LICENSE in Resources */, + DD1DED7612E28A52004C00BD /* README in Resources */, + DD1DED8312E28B37004C00BD /* FlickrSearcgTVC.xib in Resources */, + DD1DED8712E28B37004C00BD /* FlickrSearchTVC.xib in Resources */, + DD1DED9312E28B3E004C00BD /* ImgCell.xib in Resources */, + DD1DED9512E28B3E004C00BD /* ImgTVC.xib in Resources */, + DD1DEDC612E2B94D004C00BD /* 0.png in Resources */, + DD1DEDC712E2B94D004C00BD /* 1.png in Resources */, + DD1DEDC812E2B94D004C00BD /* 1.psd in Resources */, + DD1DEDC912E2B94D004C00BD /* 2.png in Resources */, + DD1DEDCA12E2B94D004C00BD /* 3.png in Resources */, + DD1DEDCB12E2B94D004C00BD /* 4.png in Resources */, + DD1DEDCC12E2B94D004C00BD /* 5.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589B0D05DD56006BFB54 /* main.m in Sources */, + 1D3623260D0F684500981E51 /* HJCacheAppDelegate.m in Sources */, + 28C286E10D94DF7D0034E888 /* RootViewController.m in Sources */, + DD1DED6812E28A12004C00BD /* HJCircularBuffer.m in Sources */, + DD1DED6912E28A12004C00BD /* HJManagedImageV.m in Sources */, + DD1DED6A12E28A12004C00BD /* HJMOBigFileCache.m in Sources */, + DD1DED6B12E28A12004C00BD /* HJMOFileCache.m in Sources */, + DD1DED6C12E28A12004C00BD /* HJMOHandler.m in Sources */, + DD1DED6D12E28A12004C00BD /* HJMOPolicy.m in Sources */, + DD1DED6E12E28A12004C00BD /* HJMOUserBase.m in Sources */, + DD1DED6F12E28A12004C00BD /* HJObjManager.m in Sources */, + DD1DED7012E28A12004C00BD /* HJWeakMutableArray.m in Sources */, + DD1DED8212E28B37004C00BD /* FlickrSearcgTVC.m in Sources */, + DD1DED8412E28B37004C00BD /* FlickrSearch.m in Sources */, + DD1DED8512E28B37004C00BD /* FlickrSearchRes.m in Sources */, + DD1DED8612E28B37004C00BD /* FlickrSearchTVC.m in Sources */, + DD1DED9112E28B3E004C00BD /* Content.m in Sources */, + DD1DED9212E28B3E004C00BD /* ImgCell.m in Sources */, + DD1DED9412E28B3E004C00BD /* ImgTVC.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = HJCache_Prefix.pch; + INFOPLIST_FILE = "HJCache-Info.plist"; + PRODUCT_NAME = HJCache; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = HJCache_Prefix.pch; + INFOPLIST_FILE = "HJCache-Info.plist"; + PRODUCT_NAME = HJCache; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = iphoneos; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + PREBINDING = NO; + SDKROOT = iphoneos; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "HJCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "HJCache" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/HJCacheClasses/HJCircularBuffer.h b/HJCacheClasses/HJCircularBuffer.h new file mode 100644 index 0000000..727307f --- /dev/null +++ b/HJCacheClasses/HJCircularBuffer.h @@ -0,0 +1,42 @@ +// +// HJCircularBuffer.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + + +#import + + +//Fixed size buffer (array) that you can add objects to in turn, when it gets full to the end of the array, +// it starts again from the front of the array replacing old objects with new ones. +// Is implemented with an array full of [NSNull null] objects, so putting nulls in is like deleting the object at +// the next available slot. The NSNulls never come out of this data structure, nil is returned instead of NSNull. + +@interface HJCircularBuffer : NSObject { + NSMutableArray* buffer; + int nextIndex; +} + + ++(HJCircularBuffer*)bufferWithCapacity:(int)capacity; +-(HJCircularBuffer*)initWithCapacity:(int)capacity; +-(int)length; + +/** + * Add object to 'end' of buffer. + * @return an autoreleased object that had to be removed to make room for the object added. + */ +-(id)addObject:(id)obj; +-(id)objectAtIndex:(int)i; +-(void)removeObject:(id)key; +-(void)removeObjectAtIndex:(int)i; +-(id)swapObject:(NSObject*)obj atIndex:(int)i; +-(id)findObject:(id)key; +-(int)findIndexOfObject:(id)key; + + +@end diff --git a/HJCacheClasses/HJCircularBuffer.m b/HJCacheClasses/HJCircularBuffer.m new file mode 100644 index 0000000..a9bc5ca --- /dev/null +++ b/HJCacheClasses/HJCircularBuffer.m @@ -0,0 +1,136 @@ +// +// HJCircularBuffer.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJCircularBuffer.h" + + +@implementation HJCircularBuffer + ++(HJCircularBuffer*)bufferWithCapacity:(int)capacity { + return [[[HJCircularBuffer alloc] initWithCapacity:capacity] autorelease]; +} + +-(HJCircularBuffer*)initWithCapacity:(int)capacity { + [super init]; + buffer = [[NSMutableArray arrayWithCapacity:capacity] retain]; + nextIndex=0; + NSNull* nullObj = [NSNull null]; + for (int i=0; i=[buffer count]) { + nextIndex=0; + } + return oldObj; +} + +-(id)swapObject:(id)obj atIndex:(int)i { + id oldObj = [buffer objectAtIndex:i]; + if (oldObj!=[NSNull null]) { + //because when old objObj replaced in the buffer, it will be released and might dealloc: + [oldObj retain]; + [oldObj autorelease]; + } + [buffer replaceObjectAtIndex:nextIndex withObject:obj]; + if (oldObj!=[NSNull null]) { + return oldObj; + } + return nil; +} + + +-(int)findIndexOfObject:(id)key { + NSNull* nullObj = [NSNull null]; + id obj; + int i = nextIndex-1; //start looking at the last object + if (i<0) { i=0; } + for (int n = [buffer count]-1; n>=0; n--) { + if (i<0) { + i=[buffer count]-1; //i has to wrap around to the end of the buffer array + } + obj = [buffer objectAtIndex:i]; + if (obj!=nullObj) { + BOOL result = [obj isEqual:key]; + if (result) { + return i; + } + } + i--; + } + return -1; +} + +-(id)findObject:(id)key { + int i = [self findIndexOfObject:key]; + if (i<0) { + return nil; + } + return [self objectAtIndex:i]; +} + +-(id)objectAtIndex:(int)i { + id obj = [buffer objectAtIndex:i]; + if (obj==[NSNull null]) { + return nil; + } + return obj; +} + +-(void)removeObjectAtIndex:(int)i { + [buffer replaceObjectAtIndex:i withObject:[NSNull null]]; +} + +-(void)removeObject:(id)key { + int i = [self findIndexOfObject:key]; + if (i<0) { + return; + } + //NSLog(@"remove at index %i",i); + [self removeObjectAtIndex:i]; +} + + ++(void)test { + /* + HJCircularBuffer* b = [HJCircularBuffer bufferWithCapacity:4]; + + id o; + o = [b addObject:@"zero"]; + o = [b addObject:@"one"]; + o = [b addObject:@"two"]; + o = [b addObject:@"three"]; + o = [b addObject:@"andBack"]; + + int i = [b findIndexOfObjectEqualTo:@"two"]; + o = [b findObjectEqualTo:@"two"]; + NSLog(@"%@",o); + */ +} + + +@end diff --git a/HJCacheClasses/HJMOBigFileCache.h b/HJCacheClasses/HJMOBigFileCache.h new file mode 100644 index 0000000..798d22f --- /dev/null +++ b/HJCacheClasses/HJMOBigFileCache.h @@ -0,0 +1,24 @@ +// +// HJMOBigFileCache.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import +#import "HJMOFileCache.h" + + + +@interface HJMOBigFileCache : HJMOFileCache { + + NSNumber* lastTrimDirNum; + NSDate* lastTrimDate; +} + +@property (retain) NSNumber* lastTrimDirNum; +@property (retain) NSDate* lastTrimDate; + +@end diff --git a/HJCacheClasses/HJMOBigFileCache.m b/HJCacheClasses/HJMOBigFileCache.m new file mode 100644 index 0000000..0ce5bb4 --- /dev/null +++ b/HJCacheClasses/HJMOBigFileCache.m @@ -0,0 +1,88 @@ +// +// HJMOBigFileCache.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJMOBigFileCache.h" + + +NSString* HJMOBigFileCache_trimDirKey = @"HJMOBigFileCacheTrimDir"; +NSString* HJMOBigFileCache_trimDateKey = @"HJMOBigFileCacheTrimDate"; + + +@implementation HJMOBigFileCache + +@synthesize lastTrimDate; +@synthesize lastTrimDirNum; + + +-(void)createCacheDirsIfNeeded { + [super createCacheDirsIfNeeded]; + for (int i=0; i<=9; i++) { + NSString* path = [NSString stringWithFormat:@"%@%i",readyPath,i]; + [[NSFileManager defaultManager] createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil]; + } +} + +-(NSString*)subdirForFilename:(NSString*)filename { + unichar c1 = [filename characterAtIndex:[filename length]-1]; + unichar c2 = [filename characterAtIndex:[filename length]-2]; + int hashpath = (c1+c2)%10; + return [NSString stringWithFormat:@"%i",hashpath]; +} + +-(NSString*)readyFilePathForOid:(id)oid { + NSString* filename = [self filenameForOid:oid]; + NSString* subdir = [self subdirForFilename:filename]; + NSString* path; + if (subdir==nil) { + path = [readyPath stringByAppendingString:filename]; + } else { + path = [NSString stringWithFormat:@"%@%@/%@",readyPath,subdir,filename]; + } + return path; +} + + +-(void)updateLastTrimState { + [[NSUserDefaults standardUserDefaults] setObject:self.lastTrimDirNum forKey:HJMOBigFileCache_trimDirKey]; + [[NSUserDefaults standardUserDefaults] setObject:self.lastTrimDate forKey:HJMOBigFileCache_trimDateKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + + +/* + This only trims 1/10th of the cache at a time, and does this no more than once every 1hrs. + */ +-(void)trimCache { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + self.lastTrimDirNum = (NSNumber*) [[NSUserDefaults standardUserDefaults] objectForKey:HJMOBigFileCache_trimDirKey]; + self.lastTrimDate = (NSDate*) [[NSUserDefaults standardUserDefaults] objectForKey:HJMOBigFileCache_trimDateKey]; + NSDate* now = [[[NSDate alloc] init] autorelease]; + + if (lastTrimDate==nil || [now timeIntervalSinceDate:lastTrimDate]>60*60*1) { + if (lastTrimDirNum==nil) { + self.lastTrimDirNum = [NSNumber numberWithInt:-1]; + } + int num = [lastTrimDirNum intValue]; + num++; + if (num>=10) { num=0; } + NSString* nextTrimPath = [NSString stringWithFormat:@"%@%i/",readyPath,num]; + [self trimCacheDir:nextTrimPath]; + + self.lastTrimDate = now; + self.lastTrimDirNum = [NSNumber numberWithInt:num]; + [self updateLastTrimState]; + } + [self performSelectorOnMainThread:@selector(updateLastTrimState) withObject:nil waitUntilDone:YES]; + + [pool release]; +} + + +@end diff --git a/HJCacheClasses/HJMOFileCache.h b/HJCacheClasses/HJMOFileCache.h new file mode 100644 index 0000000..5742237 --- /dev/null +++ b/HJCacheClasses/HJMOFileCache.h @@ -0,0 +1,58 @@ +// +// HJFiler.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import + + +@interface HJMOFileCache : NSObject { + + NSString* rootPath; + NSString* loadingPath; + NSString* readyPath; + NSString* countsPath; + + BOOL isCounting; + BOOL isLRU; + long fileCount; + long long byteCount; + + long fileCountLimit; + NSTimeInterval fileAgeLimit; + NSThread* maintenanceThread; +} + +@property long fileCount; +@property long long byteCount; +@property long fileCountLimit; +@property NSTimeInterval fileAgeLimit; +@property (nonatomic, retain) NSThread* maintenanceThread; + +-(HJMOFileCache*)initWithRootPath:(NSString*)root; +-(HJMOFileCache*)initWithRootPath:(NSString*)root + isCounting:(BOOL)isCounting + fileCountLimit:(long)countLimit + fileAgeLimit:(NSTimeInterval)ageLimit; + +-(void)createCacheDirsIfNeeded; + +-(NSString*)filenameForOid:(id)oid; +-(NSString*)readyFilePathForOid:(id)oid; +-(NSString*)loadingFilePathForOid:(id)oid; +-(NSString*)loadingFinishedForOid:(id)oid; +-(void)removeOid:(id)oid; + +-(void) deleteAllFilesInDir:(NSString*)path; +-(void) emptyCache; +-(void) saveCounts; +-(void) loadCounts; +-(void)trimCache; +-(void)trimCacheUsingBackgroundThread; +-(void)trimCacheDir:(NSString*)cachePath; + +@end diff --git a/HJCacheClasses/HJMOFileCache.m b/HJCacheClasses/HJMOFileCache.m new file mode 100644 index 0000000..c239868 --- /dev/null +++ b/HJCacheClasses/HJMOFileCache.m @@ -0,0 +1,280 @@ +// +// HJFiler.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJMOFileCache.h" + + +@implementation HJMOFileCache + +@synthesize fileCount; +@synthesize byteCount; +@synthesize fileAgeLimit; +@synthesize fileCountLimit; +@synthesize maintenanceThread; + + +-(HJMOFileCache*)initWithRootPath:(NSString*)root { + [super init]; + isCounting = NO; + fileCount = 0; + byteCount = 0; + rootPath = root; + [rootPath retain]; + + fileCountLimit = 0; + fileAgeLimit = 0; + + if (![[NSFileManager defaultManager] fileExistsAtPath:rootPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:rootPath withIntermediateDirectories:YES attributes:nil error:nil]; + } + + loadingPath = [[NSString stringWithFormat:@"%@/loading/",rootPath] retain]; + readyPath = [[NSString stringWithFormat:@"%@/ready/",rootPath] retain]; + [self createCacheDirsIfNeeded]; + countsPath = [[NSString stringWithFormat:@"%@/counts.plist",rootPath] retain]; + + //delete any half loaded files + [self deleteAllFilesInDir:loadingPath]; + + return self; +} + +-(HJMOFileCache*)initWithRootPath:(NSString*)root + isCounting:(BOOL)isCounting_ + fileCountLimit:(long)countLimit + fileAgeLimit:(NSTimeInterval)ageLimit { + + [self initWithRootPath:root]; + isCounting = isCounting_; + fileCountLimit = countLimit; + fileAgeLimit = ageLimit; + + if (isCounting) { + [self loadCounts]; + } + return self; +} + + +-(void)dealloc { + [rootPath release]; + [loadingPath release]; + [readyPath release]; + [countsPath release]; + [maintenanceThread release]; + [super dealloc]; +} + + +-(void)createCacheDirsIfNeeded { + if (![[NSFileManager defaultManager] fileExistsAtPath:loadingPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:loadingPath withIntermediateDirectories:YES attributes:nil error:nil]; + } + if (![[NSFileManager defaultManager] fileExistsAtPath:readyPath]) { + [[NSFileManager defaultManager] createDirectoryAtPath:readyPath withIntermediateDirectories:YES attributes:nil error:nil]; + } +} + + +-(void) deleteAllFilesInDir:(NSString*)path { + NSError* err=nil; + NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&err]; + if (err!=nil) { + return; + } + for (NSString* file in files) { + NSString* filepath = [NSString stringWithFormat:@"%@%@",path,file]; + [[NSFileManager defaultManager] removeItemAtPath:filepath error:&err]; + } +} + +-(void) emptyCache { + [self deleteAllFilesInDir:readyPath]; + [self deleteAllFilesInDir:loadingPath]; + self.fileCount=0; + self.byteCount=0; + if (isCounting) { + [self saveCounts]; + } +} + +-(NSString*)filenameForOid:(id)oid { + NSString* oidStr = [NSString stringWithFormat:@"%@",oid]; + oidStr = [oidStr stringByReplacingOccurrencesOfString:@"/" withString:@"_"]; + return oidStr; +} + +-(NSString*)readyFilePathForOid:(id)oid { + NSString* filename = [self filenameForOid:oid]; + NSString* path = [readyPath stringByAppendingString:filename]; + return path; +} + +-(NSString*)loadingFilePathForOid:(id)oid { + NSString* filename = [self filenameForOid:oid]; + NSString* path = [loadingPath stringByAppendingString:filename]; + return path;} + +-(NSString*)loadingFinishedForOid:(id)oid { + NSString* loadingFilename = [self loadingFilePathForOid:oid]; + NSString* readyFilename = [self readyFilePathForOid:oid]; + NSError* e=nil; + [[NSFileManager defaultManager] moveItemAtPath:loadingFilename toPath:readyFilename error:&e]; + if (e) { + NSLog(@"HJMOFileCache failed to move loading file to ready file %@",readyFilename); + return nil; + } else { + if (isCounting) { + NSError* e; + NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:readyFilename error:&e]; + NSNumber* size = [dict objectForKey:NSFileSize]; + fileCount++; + byteCount = byteCount + size.unsignedIntegerValue; + [self saveCounts]; + } + return readyFilename; + } +} + +-(void)removeOid:(id)oid { + NSError* err = nil; + NSString* path = [self readyFilePathForOid:oid]; + NSError* e; + NSDictionary* dict = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&e]; NSNumber* size = [dict objectForKey:NSFileSize]; + [[NSFileManager defaultManager] removeItemAtPath:path error:&err]; + if (err==nil) { + fileCount--; + byteCount = byteCount - size.unsignedIntegerValue; + [self saveCounts]; + } else { + //NSLog(@"HJMOFileCache error deleting %@",path); + } +} + + +-(void) saveCounts { + NSMutableDictionary* dict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithLongLong:byteCount],@"bytes", + [NSNumber numberWithLong:fileCount],@"files",nil]; + [dict writeToFile:countsPath atomically:YES]; +} + +-(void) loadCounts { + NSMutableDictionary* dict = [NSDictionary dictionaryWithContentsOfFile:countsPath]; + NSNumber* files = [dict objectForKey:@"files"]; + NSNumber* bytes = [dict objectForKey:@"bytes"]; + if (files!=nil) { + fileCount = [files longValue]; + } else { + files = 0; + } + if (bytes!=nil) { + byteCount = [bytes longLongValue]; + } else { + byteCount = 0; + } +} + +int fileAgeCompareFunction(id obj1, id obj2, void *context) { + NSNumber* age1 = [(NSArray*)obj1 objectAtIndex:0]; + NSNumber* age2 = [(NSArray*)obj2 objectAtIndex:0]; + return [age1 compare:age2]; +} + + +-(void)trimCacheDir:(NSString*)cachePath { + //limit number of files by deleting the oldest ones. + //creation date used to see age of file + //modification date used to see staleness of file - how long since last used. + + NSLog(@"triming cache %@",cachePath); + + NSFileManager *fileManager = [NSFileManager defaultManager]; + NSString *file; + NSDirectoryEnumerator *dirEnum = [fileManager enumeratorAtPath:cachePath]; + + NSMutableArray* fileAges = [NSMutableArray arrayWithCapacity:fileCountLimit]; //used to sort files by age + int thisDirFileCount=0; + int deletedCount=0; + long deletedBytes=0; + // this loop is the slow part, which is why this whole method is run on a separate thread. + while (file = [dirEnum nextObject]) { + NSString* filename = [NSString stringWithFormat:@"%@%@",cachePath,file]; + NSError* e; + NSDictionary* fsAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filename error:&e]; + double ageSeconds = -1* [[fsAttributes fileModificationDate] timeIntervalSinceNow]; + long filesize = [fsAttributes fileSize]; + if (ageSeconds>fileAgeLimit && fileAgeLimit>0) { + //old files get deleted right away + NSError* err=nil; + [fileManager removeItemAtPath:filename error:&err]; + if (isCounting && err==nil) { + deletedCount++; + deletedBytes += filesize; + } + } else { + //files that are not too old are going to be counted and sorted by age + thisDirFileCount++; + NSArray* fileAge; //a holder of filename, age, and size, for sorting names by file age + if (isCounting) { + fileAge = [NSArray arrayWithObjects:[NSNumber numberWithDouble:ageSeconds],filename,[NSNumber numberWithLong:filesize],nil]; + } else { + fileAge = [NSArray arrayWithObjects:[NSNumber numberWithDouble:ageSeconds],filename,nil]; + } + [fileAges addObject:fileAge]; + } + } + + if (thisDirFileCount >= fileCountLimit && fileCountLimit>0) { + //thisDirFileCount is still over the limit (even if some old files were deleted) + //so now have to delete the oldest files. Behavoir of cache will be FIFO or LRU depending on cache policy readsUpdateFileDate + [fileAges sortUsingFunction:fileAgeCompareFunction context:nil]; //sorted from oldest to youngest + //for (NSArray* a in fileAges) { + // NSLog(@"%@ %@",[a objectAtIndex:0],[a objectAtIndex:1]); + //} + int index = [fileAges count]-1; + //delete files until 20% under file count. + while ((thisDirFileCount)>(fileCountLimit*0.8) && index>0) { + NSError* err=nil; + NSArray* fileAgeObj = [fileAges objectAtIndex:index]; + NSString* filename = [fileAgeObj objectAtIndex:1]; + //NSLog(@"deleting %@",filename); + [fileManager removeItemAtPath:filename error:&err]; + if (err==nil) { + thisDirFileCount--; + if (isCounting) { + NSNumber* filesize = [fileAgeObj objectAtIndex:2]; + deletedCount++; + deletedBytes += [filesize longValue]; + } + } + index--; + } + } + NSLog(@"cache file trimed %i files",deletedCount); + if (isCounting) { + fileCount -= deletedCount; + byteCount -= deletedBytes; + [self performSelectorOnMainThread:@selector(saveCounts) withObject:nil waitUntilDone:YES]; + } +} + +-(void)trimCache { + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + [self trimCacheDir:readyPath]; + [pool release]; +} + +-(void)trimCacheUsingBackgroundThread { + self.maintenanceThread = [[NSThread alloc] initWithTarget:self selector:@selector(trimCache) object:nil]; + [maintenanceThread start]; +} + + +@end diff --git a/HJCacheClasses/HJMOHandler.h b/HJCacheClasses/HJMOHandler.h new file mode 100644 index 0000000..a29ab7c --- /dev/null +++ b/HJCacheClasses/HJMOHandler.h @@ -0,0 +1,70 @@ +// +// HJManagedState.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import +#import "HJWeakMutableArray.h" +#import "HJMOUser.h" +@class HJObjManager; +@class HJMOPolicy; + + +@interface HJMOHandler : NSObject { + enum HJMOState { stateNew, stateLoading, stateLoaded, stateReady, stateFailed } state; + id oid; + BOOL isDataReady; + NSURL* url; + NSURLConnection* urlConn; + NSMutableData* moData; + NSString* moReadyDataFilename; + NSFileHandle* moLoadingDataFile; + id managedObj; + HJWeakMutableArray* users; + HJObjManager* objManager; + HJMOPolicy* ownPolicy; +} + +@property (readonly) enum HJMOState state; +@property (nonatomic, retain) id oid; +@property (nonatomic, retain) NSURL* url; +@property (nonatomic, retain) NSURLConnection* urlConn; +@property (nonatomic, retain) NSData* moData; +@property (nonatomic, retain) NSFileHandle* moLoadingDataFile; +@property (nonatomic, retain) NSString* moReadyDataFilename; +@property (nonatomic, retain) id managedObj; +@property (nonatomic, assign) HJObjManager* objManager; +@property (nonatomic, retain) HJMOPolicy* ownPolicy; + + +-(HJMOHandler*)initWithOid:(id)oid_ url:(NSURL*)url_ objManager:objManager_; + + +//in use means that it has one or more users +-(BOOL)isInUse; + +//ready means that the managedObj is not nil and can be used by users. If not, then its unready +-(BOOL)isReady; + +//loading means that its not ready yet, but it will become ready by itself because the url is or will start loading. +-(BOOL)isLoading; + + +-(void) addUser:(id)user; +-(void) removeUser:(id)mo; +-(void) activateHandlerForUser:(id)user ; +-(void) startDownloadingFromURL; +-(void) callbackReadyToUsers; +-(void) callbackFailedToUsers; +-(void) goFromLoadedToReady; +-(void) cancelLoading; +-(void) clearLoadingState; + +@end + + + diff --git a/HJCacheClasses/HJMOHandler.m b/HJCacheClasses/HJMOHandler.m new file mode 100644 index 0000000..7c57db4 --- /dev/null +++ b/HJCacheClasses/HJMOHandler.m @@ -0,0 +1,359 @@ +// +// HJManagedState.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJMOHandler.h" +#import "HJMOUser.h" +#import "HJObjManager.h" +#import "HJMOFileCache.h" + + +@implementation HJMOHandler + +@synthesize state; +@synthesize oid; +@synthesize url; +@synthesize urlConn; +@synthesize moData; +@synthesize moReadyDataFilename; +@synthesize moLoadingDataFile; +@synthesize managedObj; +@synthesize objManager; +@synthesize ownPolicy; + + +-(HJMOHandler*)initWithOid:(id)oid_ url:(NSURL*)url_ objManager:objManager_{ + [super init]; + state = stateNew; + self.oid = oid_; + self.url = url_ ; + self.objManager = objManager_; + if (oid==nil) { + self.oid = url_; + } + + users = [[HJWeakMutableArray alloc] initWithCapacity:1]; //it can expand automatically. + return self; +} + +-(void)dealloc { + //NSLog(@"dealloc %@",self); + [urlConn cancel]; + [self clearLoadingState]; + [users release]; + [super dealloc]; +} + + +-(BOOL) isEqual:(id)object { + if (![object isKindOfClass:[HJMOHandler class]]) { + return NO; + } + return [oid isEqual:[(HJMOHandler*)object oid]]; +} + +-(HJMOPolicy*)policy { + if (ownPolicy) { + return ownPolicy; + } else { + return [objManager policy]; + } +} + +-(void)addUser:(id)user { + //check if already managing for this user (should not be if being used right) + if (nil==[users findObject:user]) { + [users addObject:user]; //did not already have user, so remember it (with a weak reference) + } else { + //can happen if users reused, and recycling code is lazy clearing old state, eg with UITableCellView + //NSLog(@"HJMOHandler was already managing for user"); + } + + if (user.moHandler==nil) { + //this is the normal case, so set the state + user.moHandler=self; + } else { + if (user.moHandler==self) { + //this is not what we expect, addUser has been called twice, but thats OK - do nothing + } else { + //user was pointing to another handler, this can happen when user is reused. + //have to make sure that the old handler knows it should no longer manage for this user + //otherwise it might send it callbacks, and it won't be able to become inactive (have no users) + [user.moHandler removeUser:user]; + //now can assign the current state, which will also release the old one. + user.moHandler=self; + } + } +} + +-(void) deleteFileIfExistsAtPath:(NSString*)path { + if ([[NSFileManager defaultManager] fileExistsAtPath:path]) { + NSError* e = nil; + [[NSFileManager defaultManager] removeItemAtPath:path error:&e]; + if (e) { + NSLog(@"HJMOHandler error deleting file %@",path); + } + } +} + +-(void)clearLoadingState { + self.urlConn=nil; + self.moData = nil; + [moLoadingDataFile closeFile]; + self.moLoadingDataFile = nil; + self.moData = nil; + [self deleteFileIfExistsAtPath:[self.objManager.fileCache loadingFilePathForOid:oid]]; +} + +-(void)cancelLoading { + if (state==stateLoading) { + [urlConn cancel]; + [self clearLoadingState]; + state=stateNew; + } +} + +-(void)becameNotInUse { + //TODO is there more policy decisions here? + //[self cancelLoading]; //don't cancel loading, do that in dealloc. because object manager might be holding on to + //this handler in loadingHandlers to keep loading going +} + +-(void)removeUser:(id)user { + [users removeObject:user]; + [self retain]; //because the next line could dealloc self. + user.moHandler = nil; + if (![self isInUse]) { + [self becameNotInUse]; + } + [self autorelease]; +} + + + +-(BOOL)isInUse { + return [users count]>0; +} + +-(BOOL)isLoading { + return urlConn!=nil; +} + +-(BOOL)isReady { + return managedObj!=nil; +} + +-(void)touchFile:(NSString*)path { + HJMOFileCache* fileCache = objManager.fileCache; + if (fileCache==nil) { return; } + NSTimeInterval ageLimit = fileCache.fileAgeLimit; + if (ageLimit<=0) { return; } + + NSFileManager* fileMan = [NSFileManager defaultManager]; + + NSError* e; + NSDictionary* fsAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:&e]; + double ageSeconds = -1* [[fsAttributes fileModificationDate] timeIntervalSinceNow]; + + if (ageSeconds>(ageLimit/4)) { + //to save writes, file age modification date isn't changed on every access, only if 1/4 of age limit old. + NSString *keyArray[1] = {NSFileModificationDate}; + id objectArray[1] = {[NSDate dateWithTimeIntervalSinceNow:0]}; + NSDictionary* attributes = [NSDictionary dictionaryWithObjects:objectArray forKeys:keyArray count:1]; + NSError* err; + [fileMan setAttributes:attributes ofItemAtPath:path error:&err]; + } +} + +-(void)activateNewHandlerForUser:(id)user { + HJMOFileCache* fileCache = objManager.fileCache; + if (fileCache) { + //File caching is in use + + NSString* readyFile = [fileCache readyFilePathForOid:oid]; + + if ([[NSFileManager defaultManager] fileExistsAtPath:readyFile]) { + //mo is loaded as a file in file cache + self.moReadyDataFilename = readyFile; + if (self.policy.readsUpdateFileDate) { + [self touchFile:readyFile]; + } + state = stateLoaded; + [self goFromLoadedToReady]; + return; + + } else { + //not loaded yet, so load to file because file cache in use + NSString* loadingFile = [fileCache loadingFilePathForOid:oid]; + + BOOL ok = [[NSFileManager defaultManager] createFileAtPath:loadingFile contents:nil attributes:nil]; + if (!ok) { + state = stateFailed; + NSLog(@"HJMOHandler error creating loading file %@",loadingFile); + loadingFile = nil; + [self clearLoadingState]; + [self callbackFailedToUsers]; + return; + } else { + self.moLoadingDataFile = [NSFileHandle fileHandleForWritingAtPath:loadingFile]; + } + } + } + + //if file cache is in use temporary file name is prepared, either way now load from url + [self startDownloadingFromURL]; +} + + + +-(void)activateHandlerForUser:(id)user { + //stateNew, stateLoading, stateLoaded, stateReady, stateFailed + + switch (state) { + + case stateNew: + [self activateNewHandlerForUser:user]; + return; + + case stateLoading: + //handler is still loading, have to wait for it to load, so nop. + return; + + case stateLoaded: + //for some reason it didn't go to ready when it was loaded, so try again now. + [self goFromLoadedToReady]; + return; + + case stateReady: + [user managedObjReady]; + return; + + case stateFailed: + [user managedObjFailed]; + return; + + default: + //not supposed to get here + NSLog(@"HJMOHandler activateHandlerForUser error, no recognized state"); + break; + } +} + + +-(void)startDownloadingFromURL { + //NSLog(@"HJMOHandler starting download for %@",self); + HJMOPolicy* policy = [self policy]; + NSURLRequest* request = [NSURLRequest requestWithURL:url + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:policy.urlTimeoutTime]; + self.urlConn = [[NSURLConnection alloc] initWithRequest:request delegate:self]; + [urlConn release]; + if (urlConn==nil) { + NSLog(@"HJMOHandler nil URLConnection for %@",url); + state=stateFailed; + } else { + state=stateLoading; + //TODO if app is showing a network activity monitor in the status bar, here is where a call needs to be + // made to increment the number of active URLs + } +} + +-(void) goFromLoadedToReady { + if ([users count]==0) { + //can't go to stateReady because there's no user to do it. stay in stateLoaded. + //this is not a bug, it can happen if the object has already been deleted before its content was + //loaded over the net, eg because scrolled off the top of a table. + //NSLog(@"HJMOHandler no user object to make it ready"); + return; + } + + self.managedObj=nil; //just to be sure there's not some old one around + //pick _one_ and only one user to take mo from loaded to ready + id user = [users objectAtIndex:0]; + @try { + [user changeManagedObjStateFromLoadedToReady]; + if (managedObj!=nil) { + state = stateReady; //because it worked + [self callbackReadyToUsers]; + } + } + @catch (id exception) { + NSLog(@"%@",exception); + } + @finally { + if (managedObj==nil) { + state = stateFailed; //was still nil, so it didn't work. + [self callbackFailedToUsers]; + } + } +} + +-(void) callbackReadyToUsers { + for (id user in [users objectEnumerator]) { + [user managedObjReady]; + } +} + +-(void) callbackFailedToUsers { + for (id user in [users objectEnumerator]) { + [user managedObjFailed]; + } +} + +- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { + if (state!=stateLoading) { return; } + if (!moLoadingDataFile) { + //loading direct to memory + if (moData==nil) { + self.moData = [NSMutableData dataWithCapacity:1024*10]; + } + [moData appendData:data]; + } else { + [moLoadingDataFile writeData:data]; + } +} + +- (void)connectionDidFinishLoading:(NSURLConnection *)connection { + //NSLog(@"finishedLoading %@",self); + state = stateLoaded; + if (moLoadingDataFile) { + //was downloading to file + [moLoadingDataFile closeFile]; + self.moLoadingDataFile = nil; + NSString* readyFilename = [self.objManager.fileCache loadingFinishedForOid:oid]; + if (readyFilename==nil) { + self.moLoadingDataFile = nil; + state = stateFailed; + [self callbackFailedToUsers]; + return; + } else { + self.moReadyDataFilename = readyFilename; + } + } + //TODO if app is showing a network activity monitor in the status bar, here is where a call needs to be + // made to decrement the count of active URLs + [self goFromLoadedToReady]; + [objManager handlerFinishedDownloading:self]; +} + +- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { + state = stateFailed; + NSLog(@"HJMOHandler URLConnection failed %@",error); + //TODO if app is showing a network activity monitor in the status bar, here is where a call needs to be + // made to decrement the count of active URLs + [self clearLoadingState]; + [self callbackFailedToUsers]; +} + + +-(NSString*)description { + return [NSString stringWithFormat:@"HJMOHandler %@ users:%i retains:%i",oid,[users count],[self retainCount]]; +} + + +@end diff --git a/HJCacheClasses/HJMOPolicy.h b/HJCacheClasses/HJMOPolicy.h new file mode 100644 index 0000000..fbe0991 --- /dev/null +++ b/HJCacheClasses/HJMOPolicy.h @@ -0,0 +1,33 @@ +// +// HJManagedObjPolicy.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import + + +@interface HJMOPolicy : NSObject { + + BOOL loadToFile; + BOOL cacheInMemory; + BOOL asyncStartLoad; + BOOL asyncIsReadyIfCached; + NSTimeInterval urlTimeoutTime; + BOOL readsUpdateFileDate; +} + +@property BOOL loadToFile; +@property BOOL cacheInMemory; +@property BOOL asyncStartLoad; +@property BOOL asyncIsReadyIfCached; +@property NSTimeInterval urlTimeoutTime; +@property BOOL readsUpdateFileDate; + ++(HJMOPolicy*) smallImgFastScrollLRUCachePolicy; + + +@end diff --git a/HJCacheClasses/HJMOPolicy.m b/HJCacheClasses/HJMOPolicy.m new file mode 100644 index 0000000..cf76174 --- /dev/null +++ b/HJCacheClasses/HJMOPolicy.m @@ -0,0 +1,42 @@ +// +// HJManagedObjPolicy.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJMOPolicy.h" + + +@implementation HJMOPolicy + +@synthesize loadToFile; +@synthesize cacheInMemory; +@synthesize asyncStartLoad; +@synthesize asyncIsReadyIfCached; +@synthesize urlTimeoutTime; +@synthesize readsUpdateFileDate; + + ++(HJMOPolicy*) smallImgFastScrollLRUCachePolicy { + //this is the default policy settings. + HJMOPolicy* policy = [[[HJMOPolicy alloc] init] autorelease]; + return policy; +} + +/** default policy is good for small images, fast scrolling, async updates, LRU file cache */ +-(HJMOPolicy*)init { + [super init]; + self.loadToFile = YES; + self.cacheInMemory = YES; + self.asyncStartLoad = YES; + self.asyncIsReadyIfCached = YES; + self.urlTimeoutTime = 30; + readsUpdateFileDate = YES; + return self; +} + + +@end diff --git a/HJCacheClasses/HJMOUser.h b/HJCacheClasses/HJMOUser.h new file mode 100644 index 0000000..3578d9e --- /dev/null +++ b/HJCacheClasses/HJMOUser.h @@ -0,0 +1,25 @@ +// +// HJManagedObj.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import +@class HJMOHandler; + + +@protocol HJMOUser + +@property (nonatomic, retain) HJMOHandler* moHandler; +@property (nonatomic, retain) id oid; +@property (nonatomic, retain) NSURL* url; + + +-(void) changeManagedObjStateFromLoadedToReady; +-(void) managedObjReady; +-(void) managedObjFailed; + +@end diff --git a/HJCacheClasses/HJMOUserBase.h b/HJCacheClasses/HJMOUserBase.h new file mode 100644 index 0000000..b62512d --- /dev/null +++ b/HJCacheClasses/HJMOUserBase.h @@ -0,0 +1,23 @@ +// +// HJManagedObjBase.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import +#import "HJMOUser.h" +#import "HJMOHandler.h" + + +@interface HJMOUserBase : NSObject { + + HJMOHandler* moHandler; + id oid; + NSURL* url; + +} + +@end diff --git a/HJCacheClasses/HJMOUserBase.m b/HJCacheClasses/HJMOUserBase.m new file mode 100644 index 0000000..93dbc1d --- /dev/null +++ b/HJCacheClasses/HJMOUserBase.m @@ -0,0 +1,42 @@ +// +// HJManagedObjBase.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJMOUserBase.h" + + +@implementation HJMOUserBase + +@synthesize moHandler; +@synthesize oid; +@synthesize url; + + +-(void) dealloc { + [moHandler removeUser:self]; + [moHandler release]; + [oid release]; + [url release]; + [super dealloc]; +} + +-(void) changeManagedObjStateFromLoadedToReady { + +} + +-(void) managedObjReady { + +} + +-(void) managedObjFailed { + +} + + + +@end diff --git a/HJCacheClasses/HJManagedImageV.h b/HJCacheClasses/HJManagedImageV.h new file mode 100644 index 0000000..ed841f2 --- /dev/null +++ b/HJCacheClasses/HJManagedImageV.h @@ -0,0 +1,61 @@ +// +// HJManagedImageV.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import +#import "HJMOUser.h" +#import "HJMOHandler.h" + + +@class HJManagedImageV; + +@protocol HJManagedImageVDelegate + -(void) managedImageSet:(HJManagedImageV*)mi; + -(void) managedImageCancelled:(HJManagedImageV*)mi; +@end + + + +@interface HJManagedImageV : UIView { + + id oid; + NSURL* url; + HJMOHandler* moHandler; + + UIImage* image; + UIImageView* imageView; + id callbackOnSetImage; + id callbackOnCancel; + BOOL isCancelled; + UIActivityIndicatorView* loadingWheel; + NSInvocation* onImageTap; + int index; // optional; may be used to assign an ordering to a image when working with an album, e.g. + int modification; +} + +@property int modification; +@property int index; +@property (nonatomic, retain) UIImage* image; +@property (nonatomic, retain) UIImageView* imageView; +@property (nonatomic, retain) UIActivityIndicatorView* loadingWheel; +@property (nonatomic, retain) id callbackOnSetImage; +@property (nonatomic, retain) id callbackOnCancel; + +-(void) clear; +-(void) markCancelled; +-(UIImage*) modifyImage:(UIImage*)theImage modification:(int)mod; +-(void) setImage:(UIImage*)theImage modification:(int)mod; +-(void) showLoadingWheel; +-(void) setCallbackOnImageTap:(id)obj method:(SEL)m; + +@end + + + + + diff --git a/HJCacheClasses/HJManagedImageV.m b/HJCacheClasses/HJManagedImageV.m new file mode 100644 index 0000000..5dca3bc --- /dev/null +++ b/HJCacheClasses/HJManagedImageV.m @@ -0,0 +1,169 @@ +// +// HJManagedImageV.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJManagedImageV.h" + + +@implementation HJManagedImageV + + +@synthesize oid; +@synthesize url; +@synthesize moHandler; + +@synthesize callbackOnSetImage; +@synthesize callbackOnCancel; +@synthesize imageView; +@synthesize modification; +@synthesize loadingWheel; +@synthesize index; + + +- (id)initWithFrame:(CGRect)frame { + if (self = [super initWithFrame:frame]) { + isCancelled=NO; + modification=0; + url=nil; + onImageTap = nil; + index = -1; + } + return self; +} + +- (void)dealloc { + [self clear]; + [super dealloc]; + //NSLog(@"ManagedImage dealloc"); +} + + +-(void) clear { + [self.moHandler removeUser:self]; + self.moHandler=nil; + self.image = nil; + self.imageView.image=nil; +} + +/* +-(void) clear { + self.url = nil; + self.callbackOnSetImage = nil; + //int rc1 = [image retainCount]; + [self.imageView removeFromSuperview]; + self.imageView = nil; + //int rc2 = [image retainCount]; + [image release]; image=nil; //do this instead of self.image=nil because setImage has more code + self.loadingWheel = nil; +} +*/ + + +-(void) changeManagedObjStateFromLoadedToReady { + //NSLog(@"managedStateReady %@",managedState); + if (moHandler.moData) { + moHandler.managedObj=[UIImage imageWithData:moHandler.moData]; + } else if (moHandler.moReadyDataFilename) { + moHandler.managedObj=[UIImage imageWithContentsOfFile:moHandler.moReadyDataFilename]; + } else { + //error? + NSLog(@"HJManagedImageV error in changeManagedObjStateFromLoadedToReady ?"); + } +} + +-(void) managedObjFailed { + NSLog(@"moHandlerFailed %@",moHandler); + [image release]; + image = nil; +} + +-(void) managedObjReady { + //NSLog(@"moHandlerReady %@",moHandler); + [self setImage:moHandler.managedObj]; +} + + +-(UIImage*) image { + return image; +} + +-(void) markCancelled { + isCancelled = YES; + [callbackOnCancel managedImageCancelled:self]; +} + +-(UIImage*) modifyImage:(UIImage*)theImage modification:(int)mod { + return theImage; +} + + +-(void) setImage:(UIImage*)theImage modification:(int)mod { + if (mod==modification) { + [self setImage:theImage]; + } else { + UIImage* modified = [self modifyImage:theImage modification:(int)mod]; + [self setImage:modified]; +//TODO [[ImageManager imageManager] cacheLoadedImage:self]; + } +} + + +-(void) setImage:(UIImage*)theImage { + if (theImage==image) { + //when the same image is on the screen multiple times, an image that is alredy set might be set again with the same image. + return; + } + [theImage retain]; + [image release]; + image = theImage; + + [imageView removeFromSuperview]; + self.imageView = [[[UIImageView alloc] initWithImage:theImage] autorelease]; + imageView.contentMode = UIViewContentModeScaleAspectFit; + imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth || UIViewAutoresizingFlexibleHeight ); + [self addSubview:imageView]; + imageView.frame = self.bounds; + [imageView setNeedsLayout]; + [self setNeedsLayout]; + //NSLog(@"setImageCallback from %@ to %@",self,callbackOnSetImage); + [loadingWheel stopAnimating]; + [loadingWheel removeFromSuperview]; + self.loadingWheel = nil; + self.hidden=NO; + [callbackOnSetImage managedImageSet:self]; +} + +-(void) showLoadingWheel { + [loadingWheel removeFromSuperview]; + self.loadingWheel = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray ]; + loadingWheel.center = self.center; + loadingWheel.hidesWhenStopped=YES; + [self addSubview:loadingWheel]; + [loadingWheel startAnimating]; +} + +-(void) setCallbackOnImageTap:(id)obj method:(SEL)m { + NSInvocation* invo = [NSInvocation invocationWithMethodSignature:[obj methodSignatureForSelector:m]]; + [invo setTarget:obj]; + [invo setSelector:m]; + [invo setArgument:&self atIndex:2]; + [invo retain]; + [onImageTap release]; + onImageTap = invo; +} + +-(void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { + if (onImageTap) { + [onImageTap invoke]; + } +} + + + + +@end diff --git a/HJCacheClasses/HJManagedImageVDelegate.h b/HJCacheClasses/HJManagedImageVDelegate.h new file mode 100644 index 0000000..60f6123 --- /dev/null +++ b/HJCacheClasses/HJManagedImageVDelegate.h @@ -0,0 +1,14 @@ +// +// HJManagedImageVDelegate.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import + +@class HJManagedImageV; + + diff --git a/HJCacheClasses/HJObjManager.h b/HJCacheClasses/HJObjManager.h new file mode 100644 index 0000000..b2cfe22 --- /dev/null +++ b/HJCacheClasses/HJObjManager.h @@ -0,0 +1,38 @@ +// +// HJObjManager.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import +#import "HJCircularBuffer.h" +#import "HJMOHandler.h" +#import "HJMOUser.h" +#import "HJMOPolicy.h" +#import "HJMOFileCache.h" + + +@interface HJObjManager : NSObject { + + HJMOPolicy* policy; + HJCircularBuffer* loadingHandlers; + HJCircularBuffer* memCache; + HJMOHandler* flyweightManagedState; + HJMOFileCache* fileCache; +} + +@property (nonatomic, retain) HJMOPolicy* policy; +@property (nonatomic, retain) HJCircularBuffer* loadingHandlers; +@property (nonatomic, retain) HJCircularBuffer* memCache; +@property (nonatomic, retain) HJMOFileCache* fileCache; + +-(HJObjManager*) initWithLoadingBufferSize:(int)loadingBufferSize memCacheSize:(int)memCacheSize; +-(HJObjManager*) init; + +-(BOOL) manage:(id)user; +-(void) handlerFinishedDownloading:(HJMOHandler*)handler; + +@end diff --git a/HJCacheClasses/HJObjManager.m b/HJCacheClasses/HJObjManager.m new file mode 100644 index 0000000..7a32aff --- /dev/null +++ b/HJCacheClasses/HJObjManager.m @@ -0,0 +1,109 @@ +// +// HJObjManager.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJObjManager.h" + + +@implementation HJObjManager + +@synthesize policy; +@synthesize loadingHandlers; +@synthesize memCache, fileCache; + + + +-(HJObjManager*) init { + return [self initWithLoadingBufferSize:12 memCacheSize:20]; +} + +-(HJObjManager*) initWithLoadingBufferSize:(int)loadingBufferSize memCacheSize:(int)memCacheSize { + [super init]; + self.policy = [HJMOPolicy smallImgFastScrollLRUCachePolicy]; + self.loadingHandlers = [HJCircularBuffer bufferWithCapacity:loadingBufferSize]; + self.memCache = [HJCircularBuffer bufferWithCapacity:memCacheSize]; + flyweightManagedState = [[HJMOHandler alloc] init]; + return self; +} + +-(void) dealloc { + self.loadingHandlers=nil; + self.memCache=nil; + self.policy=nil; + [flyweightManagedState release]; + [super dealloc]; +} + + +-(BOOL) manage:(id)user { + id oid; + if (! (oid=[user oid])) { + //oid is nil, try to use the url as the oid + if (! (oid=[user url])) { + //oid and url are nil, so can't manage this object + return NO; + } + + } + + //find handler for this oid in caches, or make a new handler. + HJMOHandler* handler; + BOOL handlerWasAllocedInThisCall=NO; + BOOL handlerWasAlreadyLoading=NO; + + //look in loadingHandlers first. + flyweightManagedState.oid = oid; + handler = [loadingHandlers findObject:flyweightManagedState]; + if (handler!=nil) { + //if handler from loadingHandlers, its probably in stateLoading, remember this so we don't add it to loadingHandlers again + handlerWasAlreadyLoading = (handler.state == stateLoading); + + } else { + //look in memCache for handler + handler = [memCache findObject:flyweightManagedState]; + + if (handler==nil) { + //was not in loadingHandlers or memCache. have to make a new handler to load image + handler = [[HJMOHandler alloc] initWithOid:user.oid url:user.url objManager:self]; + handlerWasAllocedInThisCall=YES; + } + } + + //now use the handler can be used, whatever state its in. + [handler addUser:user]; + [handler activateHandlerForUser:user]; //this can 'get things going' whatever state the handler is in + + //check if handler is loading and needs to be added to loadingHandlers buffer + if (!handlerWasAlreadyLoading && handler.state == stateLoading) { + //put in loadingHandlers, which is a cirular buffer so we might bump a handler out + HJMOHandler* bumpedHandler = (HJMOHandler*) [loadingHandlers addObject:handler]; + + //the whole point of the loadingHandlers is to limit how many handlers are loading at the same time, + // so if something gets bumped out of loadingHandlers, loading has to be cancelled and it won't go in to memCache. + // This is why the loadingHandlers should always be at least the number of managed objects on the screen at the same time, + // otherwise on-screen managed objects will get loading canceled. + // Can't just wait and cancel in dealloc because cell reuse typically means managed object users don't get + // dealloced until a cell gets reused. + [bumpedHandler cancelLoading]; //usually nil, but could be non nil when scrolling fast + } + + if (handlerWasAllocedInThisCall) { + [handler release]; + } + + return YES; //yes this object is now being managed. only NO if misused. +} + +-(void) handlerFinishedDownloading:(HJMOHandler*)handler { + [loadingHandlers removeObject:handler]; + [memCache addObject:handler]; //we can ignore any handler bumped from mem cache +} + + + +@end diff --git a/HJCacheClasses/HJWeakMutableArray.h b/HJCacheClasses/HJWeakMutableArray.h new file mode 100644 index 0000000..d5f5725 --- /dev/null +++ b/HJCacheClasses/HJWeakMutableArray.h @@ -0,0 +1,37 @@ +// +// HJWeakMutableArray.h +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import + + +@interface HJWeakMutableArray : NSObject { + NSMutableArray* array; +} + ++(HJWeakMutableArray*) arrayWithCapacity:(int)capacity; +-(HJWeakMutableArray*) initWithCapacity:(int)capacity; + +- (void) addObject:(id)anObject; +- (id) objectAtIndex:(int)i; +- (id) findObject:(id)obj; +- (void) removeObject:(id)obj; +- (int) count; +- (NSEnumerator*) objectEnumerator; + +@end + + +@interface HJWeakMutableArrayEnumerator : NSEnumerator { + NSEnumerator* arrayEnum; +} + +-(HJWeakMutableArrayEnumerator*)initWithInternalArray:(NSArray*)array; + +@end + diff --git a/HJCacheClasses/HJWeakMutableArray.m b/HJCacheClasses/HJWeakMutableArray.m new file mode 100644 index 0000000..4abaa93 --- /dev/null +++ b/HJCacheClasses/HJWeakMutableArray.m @@ -0,0 +1,144 @@ +// +// HJWeakMutableArray.m +// hjlib +// +// Copyright Hunter and Johnson 2009, 2010, 2011 +// HJCache may be used freely in any iOS or Mac application free or commercial. +// May be redistributed as source code only if all the original files are included. +// See http://www.markj.net + +#import "HJWeakMutableArray.h" + + +@implementation HJWeakMutableArray + ++(HJWeakMutableArray*) arrayWithCapacity:(int)capacity { + return [[[HJWeakMutableArray alloc] initWithCapacity:capacity] autorelease]; +} + +-(HJWeakMutableArray*) initWithCapacity:(int)capacity { + [super init]; + array = [[NSMutableArray arrayWithCapacity:capacity] retain]; + return self; +} + +-(void) dealloc { + [array release]; + [super dealloc]; +} + +- (void)addObject:(id)anObject { + [array addObject:[NSValue valueWithNonretainedObject:anObject]]; +} + +-(id)objectAtIndex:(int)i { + return [(NSValue*)[array objectAtIndex:i] nonretainedObjectValue]; +} + +- (void) removeObject:(id)objToRemove { + for (int i=0; i<[array count]; i++) { + NSValue* val = [array objectAtIndex:i]; + id obj = [val nonretainedObjectValue]; + if ([obj isEqual:objToRemove]) { + [array removeObjectAtIndex:i]; + return; + } + } + return; +} + +- (id) findObject:(id)obj { + for (int i=0; i<[array count]; i++) { + NSValue* val = [array objectAtIndex:i]; + id objI = [val nonretainedObjectValue]; + if ([objI isEqual:obj]) { + return objI; + } + } + return nil; +} + +-(int)count { + return [array count]; +} + +- (NSEnumerator*)objectEnumerator { + return [[[HJWeakMutableArrayEnumerator alloc] initWithInternalArray:array] autorelease]; +} + +- (NSString*)description { + NSMutableString* s = [NSMutableString stringWithCapacity:100]; + [s appendString:@"Weak array {\n"]; + for (NSValue* v in array) { + [s appendString:[[v nonretainedObjectValue] description]]; + [s appendString:@" "]; + [s appendFormat:@"%u",[[v nonretainedObjectValue] retainCount]]; + [s appendString:@"\n"]; + } + [s appendString:@"}"]; + return s; +} + ++(void)test { + /* + HJWeakMutableArray* array = [HJWeakMutableArray arrayWithCapacity:4]; + + NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; + + NSString* s = [[NSString stringWithFormat:@"zero"] retain]; + NSUInteger i1 = [s retainCount]; + [array addObject:s]; + NSUInteger i2 = [s retainCount]; + [array addObject:[[NSString stringWithFormat:@"one"] retain]]; + [array addObject:[[NSString stringWithFormat:@"two"] retain]]; + [array addObject:[NSString stringWithFormat:@"three"]]; + + for (id obj in [array objectEnumerator]) { + NSLog(@"obj %@ retain count %u",obj,[obj retainCount]); + } + + NSEnumerator* e = [array objectEnumerator]; + id obj = [e nextObject]; + id all = [e allObjects]; + + [pool drain]; + */ +} + + +@end + + +@implementation HJWeakMutableArrayEnumerator + +-(HJWeakMutableArrayEnumerator*)initWithInternalArray:(NSArray*)array { + arrayEnum = [array objectEnumerator]; + [arrayEnum retain]; + return self; +} + +-(void)dealloc { + [arrayEnum release]; + [super dealloc]; +} + +-(id)nextObject { + NSValue* val = (NSValue*)[arrayEnum nextObject]; + return [val nonretainedObjectValue]; +} + +-(NSArray*)allObjects { + NSMutableArray* all2 = [NSMutableArray arrayWithCapacity:10]; + for (NSValue* val in [arrayEnum allObjects]) { + //the value _does_ get retained here + [all2 addObject:[val nonretainedObjectValue]]; + } + return all2; +} + + + +@end + + + diff --git a/HJCache_Prefix.pch b/HJCache_Prefix.pch new file mode 100644 index 0000000..3d52534 --- /dev/null +++ b/HJCache_Prefix.pch @@ -0,0 +1,14 @@ +// +// Prefix header for all source files of the 'HJCache' target in the 'HJCache' project +// +#import + +#ifndef __IPHONE_3_0 +#warning "This project uses features only available in iPhone SDK 3.0 and later." +#endif + + +#ifdef __OBJC__ + #import + #import +#endif diff --git a/Images/0.png b/Images/0.png new file mode 100644 index 0000000..65b7f0e Binary files /dev/null and b/Images/0.png differ diff --git a/Images/1.png b/Images/1.png new file mode 100644 index 0000000..9f0bc12 Binary files /dev/null and b/Images/1.png differ diff --git a/Images/1.psd b/Images/1.psd new file mode 100644 index 0000000..89df813 Binary files /dev/null and b/Images/1.psd differ diff --git a/Images/2.png b/Images/2.png new file mode 100644 index 0000000..f2845c5 Binary files /dev/null and b/Images/2.png differ diff --git a/Images/3.png b/Images/3.png new file mode 100644 index 0000000..703ad27 Binary files /dev/null and b/Images/3.png differ diff --git a/Images/4.png b/Images/4.png new file mode 100644 index 0000000..1db53ef Binary files /dev/null and b/Images/4.png differ diff --git a/Images/5.png b/Images/5.png new file mode 100644 index 0000000..585ac5e Binary files /dev/null and b/Images/5.png differ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ed08a1c --- /dev/null +++ b/LICENSE @@ -0,0 +1,33 @@ + +This software is Copyright 2009, 2010, 2011 Hunter and Johnson +See http://www.markj.net/ + +The software may be compiled into a commercial product free of charge and without attribution. Ie +you are welcome to make any free or paid iOS apps using it, free of charge. +We'd like to hear about apps made using the software here: markj.net + +Permssion is hereby granted, free of charge, to any person +obtaining a copy of this software and associated documentation +files (the "Software"), to deal in the Software without +restriction, including without limitation the rights to use, +copy, modify, merge, publish or distribute, +copies of the Software, and to permit persons to whom the +Software is furnished to do so, subject to the following +conditions: + +All original files that comprise the software will be included in any source code distributions +of the softare, including this notice. + +The software may not be distributed as source code as part of a commercial product without +express written permission from Hunter and Johnson. Ie you can't resell this software as source +in your own commercial framework or libraries. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + diff --git a/MainWindow.xib b/MainWindow.xib new file mode 100644 index 0000000..4ecaccd --- /dev/null +++ b/MainWindow.xib @@ -0,0 +1,542 @@ + + + + 1024 + 10D571 + 786 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 112 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + IBCocoaTouchFramework + + + + 1316 + + {320, 480} + + 1 + MSAxIDEAA + + NO + NO + + IBCocoaTouchFramework + YES + + + + + 1 + + IBCocoaTouchFramework + NO + + + 256 + {0, 0} + NO + YES + YES + IBCocoaTouchFramework + + + YES + + + + IBCocoaTouchFramework + + + RootViewController + + + 1 + + IBCocoaTouchFramework + NO + + + + + + + YES + + + delegate + + + + 4 + + + + window + + + + 5 + + + + navigationController + + + + 15 + + + + + YES + + 0 + + + + + + 2 + + + YES + + + + + -1 + + + File's Owner + + + 3 + + + + + -2 + + + + + 9 + + + YES + + + + + + + 11 + + + + + 13 + + + YES + + + + + + 14 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 11.IBPluginDependency + 13.CustomClassName + 13.IBPluginDependency + 2.IBAttributePlaceholdersKey + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + 3.CustomClassName + 3.IBPluginDependency + 9.IBEditorWindowLastContentRect + 9.IBPluginDependency + + + YES + UIApplication + UIResponder + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + RootViewController + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + YES + + + YES + + + {{673, 376}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + HJCacheAppDelegate + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + {{186, 376}, {320, 480}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 16 + + + + YES + + RootViewController + UITableViewController + + IBProjectSource + Classes/RootViewController.h + + + + UIWindow + UIView + + IBUserSource + + + + + HJCacheAppDelegate + NSObject + + YES + + YES + navigationController + window + + + YES + UINavigationController + UIWindow + + + + YES + + YES + navigationController + window + + + YES + + navigationController + UINavigationController + + + window + UIWindow + + + + + IBProjectSource + Classes/HJCacheAppDelegate.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIApplication + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIApplication.h + + + + UIBarButtonItem + UIBarItem + + IBFrameworkSource + UIKit.framework/Headers/UIBarButtonItem.h + + + + UIBarItem + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIBarItem.h + + + + UINavigationBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UINavigationBar.h + + + + UINavigationController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UINavigationItem + NSObject + + + + UIResponder + NSObject + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UITableViewController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITableViewController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UIPopoverController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UISplitViewController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + UIWindow + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIWindow.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + HJCache.xcodeproj + 3 + 112 + + diff --git a/README b/README index f791774..829e216 100644 --- a/README +++ b/README @@ -4,5 +4,6 @@ and caching them. Its for iPhone / iOS, it works with data other than images too The library is designed to make it easy to make fast scrolling table views (for example) that contain imaged loaded from URLs. Eg a twitter app that shows the profile pic for each post in each table cell. - +HJCache was developed as 'HJ Managed Object' hence the 'MO' in the class names, but we renamed it HJCache +because most people who need it probably start off looking for caching libraries. diff --git a/RootViewController.xib b/RootViewController.xib new file mode 100644 index 0000000..4157671 --- /dev/null +++ b/RootViewController.xib @@ -0,0 +1,384 @@ + + + + 784 + 10D541 + 760 + 1038.29 + 460.00 + + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + 81 + + + YES + + + + YES + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + YES + + YES + + + YES + + + + YES + + IBFilesOwner + IBCocoaTouchFramework + + + IBFirstResponder + IBCocoaTouchFramework + + + + 274 + {320, 247} + + + 3 + MQA + + NO + YES + NO + IBCocoaTouchFramework + NO + 1 + 0 + YES + 44 + 22 + 22 + + + + + YES + + + view + + + + 3 + + + + dataSource + + + + 4 + + + + delegate + + + + 5 + + + + + YES + + 0 + + + + + + -1 + + + File's Owner + + + -2 + + + + + 2 + + + + + + + YES + + YES + -1.CustomClassName + -2.CustomClassName + 2.IBEditorWindowLastContentRect + 2.IBPluginDependency + + + YES + RootViewController + UIResponder + {{144, 609}, {320, 247}} + com.apple.InterfaceBuilder.IBCocoaTouchPlugin + + + + YES + + + YES + + + + + YES + + + YES + + + + 5 + + + + YES + + RootViewController + UITableViewController + + IBProjectSource + Classes/RootViewController.h + + + + + YES + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSError.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSFileManager.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueCoding.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyValueObserving.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSKeyedArchiver.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSNetServices.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSObject.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSPort.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSRunLoop.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSStream.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSThread.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURL.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSURLConnection.h + + + + NSObject + + IBFrameworkSource + Foundation.framework/Headers/NSXMLParser.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIAccessibility.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UINibLoading.h + + + + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UIResponder.h + + + + UIResponder + NSObject + + + + UIScrollView + UIView + + IBFrameworkSource + UIKit.framework/Headers/UIScrollView.h + + + + UISearchBar + UIView + + IBFrameworkSource + UIKit.framework/Headers/UISearchBar.h + + + + UISearchDisplayController + NSObject + + IBFrameworkSource + UIKit.framework/Headers/UISearchDisplayController.h + + + + UITableView + UIScrollView + + IBFrameworkSource + UIKit.framework/Headers/UITableView.h + + + + UITableViewController + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITableViewController.h + + + + UIView + + IBFrameworkSource + UIKit.framework/Headers/UITextField.h + + + + UIView + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIView.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UINavigationController.h + + + + UIViewController + + IBFrameworkSource + UIKit.framework/Headers/UITabBarController.h + + + + UIViewController + UIResponder + + IBFrameworkSource + UIKit.framework/Headers/UIViewController.h + + + + + 0 + IBCocoaTouchFramework + + com.apple.InterfaceBuilder.CocoaTouchPlugin.iPhoneOS + + + + com.apple.InterfaceBuilder.CocoaTouchPlugin.InterfaceBuilder3 + + + YES + HJCache.xcodeproj + 3 + 81 + + diff --git a/main.m b/main.m new file mode 100644 index 0000000..bb6f5f0 --- /dev/null +++ b/main.m @@ -0,0 +1,17 @@ +// +// main.m +// HJCache +// +// Created by Mark Johnson on 1/15/11. +// Copyright 2011 na. All rights reserved. +// + +#import + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + int retVal = UIApplicationMain(argc, argv, nil, nil); + [pool release]; + return retVal; +}