├── .gitattributes ├── .gitignore ├── Classes ├── AppDelegate.h ├── AppDelegate.m ├── MBSectionVC.h ├── MBSectionVC.m ├── MyViewController.h ├── MyViewController.m ├── Utilities │ ├── Alerts │ │ ├── PSAlertView.h │ │ └── PSAlertView.m │ ├── Controls │ │ ├── UICheckBox.h │ │ └── UICheckBox.m │ ├── Global Includes │ │ ├── Constants.h │ │ └── Macros.h │ ├── HTTP Requests │ │ ├── ASIAuthenticationDialog.h │ │ ├── ASIAuthenticationDialog.m │ │ ├── ASICacheDelegate.h │ │ ├── ASIDownloadCache.h │ │ ├── ASIDownloadCache.m │ │ ├── ASIFormDataRequest.h │ │ ├── ASIFormDataRequest.m │ │ ├── ASIHTTPRequest.h │ │ ├── ASIHTTPRequest.m │ │ ├── ASIHTTPRequestConfig.h │ │ ├── ASIHTTPRequestDelegate.h │ │ ├── ASIInputStream.h │ │ ├── ASIInputStream.m │ │ ├── ASINetworkQueue.h │ │ ├── ASINetworkQueue.m │ │ ├── ASIProgressDelegate.h │ │ ├── Reachability.h │ │ └── Reachability.m │ ├── ImageHelper.h │ ├── ImageHelper.m │ ├── Logging │ │ ├── GTMDefines.h │ │ ├── GTMGarbageCollection.h │ │ ├── GTMLogger.h │ │ └── GTMLogger.m │ ├── MBDataRequest.h │ ├── MBDataRequest.m │ ├── MBDataRequestDelegate.h │ ├── Object Additions │ │ ├── NSString-TruncateToWidth.h │ │ ├── NSString-TruncateToWidth.m │ │ ├── UIColor-Components.h │ │ ├── UIColor-Components.m │ │ ├── UIDevice-Helper.h │ │ └── UIDevice-Helper.m │ ├── Singleton │ │ └── SynthesizeSingleton.h │ └── XML │ │ ├── NSDataAdditions.h │ │ ├── NSDataAdditions.m │ │ ├── TBXML.h │ │ └── TBXML.m ├── View Controller │ ├── MBPageScrollVC.h │ ├── MBPageScrollVC.m │ ├── MBScrollingDelegate.h │ ├── MBScrollingVC.h │ ├── MBScrollingVC.m │ └── Table View Delegates & Data Sources │ │ ├── MBOverviewSectionDelegate.h │ │ ├── MBOverviewSectionDelegate.m │ │ ├── MBSectionDelegate.h │ │ └── MBSectionDelegate.m └── Views │ ├── MBPageScrollView.h │ ├── MBPageScrollView.m │ ├── MBSectionBackgroundView.h │ └── MBSectionBackgroundView.m ├── Info.plist ├── PageScrollView.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ ├── Matthias.xcuserdatad │ │ └── WorkspaceState.xcuserstate │ │ └── philip.xcuserdatad │ │ └── WorkspaceState.xcuserstate └── xcuserdata │ ├── Matthias.xcuserdatad │ ├── xcbreakpoints │ │ └── Breakpoints.xcbkptlist │ └── xcschemes │ │ ├── Mercedes.xcscheme │ │ ├── PageControl.xcscheme │ │ └── xcschememanagement.plist │ └── philip.xcuserdatad │ └── xcschemes │ ├── Mercedes.xcscheme │ └── xcschememanagement.plist ├── Prefix.pch ├── de.lproj └── Localizable.strings ├── en.lproj ├── Localizable.strings ├── MainWindow.xib └── MyView.xib ├── images ├── backgrounds │ ├── Home-iPad-L.png │ ├── Home-iPad.png │ └── Home.png └── iTunesArtwork └── main.m /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -crlf -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # xcode noise 2 | build 3 | *.pbxuser 4 | *.mode1v3 5 | *.perspectivev3 6 | 7 | # old scool 8 | .svn 9 | 10 | # osx noise 11 | .DS_Store 12 | profile -------------------------------------------------------------------------------- /Classes/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 27.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | 10 | #define MBApplicationDelegate ((AppDelegate*)[[UIApplication sharedApplication] delegate]) 11 | 12 | CGRect MBApplicationFrame(); 13 | 14 | #import 15 | #import "MBPageScrollVC.h" 16 | #import "MBPageScrollView.h" 17 | 18 | @interface AppDelegate : NSObject { 19 | // The Main Window 20 | UIWindow *window; 21 | // The Scrolling ViewController 22 | MBPageScrollVC *rootVC_; 23 | 24 | // The Delegates of the Sections 25 | NSMutableArray *sectionDelegates_; 26 | } 27 | 28 | // Properties 29 | @property (nonatomic, retain) IBOutlet UIWindow *window; 30 | @property (nonatomic, retain) IBOutlet MBPageScrollVC *rootVC; 31 | @property (nonatomic, retain) NSMutableArray *sectionDelegates; 32 | 33 | @property BOOL scrollEnabled; 34 | 35 | // Methods 36 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated; 37 | - (NSUInteger)currentPage; 38 | 39 | @end 40 | 41 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | #pragma mark - 43 | #pragma mark Class Extension for Private Methods 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | 46 | @interface AppDelegate () 47 | @end -------------------------------------------------------------------------------- /Classes/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 27.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "MyViewController.h" 11 | #import "MBSectionVC.h" 12 | #import "MBSectionDelegate.h" 13 | #import "MBOverviewSectionDelegate.h" 14 | 15 | // returns the application frame in the correct orientation 16 | CGRect MBApplicationFrame() { 17 | CGRect appFrame = [[UIScreen mainScreen] applicationFrame]; 18 | UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation]; 19 | int max = MAX(appFrame.size.width, appFrame.size.height); 20 | int min = MIN(appFrame.size.width, appFrame.size.height); 21 | 22 | if (UIInterfaceOrientationIsLandscape(orientation)) { 23 | return CGRectMake(0.f, 0.f, max, min); 24 | } else { 25 | return CGRectMake(0.f, 0.f, min, max); 26 | } 27 | } 28 | 29 | 30 | 31 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | #pragma mark - 33 | #pragma mark Globals 34 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 35 | 36 | static NSUInteger kNumberOfPages = 5; 37 | 38 | 39 | 40 | @implementation AppDelegate 41 | 42 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 43 | #pragma mark - 44 | #pragma mark Synthesized Properties 45 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 46 | 47 | @synthesize window; 48 | @synthesize rootVC = rootVC_; 49 | @synthesize sectionDelegates = sectionDelegates_; 50 | 51 | 52 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 53 | #pragma mark - 54 | #pragma mark Application Lifecycle 55 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 56 | 57 | - (void)dealloc { 58 | RELEASE(window); 59 | RELEASE(rootVC_); 60 | RELEASE(sectionDelegates_); 61 | 62 | [super dealloc]; 63 | } 64 | 65 | - (void)applicationDidFinishLaunching:(UIApplication *)application { 66 | // init application delegates 67 | sectionDelegates_ = [[NSMutableArray alloc] init]; 68 | // create scrolling ViewController 69 | self.rootVC = [[[MBPageScrollVC alloc] initWithNibName:nil bundle:nil] autorelease]; 70 | 71 | // add scrolling view to window 72 | [window addSubview:self.rootVC.view]; 73 | [window makeKeyAndVisible]; 74 | } 75 | 76 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 77 | #pragma mark - 78 | #pragma mark Methods 79 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 80 | 81 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated { 82 | [self.rootVC loadPage:page animated:animated]; 83 | } 84 | 85 | - (NSUInteger)currentPage { 86 | return self.rootVC.pageScrollView.pageControl.currentPage; 87 | } 88 | 89 | - (void)setScrollEnabled:(BOOL)enabled { 90 | self.rootVC.pageScrollView.scrollView.scrollEnabled = enabled; 91 | self.rootVC.pageScrollView.pageControl.hidden = !enabled; 92 | } 93 | 94 | - (BOOL)scrollEnabled { 95 | return self.rootVC.pageScrollView.scrollView.scrollEnabled; 96 | } 97 | 98 | 99 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 100 | #pragma mark - 101 | #pragma mark MBPageScrollViewDataSource-Protocol Methods 102 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 103 | 104 | - (NSUInteger)numberOfPages { 105 | return kNumberOfPages; 106 | } 107 | 108 | - (UIViewController *)viewControllerForPage:(NSUInteger)page { 109 | MBSectionVC *vc; 110 | MBSectionDelegate *delegate; 111 | 112 | switch (page) { 113 | case 0: 114 | case 1: 115 | vc = [[[MBSectionVC alloc] initWithNibName:nil bundle:nil backgroundImageName:@"Home"] autorelease]; 116 | delegate = [[[MBOverviewSectionDelegate alloc] initWithViewController:vc 117 | cellTitles:[NSArray arrayWithObjects:MBLocalize(@"NavCtrl.pushViewController"), MBLocalize(@"PresentModalVC"), nil]] autorelease]; 118 | vc.delegate = delegate; 119 | [self.sectionDelegates addObject:delegate]; 120 | break; 121 | 122 | default: 123 | vc = [[[MyViewController alloc] initWithPageNumber:page pop:YES] autorelease]; 124 | break; 125 | } 126 | 127 | UINavigationController *nc = [[[UINavigationController alloc] initWithRootViewController:vc] autorelease]; 128 | nc.navigationBarHidden = YES; 129 | nc.delegate = self; 130 | 131 | return nc; 132 | } 133 | 134 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 135 | #pragma mark - 136 | #pragma mark MBPageScrollViewDelegate-Protocol Methods 137 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 138 | 139 | - (void)didScrollToPage:(int)page { 140 | } 141 | 142 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 143 | #pragma mark - 144 | #pragma mark UINavigationControllerDelegate-Protocol Methods 145 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 146 | 147 | - (void)navigationController:(UINavigationController *)navigationController 148 | willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { 149 | [viewController viewWillAppear:animated]; 150 | 151 | // did it return to the first level? 152 | if ([viewController isKindOfClass:[MBSectionVC class]]) { 153 | self.scrollEnabled = YES; 154 | } 155 | 156 | } 157 | 158 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 159 | #pragma mark - 160 | #pragma mark Private Methods 161 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 162 | 163 | 164 | 165 | @end 166 | -------------------------------------------------------------------------------- /Classes/MBSectionVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBSectionTVC.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MBSectionBackgroundView.h" 11 | 12 | 13 | @class MBSectionDelegate; 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | #pragma mark - 17 | #pragma mark Base Class for all View Controllers that represent a Section 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | @interface MBSectionVC : UIViewController { 21 | // view for managing the background 22 | MBSectionBackgroundView *backgroundView_; 23 | // table view for displaying sections 24 | UITableView *tableView_; 25 | 26 | // table-view delegate and dataSource 27 | MBSectionDelegate *delegate_; 28 | } 29 | 30 | // Properties 31 | @property (nonatomic, retain) IBOutlet UIView *backgroundView; 32 | @property (nonatomic, assign) MBSectionDelegate *delegate; 33 | 34 | // initalizer 35 | - (id)initWithNibName:(NSString *)nibNameOrNil 36 | bundle:(NSBundle *)nibBundleOrNil 37 | backgroundImageName:(NSString *)imageName; 38 | 39 | @end 40 | 41 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 42 | #pragma mark - 43 | #pragma mark Class Extension for Private Methods 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | 46 | @interface MBSectionVC () 47 | - (CGRect)p_tableViewFrameForCurrentDevice; 48 | @end -------------------------------------------------------------------------------- /Classes/MBSectionVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBSectionTVC.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import "MBSectionVC.h" 10 | #import "MBSectionDelegate.h" 11 | 12 | #define CELL_HEIGHT 44.0 13 | #define CELL_WIDTH_IPAD 500.0 14 | 15 | #define MARGIN_BOTTOM_IPHONE 22.0 16 | #define MARGIN_BOTTOM_IPAD 55.0 17 | #define MARGIN_LEFT_IPAD 20.0 18 | 19 | #define degreesToRadian(x) (M_PI * (x) / 180.0) 20 | 21 | 22 | @implementation MBSectionVC 23 | 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | #pragma mark - 27 | #pragma mark Synthesized Properties 28 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | @synthesize backgroundView = backgroundView_; 31 | @synthesize delegate = delegate_; 32 | 33 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 34 | #pragma mark - 35 | #pragma mark View Lifecycle 36 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 37 | 38 | // the designated initializer 39 | - (id)initWithNibName:(NSString *)nibNameOrNil 40 | bundle:(NSBundle *)nibBundleOrNil 41 | backgroundImageName:(NSString *)imageName { 42 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 43 | // load background view 44 | backgroundView_ = [[MBSectionBackgroundView alloc] initWithFrame:MBApplicationFrame() 45 | imageName:imageName]; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | // the designated initializer of the superclass => overloaded 52 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 53 | return [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil backgroundImageName:nil]; 54 | } 55 | 56 | - (void)dealloc { 57 | RELEASE(backgroundView_); 58 | RELEASE(tableView_); 59 | 60 | [super dealloc]; 61 | } 62 | 63 | // Implement loadView to create a view hierarchy programmatically, without using a nib. 64 | - (void)loadView { 65 | UIView *v = [[[UIView alloc] initWithFrame:MBApplicationFrame()] autorelease]; 66 | // set own view 67 | self.view = v; 68 | 69 | // add background-view 70 | [self.view addSubview:self.backgroundView]; 71 | 72 | // add table-View 73 | if (self.delegate != nil) { 74 | tableView_ = [[UITableView alloc] initWithFrame:[self p_tableViewFrameForCurrentDevice] 75 | style:UITableViewStyleGrouped]; 76 | 77 | tableView_.dataSource = self.delegate; 78 | tableView_.delegate = self.delegate; 79 | tableView_.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 80 | tableView_.contentMode = UIViewContentModeLeft | UIViewContentModeBottom; 81 | tableView_.scrollEnabled = NO; 82 | // make table view-background transparent 83 | tableView_.backgroundColor = [UIColor clearColor]; 84 | tableView_.opaque = NO; 85 | tableView_.backgroundView = nil; 86 | [tableView_ reloadData]; 87 | 88 | [self.view addSubview:tableView_]; 89 | } 90 | 91 | self.view.backgroundColor = [UIColor colorWithRed:164/255.f green:172/255.f blue:179/255.f alpha:1.0f]; 92 | self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 93 | self.view.contentMode = UIViewContentModeScaleToFill; 94 | } 95 | 96 | /* 97 | - (void)viewDidLoad { 98 | [super viewDidLoad]; 99 | 100 | // Uncomment the following line to preserve selection between presentations. 101 | self.clearsSelectionOnViewWillAppear = NO; 102 | 103 | // Uncomment the following line to display an Edit button in the navigation bar for this view controller. 104 | // self.navigationItem.rightBarButtonItem = self.editButtonItem; 105 | } 106 | */ 107 | 108 | - (void)viewDidUnload { 109 | [super viewDidUnload]; 110 | 111 | // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand. 112 | self.backgroundView = nil; 113 | } 114 | 115 | - (void)didReceiveMemoryWarning { 116 | // Releases the view if it doesn't have a superview. 117 | [super didReceiveMemoryWarning]; 118 | 119 | // Relinquish ownership any cached data, images, etc that aren't in use. 120 | } 121 | 122 | 123 | 124 | - (void)viewWillAppear:(BOOL)animated { 125 | [super viewWillAppear:animated]; 126 | 127 | tableView_.alpha = 1.0; 128 | tableView_.frame = [self p_tableViewFrameForCurrentDevice]; 129 | } 130 | 131 | /* 132 | - (void)viewDidAppear:(BOOL)animated { 133 | [super viewDidAppear:animated]; 134 | } 135 | */ 136 | /* 137 | - (void)viewWillDisappear:(BOOL)animated { 138 | [super viewWillDisappear:animated]; 139 | } 140 | */ 141 | /* 142 | - (void)viewDidDisappear:(BOOL)animated { 143 | [super viewDidDisappear:animated]; 144 | } 145 | */ 146 | 147 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 148 | #pragma mark - 149 | #pragma mark Rotation 150 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 151 | 152 | // Override to allow orientations other than the default portrait orientation. 153 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 154 | // Return YES for supported orientations 155 | return ROTATE_ON_IPAD; 156 | } 157 | 158 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 159 | [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 160 | 161 | // clip to bounds during orientation to prevent one page from appearing on the next one during orientation 162 | //self.view.clipsToBounds = YES; 163 | 164 | [UIView beginAnimations:@"MoveTable" context:nil]; 165 | [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 166 | [UIView setAnimationDuration:0.1]; 167 | // fade out 168 | tableView_.alpha = 0.0; 169 | [UIView commitAnimations]; 170 | 171 | } 172 | 173 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 174 | [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; 175 | // stop clipping to bounds after orientation 176 | //self.view.clipsToBounds = NO; 177 | 178 | [UIView beginAnimations:@"MoveTable" context:nil]; 179 | [UIView setAnimationCurve:UIViewAnimationCurveLinear]; 180 | // compute new position of tableView 181 | tableView_.frame = [self p_tableViewFrameForCurrentDevice]; 182 | tableView_.alpha = 1.0; 183 | [UIView commitAnimations]; 184 | } 185 | 186 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 187 | #pragma mark - 188 | #pragma mark Private Methods 189 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 190 | 191 | - (CGRect)p_tableViewFrameForCurrentDevice { 192 | int numberOfRows = [delegate_ numberOfRows]; 193 | CGFloat marginLeft = 0.; 194 | CGFloat marginBottom = MARGIN_BOTTOM_IPHONE; 195 | CGFloat width = self.view.frame.size.width; 196 | CGFloat height = -1; 197 | 198 | if ([[UIDevice currentDevice] isIPad]) { 199 | marginLeft = MARGIN_LEFT_IPAD; 200 | width = CELL_WIDTH_IPAD; 201 | marginBottom = MARGIN_BOTTOM_IPAD; 202 | } 203 | 204 | height = numberOfRows * CELL_HEIGHT + marginBottom; 205 | 206 | return CGRectMake(self.view.frame.origin.x + marginLeft, self.view.frame.size.height - height, width, height); 207 | } 208 | 209 | @end 210 | 211 | -------------------------------------------------------------------------------- /Classes/MyViewController.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | 5 | 6 | @interface MyViewController : UIViewController { 7 | UILabel *pageNumberLabel; 8 | int pageNumber; 9 | BOOL pop_; 10 | } 11 | 12 | @property (nonatomic, retain) IBOutlet UILabel *pageNumberLabel; 13 | 14 | - (id)initWithPageNumber:(int)page pop:(BOOL)pop; 15 | 16 | - (IBAction)pop:(id)sender; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Classes/MyViewController.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "MyViewController.h" 4 | 5 | static NSArray *__pageControlColorList = nil; 6 | 7 | @implementation MyViewController 8 | 9 | @synthesize pageNumberLabel; 10 | 11 | // Creates the color list the first time this method is invoked. Returns one color object from the list. 12 | + (UIColor *)pageControlColorWithIndex:(NSUInteger)index { 13 | if (__pageControlColorList == nil) { 14 | __pageControlColorList = [[NSArray alloc] initWithObjects:[UIColor redColor], [UIColor greenColor], [UIColor magentaColor], 15 | [UIColor blueColor], [UIColor orangeColor], [UIColor brownColor], [UIColor grayColor], nil]; 16 | } 17 | 18 | // Mod the index by the list length to ensure access remains in bounds. 19 | return [__pageControlColorList objectAtIndex:index % [__pageControlColorList count]]; 20 | } 21 | 22 | // Load the view nib and initialize the pageNumber ivar. 23 | - (id)initWithPageNumber:(int)page pop:(BOOL)pop { 24 | if (self = [super initWithNibName:@"MyView" bundle:nil]) { 25 | pageNumber = page; 26 | pop_ = pop; 27 | self.view.backgroundColor = [MyViewController pageControlColorWithIndex:page]; 28 | } 29 | 30 | return self; 31 | } 32 | 33 | - (void)dealloc { 34 | [pageNumberLabel release]; 35 | [super dealloc]; 36 | } 37 | 38 | // Set the label and background color when the view has finished loading. 39 | - (void)viewDidLoad { 40 | pageNumberLabel.text = [NSString stringWithFormat:@"Page %d", pageNumber + 1]; 41 | } 42 | 43 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 44 | return YES; 45 | } 46 | 47 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 48 | NSLog(@"did rotate MyVC"); 49 | } 50 | 51 | - (IBAction)pop:(id)sender { 52 | if (pop_) { 53 | [self.navigationController popViewControllerAnimated:YES]; 54 | } else { 55 | [self dismissModalViewControllerAnimated:YES]; 56 | MBApplicationDelegate.scrollEnabled = YES; 57 | } 58 | 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Classes/Utilities/Alerts/PSAlertView.h: -------------------------------------------------------------------------------- 1 | // 2 | // PSAlertView.h 3 | // 4 | // Created by Peter Steinberger on 17.03.10. 5 | // Loosely based on Landon Fullers "Using Blocks", Plausible Labs Cooperative. 6 | // http://landonf.bikemonkey.org/code/iphone/Using_Blocks_1.20090704.html 7 | // 8 | 9 | #import 10 | 11 | @interface PSAlertView : NSObject { 12 | @private 13 | UIAlertView *alert_; 14 | NSMutableArray *blocks_; 15 | } 16 | 17 | + (PSAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message; 18 | 19 | - (id)initWithTitle:(NSString *)title message:(NSString *)message; 20 | 21 | - (void)setCancelButtonWithTitle:(NSString *)title block:(void (^)())block; 22 | - (void)addButtonWithTitle:(NSString *)title block:(void (^)())block; 23 | 24 | - (void)show; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Utilities/Alerts/PSAlertView.m: -------------------------------------------------------------------------------- 1 | // 2 | // PSAlertView.m 3 | // 4 | // Created by Peter Steinberger on 17.03.10. 5 | // Loosely based on Landon Fullers "Using Blocks", Plausible Labs Cooperative. 6 | // http://landonf.bikemonkey.org/code/iphone/Using_Blocks_1.20090704.html 7 | // 8 | 9 | #import "PSAlertView.h" 10 | 11 | @implementation PSAlertView 12 | 13 | /////////////////////////////////////////////////////////////////////////////////////////////////// 14 | #pragma mark - 15 | #pragma mark Static 16 | 17 | + (PSAlertView *)alertWithTitle:(NSString *)title message:(NSString *)message { 18 | return [[[PSAlertView alloc] initWithTitle:title message:message] autorelease]; 19 | } 20 | 21 | /////////////////////////////////////////////////////////////////////////////////////////////////// 22 | #pragma mark - 23 | #pragma mark NSObject 24 | 25 | - (id)initWithTitle:(NSString *)title message:(NSString *)message { 26 | if (!(self = [super init])) { 27 | return nil; 28 | } 29 | 30 | /* Initialize the alert */ 31 | alert_ = [[UIAlertView alloc] initWithTitle:title 32 | message:message 33 | delegate:self 34 | cancelButtonTitle:nil 35 | otherButtonTitles:nil]; 36 | 37 | /* Initialize button -> block array */ 38 | blocks_ = [[NSMutableArray alloc] init]; 39 | 40 | return self; 41 | } 42 | 43 | - (void)dealloc { 44 | alert_.delegate = nil; 45 | [alert_ release]; 46 | [blocks_ release]; 47 | 48 | [super dealloc]; 49 | } 50 | 51 | /////////////////////////////////////////////////////////////////////////////////////////////////// 52 | #pragma mark - 53 | #pragma mark Public 54 | 55 | - (void)setCancelButtonWithTitle:(NSString *)title block:(void (^)()) block { 56 | [self addButtonWithTitle:title block:block]; 57 | alert_.cancelButtonIndex = alert_.numberOfButtons - 1; 58 | } 59 | 60 | - (void)addButtonWithTitle:(NSString *)title block:(void (^)()) block { 61 | [blocks_ addObject:[[block copy] autorelease]]; 62 | [alert_ addButtonWithTitle:title]; 63 | } 64 | 65 | - (void)show { 66 | [alert_ show]; 67 | 68 | /* Ensure that the delegate (that's us) survives until the sheet is dismissed */ 69 | [self retain]; 70 | } 71 | 72 | /////////////////////////////////////////////////////////////////////////////////////////////////// 73 | #pragma mark - 74 | #pragma mark UIAlertViewDelegate 75 | 76 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 77 | /* Run the button's block */ 78 | if (buttonIndex >= 0 && buttonIndex < [blocks_ count]) { 79 | void (^b)() = [blocks_ objectAtIndex: buttonIndex]; 80 | b(); 81 | } 82 | 83 | /* AlertView to be dismissed, drop our self reference */ 84 | [self release]; 85 | } 86 | 87 | @end -------------------------------------------------------------------------------- /Classes/Utilities/Controls/UICheckBox.h: -------------------------------------------------------------------------------- 1 | // 2 | // UICheckBox.h 3 | // Less2Do 4 | // 5 | // Created by Matthias Tretter on 26.11.09. 6 | // Copyright 2009 BIAC. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | #pragma mark Custom Control representing a CheckBox 13 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | 16 | @interface UICheckBox : UIControl { 17 | // the image to display 18 | UIImageView* backgroundImage; 19 | // the state of the checkbox 20 | BOOL on; 21 | // the name of the On-Image 22 | NSString *imageNameOn; 23 | // the name of the Off-Image 24 | NSString *imageNameOff; 25 | } 26 | 27 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | #pragma mark Properties 29 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 30 | 31 | @property (nonatomic, retain, readwrite) UIImageView* backgroundImage; 32 | @property (nonatomic, copy) NSString *imageNameOn; 33 | @property (nonatomic, copy) NSString *imageNameOff; 34 | 35 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | #pragma mark Methods 37 | ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 38 | 39 | - (id)initWithFrame:(CGRect)frame; 40 | - (id)initWithFrame:(CGRect)frame andOnImage:(NSString *)imageOn andOffImage:(NSString *)imageOff; 41 | 42 | - (void)setOn:(BOOL)on; 43 | - (BOOL)isOn; 44 | 45 | - (void)setupUserInterface; 46 | - (void)toggle; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Classes/Utilities/Controls/UICheckBox.m: -------------------------------------------------------------------------------- 1 | // 2 | // UICheckBox.m 3 | // Less2Do 4 | // 5 | // Created by Matthias Tretter on 26.11.09. 6 | // Copyright 2009 BIAC. All rights reserved. 7 | // 8 | 9 | #import "UICheckBox.h" 10 | 11 | #define DEFAULT_ON_IMAGE @"task_on.png" 12 | #define DEFAULT_OFF_IMAGE @"task_off.png" 13 | 14 | @implementation UICheckBox 15 | 16 | @synthesize backgroundImage; 17 | @synthesize imageNameOn; 18 | @synthesize imageNameOff; 19 | 20 | 21 | - (id)initWithFrame:(CGRect)frame 22 | andOnImage:(NSString *)imageOn 23 | andOffImage:(NSString *)imageOff { 24 | if (self = [super initWithFrame:frame]) { 25 | on = NO; 26 | 27 | self.imageNameOn = imageOn; 28 | self.imageNameOff = imageOff; 29 | self.backgroundColor = [UIColor clearColor]; 30 | self.clipsToBounds = YES; 31 | self.autoresizesSubviews = NO; 32 | self.autoresizingMask = 0; 33 | self.opaque = YES; 34 | 35 | [self setupUserInterface]; 36 | } 37 | 38 | return self; 39 | } 40 | 41 | - (id)initWithFrame:(CGRect)frame { 42 | return [self initWithFrame:frame andOnImage:DEFAULT_ON_IMAGE andOffImage:DEFAULT_OFF_IMAGE]; 43 | } 44 | 45 | - (void)dealloc { 46 | [backgroundImage release]; 47 | [imageNameOn release]; 48 | [imageNameOff release]; 49 | 50 | [super dealloc]; 51 | } 52 | 53 | // Setup the user interface 54 | - (void)setupUserInterface { 55 | // Background image 56 | UIImage *image = [UIImage imageNamed:imageNameOff]; 57 | UIImageView* imageView = [[UIImageView alloc] 58 | initWithFrame:CGRectMake(0,0,image.size.width,image.size.height)]; 59 | 60 | imageView.image = image; 61 | imageView.backgroundColor = [UIColor clearColor]; 62 | imageView.contentMode = UIViewContentModeLeft; 63 | self.backgroundImage = imageView; 64 | 65 | [imageView release]; 66 | 67 | 68 | // Check for user input 69 | [self addTarget:self 70 | action:@selector(toggle) 71 | forControlEvents:UIControlEventTouchUpInside]; 72 | // add image-view 73 | [self addSubview:self.backgroundImage]; 74 | } 75 | 76 | - (void)setOn:(BOOL)isOn { 77 | on = isOn; 78 | 79 | if (on) { 80 | self.backgroundImage.image = [UIImage imageNamed:imageNameOn]; 81 | } else { 82 | self.backgroundImage.image = [UIImage imageNamed:imageNameOff]; 83 | } 84 | } 85 | 86 | - (BOOL)isOn { 87 | return on; 88 | } 89 | 90 | // Toggle state 91 | - (void)toggle { 92 | [self setOn:!on]; 93 | } 94 | 95 | @end -------------------------------------------------------------------------------- /Classes/Utilities/Global Includes/Constants.h: -------------------------------------------------------------------------------- 1 | // 2 | // Constants.h 3 | // FirstUniversal 4 | // 5 | // Created by Matthias Tretter on 25.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | #pragma mark - 12 | #pragma mark AutoRotation 13 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 14 | 15 | // Rotate to all Orientations on iPad, on iPhone support only Portrait Orientation 16 | #define ROTATE_ON_IPAD [[UIDevice currentDevice] isIPad] || interfaceOrientation == UIInterfaceOrientationPortrait 17 | 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | #pragma mark - 20 | #pragma mark Application Delegate 21 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 22 | 23 | #define MBApplicationDelegate ((AppDelegate*)[[UIApplication sharedApplication] delegate]) 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Classes/Utilities/Global Includes/Macros.h: -------------------------------------------------------------------------------- 1 | // 2 | // Macros.h 3 | // FirstUniversal 4 | // 5 | // Created by Matthias Tretter on 25.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | #pragma mark - 13 | #pragma mark Localization 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | // Shortcut for localized string, without comment 17 | #define MBLocalize(x) NSLocalizedString(x, nil) 18 | // Shortcut for getting a device-specific autoreleased Image 19 | #define MBImageNamed(x) ([UIImage imageNamed:MBDeviceSpecificImageName(x)]) 20 | // This Shortcut also takes Orientation on the iPad into account 21 | #define MBImageNamedForOrientation(x,o) ([UIImage imageNamed:MBDeviceSpecificImageNameForOrientation(x,o)]) 22 | 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | #pragma mark - 25 | #pragma mark Object Lifecycle 26 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 27 | 28 | // Releases an object an sets it to nil, for preventing memory errors when sending messages to deallocated objects 29 | #define RELEASE(x) ({[x release]; x = nil; }) 30 | 31 | 32 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 33 | #pragma mark - 34 | #pragma mark Version Numbers of iOS 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | 37 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_0 38 | #define kCFCoreFoundationVersionNumber_iPhoneOS_2_0 478.23 39 | #endif 40 | 41 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_1 42 | #define kCFCoreFoundationVersionNumber_iPhoneOS_2_1 478.26 43 | #endif 44 | 45 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_2 46 | #define kCFCoreFoundationVersionNumber_iPhoneOS_2_2 478.29 47 | #endif 48 | 49 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_0 50 | #define kCFCoreFoundationVersionNumber_iPhoneOS_3_0 478.47 51 | #endif 52 | 53 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_1 54 | #define kCFCoreFoundationVersionNumber_iPhoneOS_3_1 478.52 55 | #endif 56 | 57 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_2 58 | #define kCFCoreFoundationVersionNumber_iPhoneOS_3_2 478.61 59 | #endif 60 | 61 | #ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0 62 | #define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32 63 | #endif 64 | 65 | 66 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 67 | #pragma mark - 68 | #pragma mark Macros for Checking iOS Versions 69 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 70 | 71 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 72 | #define IF_IOS4_OR_GREATER(...) \ 73 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \ 74 | { \ 75 | __VA_ARGS__ \ 76 | } 77 | #else 78 | #define IF_IOS4_OR_GREATER(...) 79 | #endif 80 | 81 | 82 | #define IF_PRE_IOS4(...) \ 83 | if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \ 84 | { \ 85 | __VA_ARGS__ \ 86 | } 87 | 88 | 89 | #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200 90 | #define IF_IOS32_OR_GREATER(...) \ 91 | if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_2) \ 92 | { \ 93 | __VA_ARGS__ \ 94 | } 95 | #else 96 | #define IF_IOS32_OR_GREATER(...) 97 | #endif 98 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIAuthenticationDialog.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIAuthenticationDialog.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 21/08/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | @class ASIHTTPRequest; 12 | 13 | typedef enum _ASIAuthenticationType { 14 | ASIStandardAuthenticationType = 0, 15 | ASIProxyAuthenticationType = 1 16 | } ASIAuthenticationType; 17 | 18 | @interface ASIAutorotatingViewController : UIViewController 19 | @end 20 | 21 | @interface ASIAuthenticationDialog : ASIAutorotatingViewController { 22 | ASIHTTPRequest *request; 23 | ASIAuthenticationType type; 24 | UITableView *tableView; 25 | UIViewController *presentingController; 26 | BOOL didEnableRotationNotifications; 27 | } 28 | + (void)presentAuthenticationDialogForRequest:(ASIHTTPRequest *)request; 29 | + (void)dismiss; 30 | 31 | @property (retain) ASIHTTPRequest *request; 32 | @property (assign) ASIAuthenticationType type; 33 | @property (assign) BOOL didEnableRotationNotifications; 34 | @property (retain, nonatomic) UIViewController *presentingController; 35 | @end 36 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASICacheDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASICacheDelegate.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 01/05/2010. 6 | // Copyright 2010 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | @class ASIHTTPRequest; 11 | 12 | typedef enum _ASICachePolicy { 13 | ASIDefaultCachePolicy = 0, 14 | ASIIgnoreCachePolicy = 1, 15 | ASIReloadIfDifferentCachePolicy = 2, 16 | ASIOnlyLoadIfNotCachedCachePolicy = 3, 17 | ASIUseCacheIfLoadFailsCachePolicy = 4 18 | } ASICachePolicy; 19 | 20 | typedef enum _ASICacheStoragePolicy { 21 | ASICacheForSessionDurationCacheStoragePolicy = 0, 22 | ASICachePermanentlyCacheStoragePolicy = 1 23 | } ASICacheStoragePolicy; 24 | 25 | 26 | @protocol ASICacheDelegate 27 | 28 | @required 29 | 30 | // Should return the cache policy that will be used when requests have their cache policy set to ASIDefaultCachePolicy 31 | - (ASICachePolicy)defaultCachePolicy; 32 | 33 | // Should Remove cached data for a particular request 34 | - (void)removeCachedDataForRequest:(ASIHTTPRequest *)request; 35 | 36 | // Should return YES if the cache considers its cached response current for the request 37 | // Should return NO is the data is not cached, or (for example) if the cached headers state the request should have expired 38 | - (BOOL)isCachedDataCurrentForRequest:(ASIHTTPRequest *)request; 39 | 40 | // Should store the response for the passed request in the cache 41 | // When a non-zero maxAge is passed, it should be used as the expiry time for the cached response 42 | - (void)storeResponseForRequest:(ASIHTTPRequest *)request maxAge:(NSTimeInterval)maxAge; 43 | 44 | // Should return an NSDictionary of cached headers for the passed request, if it is stored in the cache 45 | - (NSDictionary *)cachedHeadersForRequest:(ASIHTTPRequest *)request; 46 | 47 | // Should return the cached body of a response for the passed request, if it is stored in the cache 48 | - (NSData *)cachedResponseDataForRequest:(ASIHTTPRequest *)request; 49 | 50 | // Same as the above, but returns a path to the cached response body instead 51 | - (NSString *)pathToCachedResponseDataForRequest:(ASIHTTPRequest *)request; 52 | 53 | // Clear cached data stored for the passed storage policy 54 | - (void)clearCachedResponsesForStoragePolicy:(ASICacheStoragePolicy)cachePolicy; 55 | @end 56 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIDownloadCache.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIDownloadCache.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 01/05/2010. 6 | // Copyright 2010 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ASICacheDelegate.h" 11 | 12 | @interface ASIDownloadCache : NSObject { 13 | 14 | // The default cache policy for this cache 15 | // Requests that store data in the cache will use this cache policy if their cache policy is set to ASIDefaultCachePolicy 16 | // Defaults to ASIReloadIfDifferentCachePolicy 17 | ASICachePolicy defaultCachePolicy; 18 | 19 | // The directory in which cached data will be stored 20 | // Defaults to a directory called 'ASIHTTPRequestCache' in the temporary directory 21 | NSString *storagePath; 22 | 23 | // Mediates access to the cache 24 | NSRecursiveLock *accessLock; 25 | 26 | // When YES, the cache will look for cache-control / pragma: no-cache headers, and won't reuse store responses if it finds them 27 | BOOL shouldRespectCacheControlHeaders; 28 | } 29 | 30 | // Returns a static instance of an ASIDownloadCache 31 | // In most circumstances, it will make sense to use this as a global cache, rather than creating your own cache 32 | // To make ASIHTTPRequests use it automatically, use [ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]]; 33 | + (id)sharedCache; 34 | 35 | // A helper function that determines if the server has requested data should not be cached by looking at the request's response headers 36 | + (BOOL)serverAllowsResponseCachingForRequest:(ASIHTTPRequest *)request; 37 | 38 | // A date formatter that can be used to construct an RFC 1123 date 39 | // The returned formatter is safe to use on the calling thread 40 | // Do not use this formatter for parsing dates because the format can vary slightly - use ASIHTTPRequest's dateFromRFC1123String: class method instead 41 | + (NSDateFormatter *)rfc1123DateFormatter; 42 | 43 | @property (assign, nonatomic) ASICachePolicy defaultCachePolicy; 44 | @property (retain, nonatomic) NSString *storagePath; 45 | @property (retain) NSRecursiveLock *accessLock; 46 | @property (assign) BOOL shouldRespectCacheControlHeaders; 47 | @end 48 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIFormDataRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIFormDataRequest.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 07/11/2008. 6 | // Copyright 2008-2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ASIHTTPRequest.h" 11 | #import "ASIHTTPRequestConfig.h" 12 | 13 | typedef enum _ASIPostFormat { 14 | ASIMultipartFormDataPostFormat = 0, 15 | ASIURLEncodedPostFormat = 1 16 | 17 | } ASIPostFormat; 18 | 19 | @interface ASIFormDataRequest : ASIHTTPRequest { 20 | 21 | // Parameters that will be POSTed to the url 22 | NSMutableArray *postData; 23 | 24 | // Files that will be POSTed to the url 25 | NSMutableArray *fileData; 26 | 27 | ASIPostFormat postFormat; 28 | 29 | NSStringEncoding stringEncoding; 30 | 31 | #if DEBUG_FORM_DATA_REQUEST 32 | // Will store a string version of the request body that will be printed to the console when ASIHTTPREQUEST_DEBUG is set in GCC_PREPROCESSOR_DEFINITIONS 33 | NSString *debugBodyString; 34 | #endif 35 | 36 | } 37 | 38 | #pragma mark utilities 39 | - (NSString*)encodeURL:(NSString *)string; 40 | 41 | #pragma mark setup request 42 | 43 | // Add a POST variable to the request 44 | - (void)addPostValue:(id )value forKey:(NSString *)key; 45 | 46 | // Set a POST variable for this request, clearing any others with the same key 47 | - (void)setPostValue:(id )value forKey:(NSString *)key; 48 | 49 | // Add the contents of a local file to the request 50 | - (void)addFile:(NSString *)filePath forKey:(NSString *)key; 51 | 52 | // Same as above, but you can specify the content-type and file name 53 | - (void)addFile:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key; 54 | 55 | // Add the contents of a local file to the request, clearing any others with the same key 56 | - (void)setFile:(NSString *)filePath forKey:(NSString *)key; 57 | 58 | // Same as above, but you can specify the content-type and file name 59 | - (void)setFile:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key; 60 | 61 | // Add the contents of an NSData object to the request 62 | - (void)addData:(NSData *)data forKey:(NSString *)key; 63 | 64 | // Same as above, but you can specify the content-type and file name 65 | - (void)addData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key; 66 | 67 | // Add the contents of an NSData object to the request, clearing any others with the same key 68 | - (void)setData:(NSData *)data forKey:(NSString *)key; 69 | 70 | // Same as above, but you can specify the content-type and file name 71 | - (void)setData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key; 72 | 73 | 74 | @property (assign) ASIPostFormat postFormat; 75 | @property (assign) NSStringEncoding stringEncoding; 76 | @end 77 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIFormDataRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASIFormDataRequest.m 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 07/11/2008. 6 | // Copyright 2008-2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import "ASIFormDataRequest.h" 10 | 11 | 12 | // Private stuff 13 | @interface ASIFormDataRequest () 14 | - (void)buildMultipartFormDataPostBody; 15 | - (void)buildURLEncodedPostBody; 16 | - (void)appendPostString:(NSString *)string; 17 | 18 | @property (retain) NSMutableArray *postData; 19 | @property (retain) NSMutableArray *fileData; 20 | 21 | #if DEBUG_FORM_DATA_REQUEST 22 | - (void)addToDebugBody:(NSString *)string; 23 | @property (retain, nonatomic) NSString *debugBodyString; 24 | #endif 25 | 26 | @end 27 | 28 | @implementation ASIFormDataRequest 29 | 30 | #pragma mark utilities 31 | - (NSString*)encodeURL:(NSString *)string 32 | { 33 | NSString *newString = NSMakeCollectable([(NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)string, NULL, CFSTR(":/?#[]@!$ &'()*+,;=\"<>%{}|\\^~`"), CFStringConvertNSStringEncodingToEncoding([self stringEncoding])) autorelease]); 34 | if (newString) { 35 | return newString; 36 | } 37 | return @""; 38 | } 39 | 40 | #pragma mark init / dealloc 41 | 42 | + (id)requestWithURL:(NSURL *)newURL 43 | { 44 | return [[[self alloc] initWithURL:newURL] autorelease]; 45 | } 46 | 47 | - (id)initWithURL:(NSURL *)newURL 48 | { 49 | self = [super initWithURL:newURL]; 50 | [self setPostFormat:ASIURLEncodedPostFormat]; 51 | [self setStringEncoding:NSUTF8StringEncoding]; 52 | return self; 53 | } 54 | 55 | - (void)dealloc 56 | { 57 | #if DEBUG_FORM_DATA_REQUEST 58 | [debugBodyString release]; 59 | #endif 60 | 61 | [postData release]; 62 | [fileData release]; 63 | [super dealloc]; 64 | } 65 | 66 | #pragma mark setup request 67 | 68 | - (void)addPostValue:(id )value forKey:(NSString *)key 69 | { 70 | if (![self postData]) { 71 | [self setPostData:[NSMutableArray array]]; 72 | } 73 | [[self postData] addObject:[NSDictionary dictionaryWithObjectsAndKeys:[value description],@"value",key,@"key",nil]]; 74 | } 75 | 76 | - (void)setPostValue:(id )value forKey:(NSString *)key 77 | { 78 | // Remove any existing value 79 | NSUInteger i; 80 | for (i=0; i<[[self postData] count]; i++) { 81 | NSDictionary *val = [[self postData] objectAtIndex:i]; 82 | if ([[val objectForKey:@"key"] isEqualToString:key]) { 83 | [[self postData] removeObjectAtIndex:i]; 84 | i--; 85 | } 86 | } 87 | [self addPostValue:value forKey:key]; 88 | } 89 | 90 | 91 | - (void)addFile:(NSString *)filePath forKey:(NSString *)key 92 | { 93 | [self addFile:filePath withFileName:nil andContentType:nil forKey:key]; 94 | } 95 | 96 | - (void)addFile:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key 97 | { 98 | if (![self fileData]) { 99 | [self setFileData:[NSMutableArray array]]; 100 | } 101 | 102 | // If data is a path to a local file 103 | if ([data isKindOfClass:[NSString class]]) { 104 | BOOL isDirectory = NO; 105 | BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:(NSString *)data isDirectory:&isDirectory]; 106 | if (!fileExists || isDirectory) { 107 | [self failWithError:[NSError errorWithDomain:NetworkRequestErrorDomain code:ASIInternalErrorWhileBuildingRequestType userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"No file exists at %@",data],NSLocalizedDescriptionKey,nil]]]; 108 | } 109 | 110 | // If the caller didn't specify a custom file name, we'll use the file name of the file we were passed 111 | if (!fileName) { 112 | fileName = [(NSString *)data lastPathComponent]; 113 | } 114 | 115 | // If we were given the path to a file, and the user didn't specify a mime type, we can detect it from the file extension 116 | if (!contentType) { 117 | contentType = [ASIHTTPRequest mimeTypeForFileAtPath:data]; 118 | } 119 | } 120 | 121 | NSDictionary *fileInfo = [NSDictionary dictionaryWithObjectsAndKeys:data, @"data", contentType, @"contentType", fileName, @"fileName", key, @"key", nil]; 122 | [[self fileData] addObject:fileInfo]; 123 | } 124 | 125 | 126 | - (void)setFile:(NSString *)filePath forKey:(NSString *)key 127 | { 128 | [self setFile:filePath withFileName:nil andContentType:nil forKey:key]; 129 | } 130 | 131 | - (void)setFile:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key 132 | { 133 | // Remove any existing value 134 | NSUInteger i; 135 | for (i=0; i<[[self fileData] count]; i++) { 136 | NSDictionary *val = [[self fileData] objectAtIndex:i]; 137 | if ([[val objectForKey:@"key"] isEqualToString:key]) { 138 | [[self fileData] removeObjectAtIndex:i]; 139 | i--; 140 | } 141 | } 142 | [self addFile:data withFileName:fileName andContentType:contentType forKey:key]; 143 | } 144 | 145 | - (void)addData:(NSData *)data forKey:(NSString *)key 146 | { 147 | [self addData:data withFileName:@"file" andContentType:nil forKey:key]; 148 | } 149 | 150 | - (void)addData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key 151 | { 152 | if (![self fileData]) { 153 | [self setFileData:[NSMutableArray array]]; 154 | } 155 | if (!contentType) { 156 | contentType = @"application/octet-stream"; 157 | } 158 | 159 | NSDictionary *fileInfo = [NSDictionary dictionaryWithObjectsAndKeys:data, @"data", contentType, @"contentType", fileName, @"fileName", key, @"key", nil]; 160 | [[self fileData] addObject:fileInfo]; 161 | } 162 | 163 | - (void)setData:(NSData *)data forKey:(NSString *)key 164 | { 165 | [self setData:data withFileName:@"file" andContentType:nil forKey:key]; 166 | } 167 | 168 | - (void)setData:(id)data withFileName:(NSString *)fileName andContentType:(NSString *)contentType forKey:(NSString *)key 169 | { 170 | // Remove any existing value 171 | NSUInteger i; 172 | for (i=0; i<[[self fileData] count]; i++) { 173 | NSDictionary *val = [[self fileData] objectAtIndex:i]; 174 | if ([[val objectForKey:@"key"] isEqualToString:key]) { 175 | [[self fileData] removeObjectAtIndex:i]; 176 | i--; 177 | } 178 | } 179 | [self addData:data withFileName:fileName andContentType:contentType forKey:key]; 180 | } 181 | 182 | - (void)buildPostBody 183 | { 184 | if ([self haveBuiltPostBody]) { 185 | return; 186 | } 187 | 188 | #if DEBUG_FORM_DATA_REQUEST 189 | [self setDebugBodyString:@""]; 190 | #endif 191 | 192 | if (![self postData] && ![self fileData]) { 193 | [super buildPostBody]; 194 | return; 195 | } 196 | if ([[self fileData] count] > 0) { 197 | [self setShouldStreamPostDataFromDisk:YES]; 198 | } 199 | 200 | if ([self postFormat] == ASIURLEncodedPostFormat) { 201 | [self buildURLEncodedPostBody]; 202 | } else { 203 | [self buildMultipartFormDataPostBody]; 204 | } 205 | 206 | [super buildPostBody]; 207 | 208 | #if DEBUG_FORM_DATA_REQUEST 209 | NSLog(@"%@",[self debugBodyString]); 210 | [self setDebugBodyString:nil]; 211 | #endif 212 | } 213 | 214 | 215 | - (void)buildMultipartFormDataPostBody 216 | { 217 | #if DEBUG_FORM_DATA_REQUEST 218 | [self addToDebugBody:@"\r\n==== Building a multipart/form-data body ====\r\n"]; 219 | #endif 220 | 221 | NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding([self stringEncoding])); 222 | 223 | // Set your own boundary string only if really obsessive. We don't bother to check if post data contains the boundary, since it's pretty unlikely that it does. 224 | NSString *stringBoundary = @"0xKhTmLbOuNdArY"; 225 | 226 | [self addRequestHeader:@"Content-Type" value:[NSString stringWithFormat:@"multipart/form-data; charset=%@; boundary=%@", charset, stringBoundary]]; 227 | 228 | [self appendPostString:[NSString stringWithFormat:@"--%@\r\n",stringBoundary]]; 229 | 230 | // Adds post data 231 | NSString *endItemBoundary = [NSString stringWithFormat:@"\r\n--%@\r\n",stringBoundary]; 232 | NSUInteger i=0; 233 | for (NSDictionary *val in [self postData]) { 234 | [self appendPostString:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n\r\n",[val objectForKey:@"key"]]]; 235 | [self appendPostString:[val objectForKey:@"value"]]; 236 | i++; 237 | if (i != [[self postData] count] || [[self fileData] count] > 0) { //Only add the boundary if this is not the last item in the post body 238 | [self appendPostString:endItemBoundary]; 239 | } 240 | } 241 | 242 | // Adds files to upload 243 | i=0; 244 | for (NSDictionary *val in [self fileData]) { 245 | 246 | [self appendPostString:[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", [val objectForKey:@"key"], [val objectForKey:@"fileName"]]]; 247 | [self appendPostString:[NSString stringWithFormat:@"Content-Type: %@\r\n\r\n", [val objectForKey:@"contentType"]]]; 248 | 249 | id data = [val objectForKey:@"data"]; 250 | if ([data isKindOfClass:[NSString class]]) { 251 | [self appendPostDataFromFile:data]; 252 | } else { 253 | [self appendPostData:data]; 254 | } 255 | i++; 256 | // Only add the boundary if this is not the last item in the post body 257 | if (i != [[self fileData] count]) { 258 | [self appendPostString:endItemBoundary]; 259 | } 260 | } 261 | 262 | [self appendPostString:[NSString stringWithFormat:@"\r\n--%@--\r\n",stringBoundary]]; 263 | 264 | #if DEBUG_FORM_DATA_REQUEST 265 | [self addToDebugBody:@"==== End of multipart/form-data body ====\r\n"]; 266 | #endif 267 | } 268 | 269 | - (void)buildURLEncodedPostBody 270 | { 271 | 272 | // We can't post binary data using application/x-www-form-urlencoded 273 | if ([[self fileData] count] > 0) { 274 | [self setPostFormat:ASIMultipartFormDataPostFormat]; 275 | [self buildMultipartFormDataPostBody]; 276 | return; 277 | } 278 | 279 | #if DEBUG_FORM_DATA_REQUEST 280 | [self addToDebugBody:@"\r\n==== Building an application/x-www-form-urlencoded body ====\r\n"]; 281 | #endif 282 | 283 | 284 | NSString *charset = (NSString *)CFStringConvertEncodingToIANACharSetName(CFStringConvertNSStringEncodingToEncoding([self stringEncoding])); 285 | 286 | [self addRequestHeader:@"Content-Type" value:[NSString stringWithFormat:@"application/x-www-form-urlencoded; charset=%@",charset]]; 287 | 288 | 289 | NSUInteger i=0; 290 | NSUInteger count = [[self postData] count]-1; 291 | for (NSDictionary *val in [self postData]) { 292 | NSString *data = [NSString stringWithFormat:@"%@=%@%@", [self encodeURL:[val objectForKey:@"key"]], [self encodeURL:[val objectForKey:@"value"]],(i http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 14/12/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | 10 | // ====== 11 | // Debug output configuration options 12 | // ====== 13 | 14 | // When set to 1 ASIHTTPRequests will print information about what a request is doing 15 | #ifndef DEBUG_REQUEST_STATUS 16 | #define DEBUG_REQUEST_STATUS 0 17 | #endif 18 | 19 | // When set to 1, ASIFormDataRequests will print information about the request body to the console 20 | #ifndef DEBUG_FORM_DATA_REQUEST 21 | #define DEBUG_FORM_DATA_REQUEST 0 22 | #endif 23 | 24 | // When set to 1, ASIHTTPRequests will print information about bandwidth throttling to the console 25 | #ifndef DEBUG_THROTTLING 26 | #define DEBUG_THROTTLING 0 27 | #endif 28 | 29 | // When set to 1, ASIHTTPRequests will print information about persistent connections to the console 30 | #ifndef DEBUG_PERSISTENT_CONNECTIONS 31 | #define DEBUG_PERSISTENT_CONNECTIONS 0 32 | #endif 33 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIHTTPRequestDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIHTTPRequestDelegate.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 13/04/2010. 6 | // Copyright 2010 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | @class ASIHTTPRequest; 10 | 11 | @protocol ASIHTTPRequestDelegate 12 | 13 | @optional 14 | 15 | // These are the default delegate methods for request status 16 | // You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector 17 | - (void)requestStarted:(ASIHTTPRequest *)request; 18 | - (void)requestReceivedResponseHeaders:(ASIHTTPRequest *)request; 19 | - (void)requestFinished:(ASIHTTPRequest *)request; 20 | - (void)requestFailed:(ASIHTTPRequest *)request; 21 | 22 | // When a delegate implements this method, it is expected to process all incoming data itself 23 | // This means that responseData / responseString / downloadDestinationPath etc are ignored 24 | // You can have the request call a different method by setting didReceiveDataSelector 25 | - (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data; 26 | 27 | // If a delegate implements one of these, it will be asked to supply credentials when none are available 28 | // The delegate can then either restart the request ([request retryUsingSuppliedCredentials]) once credentials have been set 29 | // or cancel it ([request cancelAuthentication]) 30 | - (void)authenticationNeededForRequest:(ASIHTTPRequest *)request; 31 | - (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIInputStream.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIInputStream.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 10/08/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class ASIHTTPRequest; 12 | 13 | // This is a wrapper for NSInputStream that pretends to be an NSInputStream itself 14 | // Subclassing NSInputStream seems to be tricky, and may involve overriding undocumented methods, so we'll cheat instead. 15 | // It is used by ASIHTTPRequest whenever we have a request body, and handles measuring and throttling the bandwidth used for uploading 16 | 17 | @interface ASIInputStream : NSObject { 18 | NSInputStream *stream; 19 | ASIHTTPRequest *request; 20 | } 21 | + (id)inputStreamWithFileAtPath:(NSString *)path request:(ASIHTTPRequest *)request; 22 | + (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)request; 23 | 24 | @property (retain, nonatomic) NSInputStream *stream; 25 | @property (assign, nonatomic) ASIHTTPRequest *request; 26 | @end 27 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIInputStream.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASIInputStream.m 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 10/08/2009. 6 | // Copyright 2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import "ASIInputStream.h" 10 | #import "ASIHTTPRequest.h" 11 | 12 | // Used to ensure only one request can read data at once 13 | static NSLock *readLock = nil; 14 | 15 | @implementation ASIInputStream 16 | 17 | + (void)initialize 18 | { 19 | if (self == [ASIInputStream class]) { 20 | readLock = [[NSLock alloc] init]; 21 | } 22 | } 23 | 24 | + (id)inputStreamWithFileAtPath:(NSString *)path request:(ASIHTTPRequest *)request 25 | { 26 | ASIInputStream *stream = [[[self alloc] init] autorelease]; 27 | [stream setRequest:request]; 28 | [stream setStream:[NSInputStream inputStreamWithFileAtPath:path]]; 29 | return stream; 30 | } 31 | 32 | + (id)inputStreamWithData:(NSData *)data request:(ASIHTTPRequest *)request 33 | { 34 | ASIInputStream *stream = [[[self alloc] init] autorelease]; 35 | [stream setRequest:request]; 36 | [stream setStream:[NSInputStream inputStreamWithData:data]]; 37 | return stream; 38 | } 39 | 40 | - (void)dealloc 41 | { 42 | [stream release]; 43 | [super dealloc]; 44 | } 45 | 46 | // Called when CFNetwork wants to read more of our request body 47 | // When throttling is on, we ask ASIHTTPRequest for the maximum amount of data we can read 48 | - (NSInteger)read:(uint8_t *)buffer maxLength:(NSUInteger)len 49 | { 50 | [readLock lock]; 51 | unsigned long toRead = len; 52 | if ([ASIHTTPRequest isBandwidthThrottled]) { 53 | toRead = [ASIHTTPRequest maxUploadReadLength]; 54 | if (toRead > len) { 55 | toRead = len; 56 | } else if (toRead == 0) { 57 | toRead = 1; 58 | } 59 | [request performThrottling]; 60 | } 61 | [ASIHTTPRequest incrementBandwidthUsedInLastSecond:toRead]; 62 | [readLock unlock]; 63 | return [stream read:buffer maxLength:toRead]; 64 | } 65 | 66 | /* 67 | * Implement NSInputStream mandatory methods to make sure they are implemented 68 | * (necessary for MacRuby for example) and avoir the overhead of method 69 | * forwarding for these common methods. 70 | */ 71 | - (void)open 72 | { 73 | [stream open]; 74 | } 75 | 76 | - (void)close 77 | { 78 | [stream close]; 79 | } 80 | 81 | - (id)delegate 82 | { 83 | return [stream delegate]; 84 | } 85 | 86 | - (void)setDelegate:(id)delegate 87 | { 88 | [stream setDelegate:delegate]; 89 | } 90 | 91 | - (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode 92 | { 93 | [stream scheduleInRunLoop:aRunLoop forMode:mode]; 94 | } 95 | 96 | - (void)removeFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode 97 | { 98 | [stream removeFromRunLoop:aRunLoop forMode:mode]; 99 | } 100 | 101 | - (id)propertyForKey:(NSString *)key 102 | { 103 | return [stream propertyForKey:key]; 104 | } 105 | 106 | - (BOOL)setProperty:(id)property forKey:(NSString *)key 107 | { 108 | return [stream setProperty:property forKey:key]; 109 | } 110 | 111 | - (NSStreamStatus)streamStatus 112 | { 113 | return [stream streamStatus]; 114 | } 115 | 116 | - (NSError *)streamError 117 | { 118 | return [stream streamError]; 119 | } 120 | 121 | // If we get asked to perform a method we don't have (probably internal ones), 122 | // we'll just forward the message to our stream 123 | 124 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector 125 | { 126 | return [stream methodSignatureForSelector:aSelector]; 127 | } 128 | 129 | - (void)forwardInvocation:(NSInvocation *)anInvocation 130 | { 131 | [anInvocation invokeWithTarget:stream]; 132 | } 133 | 134 | @synthesize stream; 135 | @synthesize request; 136 | @end 137 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASINetworkQueue.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASINetworkQueue.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 07/11/2008. 6 | // Copyright 2008-2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "ASIHTTPRequestDelegate.h" 11 | #import "ASIProgressDelegate.h" 12 | 13 | @interface ASINetworkQueue : NSOperationQueue { 14 | 15 | // Delegate will get didFail + didFinish messages (if set) 16 | id delegate; 17 | 18 | // Will be called when a request starts with the request as the argument 19 | SEL requestDidStartSelector; 20 | 21 | // Will be called when a request receives response headers with the request as the argument 22 | SEL requestDidReceiveResponseHeadersSelector; 23 | 24 | // Will be called when a request completes with the request as the argument 25 | SEL requestDidFinishSelector; 26 | 27 | // Will be called when a request fails with the request as the argument 28 | SEL requestDidFailSelector; 29 | 30 | // Will be called when the queue finishes with the queue as the argument 31 | SEL queueDidFinishSelector; 32 | 33 | // Upload progress indicator, probably an NSProgressIndicator or UIProgressView 34 | id uploadProgressDelegate; 35 | 36 | // Total amount uploaded so far for all requests in this queue 37 | unsigned long long bytesUploadedSoFar; 38 | 39 | // Total amount to be uploaded for all requests in this queue - requests add to this figure as they work out how much data they have to transmit 40 | unsigned long long totalBytesToUpload; 41 | 42 | // Download progress indicator, probably an NSProgressIndicator or UIProgressView 43 | id downloadProgressDelegate; 44 | 45 | // Total amount downloaded so far for all requests in this queue 46 | unsigned long long bytesDownloadedSoFar; 47 | 48 | // Total amount to be downloaded for all requests in this queue - requests add to this figure as they receive Content-Length headers 49 | unsigned long long totalBytesToDownload; 50 | 51 | // When YES, the queue will cancel all requests when a request fails. Default is YES 52 | BOOL shouldCancelAllRequestsOnFailure; 53 | 54 | //Number of real requests (excludes HEAD requests created to manage showAccurateProgress) 55 | int requestsCount; 56 | 57 | // When NO, this request will only update the progress indicator when it completes 58 | // When YES, this request will update the progress indicator according to how much data it has received so far 59 | // When YES, the queue will first perform HEAD requests for all GET requests in the queue, so it can calculate the total download size before it starts 60 | // NO means better performance, because it skips this step for GET requests, and it won't waste time updating the progress indicator until a request completes 61 | // Set to YES if the size of a requests in the queue varies greatly for much more accurate results 62 | // Default for requests in the queue is NO 63 | BOOL showAccurateProgress; 64 | 65 | // Storage container for additional queue information. 66 | NSDictionary *userInfo; 67 | 68 | } 69 | 70 | // Convenience constructor 71 | + (id)queue; 72 | 73 | // Call this to reset a queue - it will cancel all operations, clear delegates, and suspend operation 74 | - (void)reset; 75 | 76 | // Used internally to manage HEAD requests when showAccurateProgress is YES, do not use! 77 | - (void)addHEADOperation:(NSOperation *)operation; 78 | 79 | // All ASINetworkQueues are paused when created so that total size can be calculated before the queue starts 80 | // This method will start the queue 81 | - (void)go; 82 | 83 | @property (assign, nonatomic, setter=setUploadProgressDelegate:) id uploadProgressDelegate; 84 | @property (assign, nonatomic, setter=setDownloadProgressDelegate:) id downloadProgressDelegate; 85 | 86 | @property (assign) SEL requestDidStartSelector; 87 | @property (assign) SEL requestDidReceiveResponseHeadersSelector; 88 | @property (assign) SEL requestDidFinishSelector; 89 | @property (assign) SEL requestDidFailSelector; 90 | @property (assign) SEL queueDidFinishSelector; 91 | @property (assign) BOOL shouldCancelAllRequestsOnFailure; 92 | @property (assign) id delegate; 93 | @property (assign) BOOL showAccurateProgress; 94 | @property (assign, readonly) int requestsCount; 95 | @property (retain) NSDictionary *userInfo; 96 | 97 | @property (assign) unsigned long long bytesUploadedSoFar; 98 | @property (assign) unsigned long long totalBytesToUpload; 99 | @property (assign) unsigned long long bytesDownloadedSoFar; 100 | @property (assign) unsigned long long totalBytesToDownload; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASINetworkQueue.m: -------------------------------------------------------------------------------- 1 | // 2 | // ASINetworkQueue.m 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 07/11/2008. 6 | // Copyright 2008-2009 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | #import "ASINetworkQueue.h" 10 | #import "ASIHTTPRequest.h" 11 | 12 | // Private stuff 13 | @interface ASINetworkQueue () 14 | - (void)resetProgressDelegate:(id *)progressDelegate; 15 | @property (assign) int requestsCount; 16 | @end 17 | 18 | @implementation ASINetworkQueue 19 | 20 | - (id)init 21 | { 22 | self = [super init]; 23 | [self setShouldCancelAllRequestsOnFailure:YES]; 24 | [self setMaxConcurrentOperationCount:4]; 25 | [self setSuspended:YES]; 26 | 27 | return self; 28 | } 29 | 30 | + (id)queue 31 | { 32 | return [[[self alloc] init] autorelease]; 33 | } 34 | 35 | - (void)dealloc 36 | { 37 | //We need to clear the queue on any requests that haven't got around to cleaning up yet, as otherwise they'll try to let us know if something goes wrong, and we'll be long gone by then 38 | for (ASIHTTPRequest *request in [self operations]) { 39 | [request setQueue:nil]; 40 | } 41 | [userInfo release]; 42 | [super dealloc]; 43 | } 44 | 45 | - (void)setSuspended:(BOOL)suspend 46 | { 47 | [super setSuspended:suspend]; 48 | } 49 | 50 | - (void)reset 51 | { 52 | [self cancelAllOperations]; 53 | [self setDelegate:nil]; 54 | [self setDownloadProgressDelegate:nil]; 55 | [self setUploadProgressDelegate:nil]; 56 | [self setRequestDidStartSelector:NULL]; 57 | [self setRequestDidReceiveResponseHeadersSelector:NULL]; 58 | [self setRequestDidFailSelector:NULL]; 59 | [self setRequestDidFinishSelector:NULL]; 60 | [self setQueueDidFinishSelector:NULL]; 61 | [self setSuspended:YES]; 62 | } 63 | 64 | 65 | - (void)go 66 | { 67 | [self setSuspended:NO]; 68 | } 69 | 70 | - (void)cancelAllOperations 71 | { 72 | [self setBytesUploadedSoFar:0]; 73 | [self setTotalBytesToUpload:0]; 74 | [self setBytesDownloadedSoFar:0]; 75 | [self setTotalBytesToDownload:0]; 76 | [super cancelAllOperations]; 77 | } 78 | 79 | - (void)setUploadProgressDelegate:(id)newDelegate 80 | { 81 | uploadProgressDelegate = newDelegate; 82 | [self resetProgressDelegate:&uploadProgressDelegate]; 83 | 84 | } 85 | 86 | - (void)setDownloadProgressDelegate:(id)newDelegate 87 | { 88 | downloadProgressDelegate = newDelegate; 89 | [self resetProgressDelegate:&downloadProgressDelegate]; 90 | } 91 | 92 | - (void)resetProgressDelegate:(id *)progressDelegate 93 | { 94 | #if !TARGET_OS_IPHONE 95 | // If the uploadProgressDelegate is an NSProgressIndicator, we set its MaxValue to 1.0 so we can treat it similarly to UIProgressViews 96 | SEL selector = @selector(setMaxValue:); 97 | if ([*progressDelegate respondsToSelector:selector]) { 98 | double max = 1.0; 99 | [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&max]; 100 | } 101 | selector = @selector(setDoubleValue:); 102 | if ([*progressDelegate respondsToSelector:selector]) { 103 | double value = 0.0; 104 | [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value]; 105 | } 106 | #else 107 | SEL selector = @selector(setProgress:); 108 | if ([*progressDelegate respondsToSelector:selector]) { 109 | float value = 0.0f; 110 | [ASIHTTPRequest performSelector:selector onTarget:progressDelegate withObject:nil amount:&value]; 111 | } 112 | #endif 113 | } 114 | 115 | - (void)addHEADOperation:(NSOperation *)operation 116 | { 117 | if ([operation isKindOfClass:[ASIHTTPRequest class]]) { 118 | 119 | ASIHTTPRequest *request = (ASIHTTPRequest *)operation; 120 | [request setRequestMethod:@"HEAD"]; 121 | [request setQueuePriority:10]; 122 | [request setShowAccurateProgress:YES]; 123 | [request setQueue:self]; 124 | 125 | // Important - we are calling NSOperation's add method - we don't want to add this as a normal request! 126 | [super addOperation:request]; 127 | } 128 | } 129 | 130 | // Only add ASIHTTPRequests to this queue!! 131 | - (void)addOperation:(NSOperation *)operation 132 | { 133 | if (![operation isKindOfClass:[ASIHTTPRequest class]]) { 134 | [NSException raise:@"AttemptToAddInvalidRequest" format:@"Attempted to add an object that was not an ASIHTTPRequest to an ASINetworkQueue"]; 135 | } 136 | 137 | [self setRequestsCount:[self requestsCount]+1]; 138 | 139 | ASIHTTPRequest *request = (ASIHTTPRequest *)operation; 140 | 141 | if ([self showAccurateProgress]) { 142 | 143 | // Force the request to build its body (this may change requestMethod) 144 | [request buildPostBody]; 145 | 146 | // If this is a GET request and we want accurate progress, perform a HEAD request first to get the content-length 147 | // We'll only do this before the queue is started 148 | // If requests are added after the queue is started they will probably move the overall progress backwards anyway, so there's no value performing the HEAD requests first 149 | // Instead, they'll update the total progress if and when they receive a content-length header 150 | if ([[request requestMethod] isEqualToString:@"GET"]) { 151 | if ([self isSuspended]) { 152 | ASIHTTPRequest *HEADRequest = [request HEADRequest]; 153 | [self addHEADOperation:HEADRequest]; 154 | [request addDependency:HEADRequest]; 155 | if ([request shouldResetDownloadProgress]) { 156 | [self resetProgressDelegate:&downloadProgressDelegate]; 157 | [request setShouldResetDownloadProgress:NO]; 158 | } 159 | } 160 | } 161 | [request buildPostBody]; 162 | [self request:nil incrementUploadSizeBy:[request postLength]]; 163 | 164 | 165 | } else { 166 | [self request:nil incrementDownloadSizeBy:1]; 167 | [self request:nil incrementUploadSizeBy:1]; 168 | } 169 | // Tell the request not to increment the upload size when it starts, as we've already added its length 170 | if ([request shouldResetUploadProgress]) { 171 | [self resetProgressDelegate:&uploadProgressDelegate]; 172 | [request setShouldResetUploadProgress:NO]; 173 | } 174 | 175 | [request setShowAccurateProgress:[self showAccurateProgress]]; 176 | 177 | [request setQueue:self]; 178 | [super addOperation:request]; 179 | 180 | } 181 | 182 | - (void)requestStarted:(ASIHTTPRequest *)request 183 | { 184 | if ([self requestDidStartSelector]) { 185 | [[self delegate] performSelector:[self requestDidStartSelector] withObject:request]; 186 | } 187 | } 188 | 189 | - (void)requestReceivedResponseHeaders:(ASIHTTPRequest *)request 190 | { 191 | if ([self requestDidReceiveResponseHeadersSelector]) { 192 | [[self delegate] performSelector:[self requestDidReceiveResponseHeadersSelector] withObject:request]; 193 | } 194 | } 195 | 196 | 197 | - (void)requestFinished:(ASIHTTPRequest *)request 198 | { 199 | [self setRequestsCount:[self requestsCount]-1]; 200 | if ([self requestDidFinishSelector]) { 201 | [[self delegate] performSelector:[self requestDidFinishSelector] withObject:request]; 202 | } 203 | if ([self requestsCount] == 0) { 204 | if ([self queueDidFinishSelector]) { 205 | [[self delegate] performSelector:[self queueDidFinishSelector] withObject:self]; 206 | } 207 | } 208 | } 209 | 210 | - (void)requestFailed:(ASIHTTPRequest *)request 211 | { 212 | [self setRequestsCount:[self requestsCount]-1]; 213 | if ([self requestDidFailSelector]) { 214 | [[self delegate] performSelector:[self requestDidFailSelector] withObject:request]; 215 | } 216 | if ([self requestsCount] == 0) { 217 | if ([self queueDidFinishSelector]) { 218 | [[self delegate] performSelector:[self queueDidFinishSelector] withObject:self]; 219 | } 220 | } 221 | if ([self shouldCancelAllRequestsOnFailure] && [self requestsCount] > 0) { 222 | [self cancelAllOperations]; 223 | } 224 | 225 | } 226 | 227 | 228 | - (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes 229 | { 230 | [self setBytesDownloadedSoFar:[self bytesDownloadedSoFar]+bytes]; 231 | if ([self downloadProgressDelegate]) { 232 | [ASIHTTPRequest updateProgressIndicator:&downloadProgressDelegate withProgress:[self bytesDownloadedSoFar] ofTotal:[self totalBytesToDownload]]; 233 | } 234 | } 235 | 236 | - (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes 237 | { 238 | [self setBytesUploadedSoFar:[self bytesUploadedSoFar]+bytes]; 239 | if ([self uploadProgressDelegate]) { 240 | [ASIHTTPRequest updateProgressIndicator:&uploadProgressDelegate withProgress:[self bytesUploadedSoFar] ofTotal:[self totalBytesToUpload]]; 241 | } 242 | } 243 | 244 | - (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength 245 | { 246 | [self setTotalBytesToDownload:[self totalBytesToDownload]+newLength]; 247 | } 248 | 249 | - (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength 250 | { 251 | [self setTotalBytesToUpload:[self totalBytesToUpload]+newLength]; 252 | } 253 | 254 | 255 | // Since this queue takes over as the delegate for all requests it contains, it should forward authorisation requests to its own delegate 256 | - (void)authenticationNeededForRequest:(ASIHTTPRequest *)request 257 | { 258 | if ([[self delegate] respondsToSelector:@selector(authenticationNeededForRequest:)]) { 259 | [[self delegate] performSelector:@selector(authenticationNeededForRequest:) withObject:request]; 260 | } 261 | } 262 | 263 | - (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request 264 | { 265 | if ([[self delegate] respondsToSelector:@selector(proxyAuthenticationNeededForRequest:)]) { 266 | [[self delegate] performSelector:@selector(proxyAuthenticationNeededForRequest:) withObject:request]; 267 | } 268 | } 269 | 270 | 271 | - (BOOL)respondsToSelector:(SEL)selector 272 | { 273 | if (selector == @selector(authenticationNeededForRequest:)) { 274 | if ([[self delegate] respondsToSelector:@selector(authenticationNeededForRequest:)]) { 275 | return YES; 276 | } 277 | return NO; 278 | } else if (selector == @selector(proxyAuthenticationNeededForRequest:)) { 279 | if ([[self delegate] respondsToSelector:@selector(proxyAuthenticationNeededForRequest:)]) { 280 | return YES; 281 | } 282 | return NO; 283 | } 284 | return [super respondsToSelector:selector]; 285 | } 286 | 287 | #pragma mark NSCopying 288 | 289 | - (id)copyWithZone:(NSZone *)zone 290 | { 291 | ASINetworkQueue *newQueue = [[[self class] alloc] init]; 292 | [newQueue setDelegate:[self delegate]]; 293 | [newQueue setRequestDidStartSelector:[self requestDidStartSelector]]; 294 | [newQueue setRequestDidFinishSelector:[self requestDidFinishSelector]]; 295 | [newQueue setRequestDidFailSelector:[self requestDidFailSelector]]; 296 | [newQueue setQueueDidFinishSelector:[self queueDidFinishSelector]]; 297 | [newQueue setUploadProgressDelegate:[self uploadProgressDelegate]]; 298 | [newQueue setDownloadProgressDelegate:[self downloadProgressDelegate]]; 299 | [newQueue setShouldCancelAllRequestsOnFailure:[self shouldCancelAllRequestsOnFailure]]; 300 | [newQueue setShowAccurateProgress:[self showAccurateProgress]]; 301 | [newQueue setUserInfo:[[[self userInfo] copyWithZone:zone] autorelease]]; 302 | return newQueue; 303 | } 304 | 305 | 306 | @synthesize requestsCount; 307 | @synthesize bytesUploadedSoFar; 308 | @synthesize totalBytesToUpload; 309 | @synthesize bytesDownloadedSoFar; 310 | @synthesize totalBytesToDownload; 311 | @synthesize shouldCancelAllRequestsOnFailure; 312 | @synthesize uploadProgressDelegate; 313 | @synthesize downloadProgressDelegate; 314 | @synthesize requestDidStartSelector; 315 | @synthesize requestDidReceiveResponseHeadersSelector; 316 | @synthesize requestDidFinishSelector; 317 | @synthesize requestDidFailSelector; 318 | @synthesize queueDidFinishSelector; 319 | @synthesize delegate; 320 | @synthesize showAccurateProgress; 321 | @synthesize userInfo; 322 | @end 323 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/ASIProgressDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ASIProgressDelegate.h 3 | // Part of ASIHTTPRequest -> http://allseeing-i.com/ASIHTTPRequest 4 | // 5 | // Created by Ben Copsey on 13/04/2010. 6 | // Copyright 2010 All-Seeing Interactive. All rights reserved. 7 | // 8 | 9 | @class ASIHTTPRequest; 10 | 11 | @protocol ASIProgressDelegate 12 | 13 | @optional 14 | 15 | // These methods are used to update UIProgressViews (iPhone OS) or NSProgressIndicators (Mac OS X) 16 | // If you are using a custom progress delegate, you may find it easier to implement didReceiveBytes / didSendBytes instead 17 | #if TARGET_OS_IPHONE 18 | - (void)setProgress:(float)newProgress; 19 | #else 20 | - (void)setDoubleValue:(double)newProgress; 21 | - (void)setMaxValue:(double)newMax; 22 | #endif 23 | 24 | // Called when the request receives some data - bytes is the length of that data 25 | - (void)request:(ASIHTTPRequest *)request didReceiveBytes:(long long)bytes; 26 | 27 | // Called when the request sends some data 28 | // The first 32KB (128KB on older platforms) of data sent is not included in this amount because of limitations with the CFNetwork API 29 | // bytes may be less than zero if a request needs to remove upload progress (probably because the request needs to run again) 30 | - (void)request:(ASIHTTPRequest *)request didSendBytes:(long long)bytes; 31 | 32 | // Called when a request needs to change the length of the content to download 33 | - (void)request:(ASIHTTPRequest *)request incrementDownloadSizeBy:(long long)newLength; 34 | 35 | // Called when a request needs to change the length of the content to upload 36 | // newLength may be less than zero when a request needs to remove the size of the internal buffer from progress tracking 37 | - (void)request:(ASIHTTPRequest *)request incrementUploadSizeBy:(long long)newLength; 38 | @end 39 | -------------------------------------------------------------------------------- /Classes/Utilities/HTTP Requests/Reachability.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | File: Reachability.h 4 | Abstract: Basic demonstration of how to use the SystemConfiguration Reachablity APIs. 5 | 6 | Version: 2.0.4ddg 7 | */ 8 | 9 | /* 10 | Significant additions made by Andrew W. Donoho, August 11, 2009. 11 | This is a derived work of Apple's Reachability v2.0 class. 12 | 13 | The below license is the new BSD license with the OSI recommended personalizations. 14 | 15 | 16 | Extensions Copyright (C) 2009 Donoho Design Group, LLC. All Rights Reserved. 17 | 18 | Redistribution and use in source and binary forms, with or without 19 | modification, are permitted provided that the following conditions are 20 | met: 21 | 22 | * Redistributions of source code must retain the above copyright notice, 23 | this list of conditions and the following disclaimer. 24 | 25 | * Redistributions in binary form must reproduce the above copyright 26 | notice, this list of conditions and the following disclaimer in the 27 | documentation and/or other materials provided with the distribution. 28 | 29 | * Neither the name of Andrew W. Donoho nor Donoho Design Group, L.L.C. 30 | may be used to endorse or promote products derived from this software 31 | without specific prior written permission. 32 | 33 | THIS SOFTWARE IS PROVIDED BY DONOHO DESIGN GROUP, L.L.C. "AS IS" AND ANY 34 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 35 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 36 | PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 37 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 38 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 39 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 40 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 41 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 42 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 43 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 44 | 45 | */ 46 | 47 | 48 | /* 49 | 50 | Apple's Original License on Reachability v2.0 51 | 52 | Disclaimer: IMPORTANT: This Apple software is supplied to you by Apple Inc. 53 | ("Apple") in consideration of your agreement to the following terms, and your 54 | use, installation, modification or redistribution of this Apple software 55 | constitutes acceptance of these terms. If you do not agree with these terms, 56 | please do not use, install, modify or redistribute this Apple software. 57 | 58 | In consideration of your agreement to abide by the following terms, and subject 59 | to these terms, Apple grants you a personal, non-exclusive license, under 60 | Apple's copyrights in this original Apple software (the "Apple Software"), to 61 | use, reproduce, modify and redistribute the Apple Software, with or without 62 | modifications, in source and/or binary forms; provided that if you redistribute 63 | the Apple Software in its entirety and without modifications, you must retain 64 | this notice and the following text and disclaimers in all such redistributions 65 | of the Apple Software. 66 | 67 | Neither the name, trademarks, service marks or logos of Apple Inc. may be used 68 | to endorse or promote products derived from the Apple Software without specific 69 | prior written permission from Apple. Except as expressly stated in this notice, 70 | no other rights or licenses, express or implied, are granted by Apple herein, 71 | including but not limited to any patent rights that may be infringed by your 72 | derivative works or by other works in which the Apple Software may be 73 | incorporated. 74 | 75 | The Apple Software is provided by Apple on an "AS IS" basis. APPLE MAKES NO 76 | WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE IMPLIED 77 | WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR 78 | PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND OPERATION ALONE OR IN 79 | COMBINATION WITH YOUR PRODUCTS. 80 | 81 | IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL OR 82 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 83 | GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 84 | ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION, MODIFICATION AND/OR 85 | DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED AND WHETHER UNDER THEORY OF 86 | CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF 87 | APPLE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 88 | 89 | Copyright (C) 2009 Apple Inc. All Rights Reserved. 90 | 91 | */ 92 | 93 | 94 | /* 95 | DDG extensions include: 96 | Each reachability object now has a copy of the key used to store it in a 97 | dictionary. This allows each observer to quickly determine if the event is 98 | important to them. 99 | 100 | -currentReachabilityStatus also has a significantly different decision criteria than 101 | Apple's code. 102 | 103 | A multiple convenience test methods have been added. 104 | */ 105 | 106 | #import 107 | #import 108 | 109 | #define USE_DDG_EXTENSIONS 1 // Use DDG's Extensions to test network criteria. 110 | // Since NSAssert and NSCAssert are used in this code, 111 | // I recommend you set NS_BLOCK_ASSERTIONS=1 in the release versions of your projects. 112 | 113 | enum { 114 | 115 | // DDG NetworkStatus Constant Names. 116 | kNotReachable = 0, // Apple's code depends upon 'NotReachable' being the same value as 'NO'. 117 | kReachableViaWWAN, // Switched order from Apple's enum. WWAN is active before WiFi. 118 | kReachableViaWiFi 119 | 120 | }; 121 | typedef uint32_t NetworkStatus; 122 | 123 | enum { 124 | 125 | // Apple NetworkStatus Constant Names. 126 | NotReachable = kNotReachable, 127 | ReachableViaWiFi = kReachableViaWiFi, 128 | ReachableViaWWAN = kReachableViaWWAN 129 | 130 | }; 131 | 132 | 133 | extern NSString *const kInternetConnection; 134 | extern NSString *const kLocalWiFiConnection; 135 | extern NSString *const kReachabilityChangedNotification; 136 | 137 | @interface Reachability: NSObject { 138 | 139 | @private 140 | NSString *key_; 141 | SCNetworkReachabilityRef reachabilityRef; 142 | 143 | } 144 | 145 | @property (copy) NSString *key; // Atomic because network operations are asynchronous. 146 | 147 | // Designated Initializer. 148 | - (Reachability *) initWithReachabilityRef: (SCNetworkReachabilityRef) ref; 149 | 150 | // Use to check the reachability of a particular host name. 151 | + (Reachability *) reachabilityWithHostName: (NSString*) hostName; 152 | 153 | // Use to check the reachability of a particular IP address. 154 | + (Reachability *) reachabilityWithAddress: (const struct sockaddr_in*) hostAddress; 155 | 156 | // Use to check whether the default route is available. 157 | // Should be used to, at minimum, establish network connectivity. 158 | + (Reachability *) reachabilityForInternetConnection; 159 | 160 | // Use to check whether a local wifi connection is available. 161 | + (Reachability *) reachabilityForLocalWiFi; 162 | 163 | //Start listening for reachability notifications on the current run loop. 164 | - (BOOL) startNotifier; 165 | - (void) stopNotifier; 166 | 167 | // Comparison routines to enable choosing actions in a notification. 168 | - (BOOL) isEqual: (Reachability *) r; 169 | 170 | // These are the status tests. 171 | - (NetworkStatus) currentReachabilityStatus; 172 | 173 | // The main direct test of reachability. 174 | - (BOOL) isReachable; 175 | 176 | // WWAN may be available, but not active until a connection has been established. 177 | // WiFi may require a connection for VPN on Demand. 178 | - (BOOL) isConnectionRequired; // Identical DDG variant. 179 | - (BOOL) connectionRequired; // Apple's routine. 180 | 181 | // Dynamic, on demand connection? 182 | - (BOOL) isConnectionOnDemand; 183 | 184 | // Is user intervention required? 185 | - (BOOL) isInterventionRequired; 186 | 187 | // Routines for specific connection testing by your app. 188 | - (BOOL) isReachableViaWWAN; 189 | - (BOOL) isReachableViaWiFi; 190 | 191 | - (SCNetworkReachabilityFlags) reachabilityFlags; 192 | 193 | @end 194 | -------------------------------------------------------------------------------- /Classes/Utilities/ImageHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHelper.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | #pragma mark - 13 | #pragma mark Functions for managing device-specific images on iPhone/iPad 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | // returns the image name depending on the current device by appending "-iPad" when on iPad 17 | NSString* MBDeviceSpecificImageName(NSString *imageName); 18 | // takes the current orientation on iPad into account by appending "-iPad-L" when in Landscape-Mode, otherwise "-iPad" 19 | NSString* MBDeviceSpecificImageNameForOrientation(NSString *imageName, UIInterfaceOrientation orientation); -------------------------------------------------------------------------------- /Classes/Utilities/ImageHelper.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageHelper.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "ImageHelper.h" 10 | 11 | 12 | NSString* MBDeviceSpecificImageName(NSString *imageName) { 13 | // seperate extension from imageName 14 | NSArray *parts = [imageName componentsSeparatedByString:@"."]; 15 | // when on iPad, append "-iPad" 16 | NSString *iPadAppendix = [[UIDevice currentDevice] isIPad] ? @"-iPad" : @""; 17 | 18 | if (parts.count == 2) { 19 | return [NSString stringWithFormat:@"%@%@.%@", [parts objectAtIndex:0], iPadAppendix, [parts objectAtIndex:1]]; 20 | } else if (parts.count == 1) { 21 | // append .png per default 22 | return [NSString stringWithFormat:@"%@%@.png", [parts objectAtIndex:0], iPadAppendix]; 23 | } 24 | 25 | return nil; 26 | } 27 | 28 | NSString* MBDeviceSpecificImageNameForOrientation(NSString *imageName, UIInterfaceOrientation orientation) { 29 | // seperate extension from imageName 30 | NSArray *parts = [imageName componentsSeparatedByString:@"."]; 31 | // when on iPad, append "-iPad" 32 | NSString *iPadAppendix = [[UIDevice currentDevice] isIPad] ? @"-iPad" : @""; 33 | // when on iPad and orientation is Landscape, append "-iPad-L" 34 | NSString *orientationAppendix = [[UIDevice currentDevice] isIPad] && UIInterfaceOrientationIsLandscape(orientation) ? @"-L" : @""; 35 | 36 | if (parts.count == 2) { 37 | return [NSString stringWithFormat:@"%@%@%@.%@", [parts objectAtIndex:0], iPadAppendix, orientationAppendix, [parts objectAtIndex:1]]; 38 | } else if (parts.count == 1) { 39 | // append .png per default 40 | return [NSString stringWithFormat:@"%@%@%@.png", [parts objectAtIndex:0], iPadAppendix, orientationAppendix]; 41 | } 42 | 43 | return nil; 44 | } -------------------------------------------------------------------------------- /Classes/Utilities/Logging/GTMDefines.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMDefines.h 3 | // 4 | // Copyright 2008 Google Inc. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | // use this file except in compliance with the License. You may obtain a copy 8 | // of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | // License for the specific language governing permissions and limitations under 16 | // the License. 17 | // 18 | 19 | // ============================================================================ 20 | 21 | #include 22 | #include 23 | 24 | #if TARGET_OS_IPHONE 25 | #include 26 | #endif // TARGET_OS_IPHONE 27 | 28 | // Not all MAC_OS_X_VERSION_10_X macros defined in past SDKs 29 | #ifndef MAC_OS_X_VERSION_10_5 30 | #define MAC_OS_X_VERSION_10_5 1050 31 | #endif 32 | #ifndef MAC_OS_X_VERSION_10_6 33 | #define MAC_OS_X_VERSION_10_6 1060 34 | #endif 35 | 36 | // Not all __IPHONE_X macros defined in past SDKs 37 | #ifndef __IPHONE_2_1 38 | #define __IPHONE_2_1 20100 39 | #endif 40 | #ifndef __IPHONE_2_2 41 | #define __IPHONE_2_2 20200 42 | #endif 43 | #ifndef __IPHONE_3_0 44 | #define __IPHONE_3_0 30000 45 | #endif 46 | #ifndef __IPHONE_3_1 47 | #define __IPHONE_3_1 30100 48 | #endif 49 | #ifndef __IPHONE_3_2 50 | #define __IPHONE_3_2 30200 51 | #endif 52 | #ifndef __IPHONE_4_0 53 | #define __IPHONE_4_0 40000 54 | #endif 55 | 56 | // ---------------------------------------------------------------------------- 57 | // CPP symbols that can be overridden in a prefix to control how the toolbox 58 | // is compiled. 59 | // ---------------------------------------------------------------------------- 60 | 61 | 62 | // By setting the GTM_CONTAINERS_VALIDATION_FAILED_LOG and 63 | // GTM_CONTAINERS_VALIDATION_FAILED_ASSERT macros you can control what happens 64 | // when a validation fails. If you implement your own validators, you may want 65 | // to control their internals using the same macros for consistency. 66 | #ifndef GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 67 | #define GTM_CONTAINERS_VALIDATION_FAILED_ASSERT 0 68 | #endif 69 | 70 | // Give ourselves a consistent way to do inlines. Apple's macros even use 71 | // a few different actual definitions, so we're based off of the foundation 72 | // one. 73 | #if !defined(GTM_INLINE) 74 | #if defined (__GNUC__) && (__GNUC__ == 4) 75 | #define GTM_INLINE static __inline__ __attribute__((always_inline)) 76 | #else 77 | #define GTM_INLINE static __inline__ 78 | #endif 79 | #endif 80 | 81 | // Give ourselves a consistent way of doing externs that links up nicely 82 | // when mixing objc and objc++ 83 | #if !defined (GTM_EXTERN) 84 | #if defined __cplusplus 85 | #define GTM_EXTERN extern "C" 86 | #else 87 | #define GTM_EXTERN extern 88 | #endif 89 | #endif 90 | 91 | // Give ourselves a consistent way of exporting things if we have visibility 92 | // set to hidden. 93 | #if !defined (GTM_EXPORT) 94 | #define GTM_EXPORT __attribute__((visibility("default"))) 95 | #endif 96 | 97 | // _GTMDevLog & _GTMDevAssert 98 | // 99 | // _GTMDevLog & _GTMDevAssert are meant to be a very lightweight shell for 100 | // developer level errors. This implementation simply macros to NSLog/NSAssert. 101 | // It is not intended to be a general logging/reporting system. 102 | // 103 | // Please see http://code.google.com/p/google-toolbox-for-mac/wiki/DevLogNAssert 104 | // for a little more background on the usage of these macros. 105 | // 106 | // _GTMDevLog log some error/problem in debug builds 107 | // _GTMDevAssert assert if conditon isn't met w/in a method/function 108 | // in all builds. 109 | // 110 | // To replace this system, just provide different macro definitions in your 111 | // prefix header. Remember, any implementation you provide *must* be thread 112 | // safe since this could be called by anything in what ever situtation it has 113 | // been placed in. 114 | // 115 | 116 | // We only define the simple macros if nothing else has defined this. 117 | #ifndef _GTMDevLog 118 | 119 | #ifdef DEBUG 120 | #define _GTMDevLog(...) NSLog(__VA_ARGS__) 121 | #else 122 | #define _GTMDevLog(...) do { } while (0) 123 | #endif 124 | 125 | #endif // _GTMDevLog 126 | 127 | // Declared here so that it can easily be used for logging tracking if 128 | // necessary. See GTMUnitTestDevLog.h for details. 129 | @class NSString; 130 | GTM_EXTERN void _GTMUnitTestDevLog(NSString *format, ...); 131 | 132 | #ifndef _GTMDevAssert 133 | // we directly invoke the NSAssert handler so we can pass on the varargs 134 | // (NSAssert doesn't have a macro we can use that takes varargs) 135 | #if !defined(NS_BLOCK_ASSERTIONS) 136 | #define _GTMDevAssert(condition, ...) \ 137 | do { \ 138 | if (!(condition)) { \ 139 | [[NSAssertionHandler currentHandler] \ 140 | handleFailureInFunction:[NSString stringWithUTF8String:__PRETTY_FUNCTION__] \ 141 | file:[NSString stringWithUTF8String:__FILE__] \ 142 | lineNumber:__LINE__ \ 143 | description:__VA_ARGS__]; \ 144 | } \ 145 | } while(0) 146 | #else // !defined(NS_BLOCK_ASSERTIONS) 147 | #define _GTMDevAssert(condition, ...) do { } while (0) 148 | #endif // !defined(NS_BLOCK_ASSERTIONS) 149 | 150 | #endif // _GTMDevAssert 151 | 152 | // _GTMCompileAssert 153 | // _GTMCompileAssert is an assert that is meant to fire at compile time if you 154 | // want to check things at compile instead of runtime. For example if you 155 | // want to check that a wchar is 4 bytes instead of 2 you would use 156 | // _GTMCompileAssert(sizeof(wchar_t) == 4, wchar_t_is_4_bytes_on_OS_X) 157 | // Note that the second "arg" is not in quotes, and must be a valid processor 158 | // symbol in it's own right (no spaces, punctuation etc). 159 | 160 | // Wrapping this in an #ifndef allows external groups to define their own 161 | // compile time assert scheme. 162 | #ifndef _GTMCompileAssert 163 | // We got this technique from here: 164 | // http://unixjunkie.blogspot.com/2007/10/better-compile-time-asserts_29.html 165 | 166 | #define _GTMCompileAssertSymbolInner(line, msg) _GTMCOMPILEASSERT ## line ## __ ## msg 167 | #define _GTMCompileAssertSymbol(line, msg) _GTMCompileAssertSymbolInner(line, msg) 168 | #define _GTMCompileAssert(test, msg) \ 169 | typedef char _GTMCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ] 170 | #endif // _GTMCompileAssert 171 | 172 | // Macro to allow you to create NSStrings out of other macros. 173 | // #define FOO foo 174 | // NSString *fooString = GTM_NSSTRINGIFY(FOO); 175 | #if !defined (GTM_NSSTRINGIFY) 176 | #define GTM_NSSTRINGIFY_INNER(x) @#x 177 | #define GTM_NSSTRINGIFY(x) GTM_NSSTRINGIFY_INNER(x) 178 | #endif 179 | 180 | // Macro to allow fast enumeration when building for 10.5 or later, and 181 | // reliance on NSEnumerator for 10.4. Remember, NSDictionary w/ FastEnumeration 182 | // does keys, so pick the right thing, nothing is done on the FastEnumeration 183 | // side to be sure you're getting what you wanted. 184 | #ifndef GTM_FOREACH_OBJECT 185 | #if TARGET_OS_IPHONE || !(MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5) 186 | #define GTM_FOREACH_ENUMEREE(element, enumeration) \ 187 | for (element in enumeration) 188 | #define GTM_FOREACH_OBJECT(element, collection) \ 189 | for (element in collection) 190 | #define GTM_FOREACH_KEY(element, collection) \ 191 | for (element in collection) 192 | #else 193 | #define GTM_FOREACH_ENUMEREE(element, enumeration) \ 194 | for (NSEnumerator *_ ## element ## _enum = enumeration; \ 195 | (element = [_ ## element ## _enum nextObject]) != nil; ) 196 | #define GTM_FOREACH_OBJECT(element, collection) \ 197 | GTM_FOREACH_ENUMEREE(element, [collection objectEnumerator]) 198 | #define GTM_FOREACH_KEY(element, collection) \ 199 | GTM_FOREACH_ENUMEREE(element, [collection keyEnumerator]) 200 | #endif 201 | #endif 202 | 203 | // ============================================================================ 204 | 205 | // ---------------------------------------------------------------------------- 206 | // CPP symbols defined based on the project settings so the GTM code has 207 | // simple things to test against w/o scattering the knowledge of project 208 | // setting through all the code. 209 | // ---------------------------------------------------------------------------- 210 | 211 | // Provide a single constant CPP symbol that all of GTM uses for ifdefing 212 | // iPhone code. 213 | #if TARGET_OS_IPHONE // iPhone SDK 214 | // For iPhone specific stuff 215 | #define GTM_IPHONE_SDK 1 216 | #if TARGET_IPHONE_SIMULATOR 217 | #define GTM_IPHONE_SIMULATOR 1 218 | #else 219 | #define GTM_IPHONE_DEVICE 1 220 | #endif // TARGET_IPHONE_SIMULATOR 221 | #else 222 | // For MacOS specific stuff 223 | #define GTM_MACOS_SDK 1 224 | #endif 225 | 226 | // Some of our own availability macros 227 | #if GTM_MACOS_SDK 228 | #define GTM_AVAILABLE_ONLY_ON_IPHONE UNAVAILABLE_ATTRIBUTE 229 | #define GTM_AVAILABLE_ONLY_ON_MACOS 230 | #else 231 | #define GTM_AVAILABLE_ONLY_ON_IPHONE 232 | #define GTM_AVAILABLE_ONLY_ON_MACOS UNAVAILABLE_ATTRIBUTE 233 | #endif 234 | 235 | // Provide a symbol to include/exclude extra code for GC support. (This mainly 236 | // just controls the inclusion of finalize methods). 237 | #ifndef GTM_SUPPORT_GC 238 | #if GTM_IPHONE_SDK 239 | // iPhone never needs GC 240 | #define GTM_SUPPORT_GC 0 241 | #else 242 | // We can't find a symbol to tell if GC is supported/required, so best we 243 | // do on Mac targets is include it if we're on 10.5 or later. 244 | #if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 245 | #define GTM_SUPPORT_GC 0 246 | #else 247 | #define GTM_SUPPORT_GC 1 248 | #endif 249 | #endif 250 | #endif 251 | 252 | // To simplify support for 64bit (and Leopard in general), we provide the type 253 | // defines for non Leopard SDKs 254 | #if !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5) 255 | // NSInteger/NSUInteger and Max/Mins 256 | #ifndef NSINTEGER_DEFINED 257 | #if __LP64__ || NS_BUILD_32_LIKE_64 258 | typedef long NSInteger; 259 | typedef unsigned long NSUInteger; 260 | #else 261 | typedef int NSInteger; 262 | typedef unsigned int NSUInteger; 263 | #endif 264 | #define NSIntegerMax LONG_MAX 265 | #define NSIntegerMin LONG_MIN 266 | #define NSUIntegerMax ULONG_MAX 267 | #define NSINTEGER_DEFINED 1 268 | #endif // NSINTEGER_DEFINED 269 | // CGFloat 270 | #ifndef CGFLOAT_DEFINED 271 | #if defined(__LP64__) && __LP64__ 272 | // This really is an untested path (64bit on Tiger?) 273 | typedef double CGFloat; 274 | #define CGFLOAT_MIN DBL_MIN 275 | #define CGFLOAT_MAX DBL_MAX 276 | #define CGFLOAT_IS_DOUBLE 1 277 | #else /* !defined(__LP64__) || !__LP64__ */ 278 | typedef float CGFloat; 279 | #define CGFLOAT_MIN FLT_MIN 280 | #define CGFLOAT_MAX FLT_MAX 281 | #define CGFLOAT_IS_DOUBLE 0 282 | #endif /* !defined(__LP64__) || !__LP64__ */ 283 | #define CGFLOAT_DEFINED 1 284 | #endif // CGFLOAT_DEFINED 285 | #endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5 286 | 287 | // Some support for advanced clang static analysis functionality 288 | // See http://clang-analyzer.llvm.org/annotations.html 289 | #ifndef __has_feature // Optional. 290 | #define __has_feature(x) 0 // Compatibility with non-clang compilers. 291 | #endif 292 | 293 | #ifndef NS_RETURNS_RETAINED 294 | #if __has_feature(attribute_ns_returns_retained) 295 | #define NS_RETURNS_RETAINED __attribute__((ns_returns_retained)) 296 | #else 297 | #define NS_RETURNS_RETAINED 298 | #endif 299 | #endif 300 | 301 | #ifndef NS_RETURNS_NOT_RETAINED 302 | #if __has_feature(attribute_ns_returns_not_retained) 303 | #define NS_RETURNS_NOT_RETAINED __attribute__((ns_returns_not_retained)) 304 | #else 305 | #define NS_RETURNS_NOT_RETAINED 306 | #endif 307 | #endif 308 | 309 | #ifndef CF_RETURNS_RETAINED 310 | #if __has_feature(attribute_cf_returns_retained) 311 | #define CF_RETURNS_RETAINED __attribute__((cf_returns_retained)) 312 | #else 313 | #define CF_RETURNS_RETAINED 314 | #endif 315 | #endif 316 | 317 | #ifndef CF_RETURNS_NOT_RETAINED 318 | #if __has_feature(attribute_cf_returns_not_retained) 319 | #define CF_RETURNS_NOT_RETAINED __attribute__((cf_returns_not_retained)) 320 | #else 321 | #define CF_RETURNS_NOT_RETAINED 322 | #endif 323 | #endif 324 | 325 | // Defined on 10.6 and above. 326 | #ifndef NS_FORMAT_ARGUMENT 327 | #define NS_FORMAT_ARGUMENT(A) 328 | #endif 329 | 330 | // Defined on 10.6 and above. 331 | #ifndef NS_FORMAT_FUNCTION 332 | #define NS_FORMAT_FUNCTION(F,A) 333 | #endif 334 | 335 | #ifndef GTM_NONNULL 336 | #define GTM_NONNULL(x) __attribute__((nonnull(x))) 337 | #endif 338 | 339 | // To simplify support for both Leopard and Snow Leopard we declare 340 | // the Snow Leopard protocols that we need here. 341 | #if !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) 342 | #define GTM_10_6_PROTOCOLS_DEFINED 1 343 | @protocol NSConnectionDelegate 344 | @end 345 | @protocol NSAnimationDelegate 346 | @end 347 | @protocol NSImageDelegate 348 | @end 349 | @protocol NSTabViewDelegate 350 | @end 351 | #endif // !defined(GTM_10_6_PROTOCOLS_DEFINED) && !(MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6) 352 | -------------------------------------------------------------------------------- /Classes/Utilities/Logging/GTMGarbageCollection.h: -------------------------------------------------------------------------------- 1 | // 2 | // GTMGarbageCollection.h 3 | // 4 | // Copyright 2007-2008 Google Inc. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | // use this file except in compliance with the License. You may obtain a copy 8 | // of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | // License for the specific language governing permissions and limitations under 16 | // the License. 17 | // 18 | 19 | #import 20 | 21 | #import "GTMDefines.h" 22 | 23 | // This allows us to easily move our code from GC to non GC. 24 | // They are no-ops unless we are require Leopard or above. 25 | // See 26 | // http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/index.html 27 | // and 28 | // http://developer.apple.com/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html#//apple_ref/doc/uid/TP40006687-SW1 29 | // for details. 30 | 31 | #if (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5) && !GTM_IPHONE_SDK 32 | // General use would be to call this through GTMCFAutorelease 33 | // but there may be a reason the you want to make something collectable 34 | // but not autoreleased, especially in pure GC code where you don't 35 | // want to bother with the nop autorelease. Done as a define instead of an 36 | // inline so that tools like Clang's scan-build don't report code as leaking. 37 | #define GTMNSMakeCollectable(cf) ((id)NSMakeCollectable(cf)) 38 | 39 | // GTMNSMakeUncollectable is for global maps, etc. that we don't 40 | // want released ever. You should still retain these in non-gc code. 41 | GTM_INLINE void GTMNSMakeUncollectable(id object) { 42 | [[NSGarbageCollector defaultCollector] disableCollectorForPointer:object]; 43 | } 44 | 45 | // Hopefully no code really needs this, but GTMIsGarbageCollectionEnabled is 46 | // a common way to check at runtime if GC is on. 47 | // There are some places where GC doesn't work w/ things w/in Apple's 48 | // frameworks, so this is here so GTM unittests and detect it, and not run 49 | // individual tests to work around bugs in Apple's frameworks. 50 | GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) { 51 | return ([NSGarbageCollector defaultCollector] != nil); 52 | } 53 | 54 | #else 55 | 56 | #define GTMNSMakeCollectable(cf) ((id)(cf)) 57 | 58 | GTM_INLINE void GTMNSMakeUncollectable(id object) { 59 | } 60 | 61 | GTM_INLINE BOOL GTMIsGarbageCollectionEnabled(void) { 62 | return NO; 63 | } 64 | 65 | #endif 66 | 67 | // GTMCFAutorelease makes a CF object collectable in GC mode, or adds it 68 | // to the autorelease pool in non-GC mode. Either way it is taken care 69 | // of. Done as a define instead of an inline so that tools like Clang's 70 | // scan-build don't report code as leaking. 71 | #define GTMCFAutorelease(cf) ([GTMNSMakeCollectable(cf) autorelease]) 72 | 73 | -------------------------------------------------------------------------------- /Classes/Utilities/Logging/GTMLogger.m: -------------------------------------------------------------------------------- 1 | // 2 | // GTMLogger.m 3 | // 4 | // Copyright 2007-2008 Google Inc. 5 | // 6 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not 7 | // use this file except in compliance with the License. You may obtain a copy 8 | // of the License at 9 | // 10 | // http://www.apache.org/licenses/LICENSE-2.0 11 | // 12 | // Unless required by applicable law or agreed to in writing, software 13 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | // License for the specific language governing permissions and limitations under 16 | // the License. 17 | // 18 | 19 | #import "GTMLogger.h" 20 | #import "GTMGarbageCollection.h" 21 | #import 22 | #import 23 | #import 24 | #import 25 | 26 | 27 | // Define a trivial assertion macro to avoid dependencies 28 | #ifdef DEBUG 29 | #define GTMLOGGER_ASSERT(expr) assert(expr) 30 | #else 31 | #define GTMLOGGER_ASSERT(expr) 32 | #endif 33 | 34 | 35 | @interface GTMLogger (PrivateMethods) 36 | 37 | - (void)logInternalFunc:(const char *)func 38 | format:(NSString *)fmt 39 | valist:(va_list)args 40 | level:(GTMLoggerLevel)level NS_FORMAT_FUNCTION(2, 0); 41 | 42 | @end 43 | 44 | 45 | // Reference to the shared GTMLogger instance. This is not a singleton, it's 46 | // just an easy reference to one shared instance. 47 | static GTMLogger *gSharedLogger = nil; 48 | 49 | 50 | @implementation GTMLogger 51 | 52 | // Returns a pointer to the shared logger instance. If none exists, a standard 53 | // logger is created and returned. 54 | + (id)sharedLogger { 55 | @synchronized(self) { 56 | if (gSharedLogger == nil) { 57 | gSharedLogger = [[self standardLogger] retain]; 58 | } 59 | GTMLOGGER_ASSERT(gSharedLogger != nil); 60 | } 61 | return [[gSharedLogger retain] autorelease]; 62 | } 63 | 64 | + (void)setSharedLogger:(GTMLogger *)logger { 65 | @synchronized(self) { 66 | [gSharedLogger autorelease]; 67 | gSharedLogger = [logger retain]; 68 | } 69 | } 70 | 71 | + (id)standardLogger { 72 | id writer = [NSFileHandle fileHandleWithStandardOutput]; 73 | id fr = [[[GTMLogStandardFormatter alloc] init] autorelease]; 74 | id filter = [[[GTMLogLevelFilter alloc] init] autorelease]; 75 | return [self loggerWithWriter:writer formatter:fr filter:filter]; 76 | } 77 | 78 | + (id)standardLoggerWithStderr { 79 | id me = [self standardLogger]; 80 | [me setWriter:[NSFileHandle fileHandleWithStandardError]]; 81 | return me; 82 | } 83 | 84 | + (id)standardLoggerWithPath:(NSString *)path { 85 | NSFileHandle *fh = [NSFileHandle fileHandleForLoggingAtPath:path mode:0644]; 86 | if (fh == nil) return nil; 87 | id me = [self standardLogger]; 88 | [me setWriter:fh]; 89 | return me; 90 | } 91 | 92 | + (id)loggerWithWriter:(id)writer 93 | formatter:(id)formatter 94 | filter:(id)filter { 95 | return [[[self alloc] initWithWriter:writer 96 | formatter:formatter 97 | filter:filter] autorelease]; 98 | } 99 | 100 | + (id)logger { 101 | return [[[self alloc] init] autorelease]; 102 | } 103 | 104 | - (id)init { 105 | return [self initWithWriter:nil formatter:nil filter:nil]; 106 | } 107 | 108 | - (id)initWithWriter:(id)writer 109 | formatter:(id)formatter 110 | filter:(id)filter { 111 | if ((self = [super init])) { 112 | [self setWriter:writer]; 113 | [self setFormatter:formatter]; 114 | [self setFilter:filter]; 115 | GTMLOGGER_ASSERT(formatter_ != nil); 116 | GTMLOGGER_ASSERT(filter_ != nil); 117 | GTMLOGGER_ASSERT(writer_ != nil); 118 | } 119 | return self; 120 | } 121 | 122 | - (void)dealloc { 123 | GTMLOGGER_ASSERT(writer_ != nil); 124 | GTMLOGGER_ASSERT(formatter_ != nil); 125 | GTMLOGGER_ASSERT(filter_ != nil); 126 | [writer_ release]; 127 | [formatter_ release]; 128 | [filter_ release]; 129 | [super dealloc]; 130 | } 131 | 132 | - (id)writer { 133 | GTMLOGGER_ASSERT(writer_ != nil); 134 | return [[writer_ retain] autorelease]; 135 | } 136 | 137 | - (void)setWriter:(id)writer { 138 | @synchronized(self) { 139 | [writer_ autorelease]; 140 | if (writer == nil) 141 | writer_ = [[NSFileHandle fileHandleWithStandardOutput] retain]; 142 | else 143 | writer_ = [writer retain]; 144 | } 145 | GTMLOGGER_ASSERT(writer_ != nil); 146 | } 147 | 148 | - (id)formatter { 149 | GTMLOGGER_ASSERT(formatter_ != nil); 150 | return [[formatter_ retain] autorelease]; 151 | } 152 | 153 | - (void)setFormatter:(id)formatter { 154 | @synchronized(self) { 155 | [formatter_ autorelease]; 156 | if (formatter == nil) 157 | formatter_ = [[GTMLogBasicFormatter alloc] init]; 158 | else 159 | formatter_ = [formatter retain]; 160 | } 161 | GTMLOGGER_ASSERT(formatter_ != nil); 162 | } 163 | 164 | - (id)filter { 165 | GTMLOGGER_ASSERT(filter_ != nil); 166 | return [[filter_ retain] autorelease]; 167 | } 168 | 169 | - (void)setFilter:(id)filter { 170 | @synchronized(self) { 171 | [filter_ autorelease]; 172 | if (filter == nil) 173 | filter_ = [[GTMLogNoFilter alloc] init]; 174 | else 175 | filter_ = [filter retain]; 176 | } 177 | GTMLOGGER_ASSERT(filter_ != nil); 178 | } 179 | 180 | - (void)logDebug:(NSString *)fmt, ... { 181 | va_list args; 182 | va_start(args, fmt); 183 | [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelDebug]; 184 | va_end(args); 185 | } 186 | 187 | - (void)logInfo:(NSString *)fmt, ... { 188 | va_list args; 189 | va_start(args, fmt); 190 | [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelInfo]; 191 | va_end(args); 192 | } 193 | 194 | - (void)logError:(NSString *)fmt, ... { 195 | va_list args; 196 | va_start(args, fmt); 197 | [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelError]; 198 | va_end(args); 199 | } 200 | 201 | - (void)logAssert:(NSString *)fmt, ... { 202 | va_list args; 203 | va_start(args, fmt); 204 | [self logInternalFunc:NULL format:fmt valist:args level:kGTMLoggerLevelAssert]; 205 | va_end(args); 206 | } 207 | 208 | @end // GTMLogger 209 | 210 | 211 | @implementation GTMLogger (GTMLoggerMacroHelpers) 212 | 213 | - (void)logFuncDebug:(const char *)func msg:(NSString *)fmt, ... { 214 | va_list args; 215 | va_start(args, fmt); 216 | [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelDebug]; 217 | va_end(args); 218 | } 219 | 220 | - (void)logFuncInfo:(const char *)func msg:(NSString *)fmt, ... { 221 | va_list args; 222 | va_start(args, fmt); 223 | [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelInfo]; 224 | va_end(args); 225 | } 226 | 227 | - (void)logFuncError:(const char *)func msg:(NSString *)fmt, ... { 228 | va_list args; 229 | va_start(args, fmt); 230 | [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelError]; 231 | va_end(args); 232 | } 233 | 234 | - (void)logFuncAssert:(const char *)func msg:(NSString *)fmt, ... { 235 | va_list args; 236 | va_start(args, fmt); 237 | [self logInternalFunc:func format:fmt valist:args level:kGTMLoggerLevelAssert]; 238 | va_end(args); 239 | } 240 | 241 | @end // GTMLoggerMacroHelpers 242 | 243 | 244 | @implementation GTMLogger (PrivateMethods) 245 | 246 | - (void)logInternalFunc:(const char *)func 247 | format:(NSString *)fmt 248 | valist:(va_list)args 249 | level:(GTMLoggerLevel)level { 250 | GTMLOGGER_ASSERT(formatter_ != nil); 251 | GTMLOGGER_ASSERT(filter_ != nil); 252 | GTMLOGGER_ASSERT(writer_ != nil); 253 | 254 | NSString *fname = func ? [NSString stringWithUTF8String:func] : nil; 255 | NSString *msg = [formatter_ stringForFunc:fname 256 | withFormat:fmt 257 | valist:args 258 | level:level]; 259 | if (msg && [filter_ filterAllowsMessage:msg level:level]) 260 | [writer_ logMessage:msg level:level]; 261 | } 262 | 263 | @end // PrivateMethods 264 | 265 | 266 | @implementation NSFileHandle (GTMFileHandleLogWriter) 267 | 268 | + (id)fileHandleForLoggingAtPath:(NSString *)path mode:(mode_t)mode { 269 | int fd = -1; 270 | if (path) { 271 | int flags = O_WRONLY | O_APPEND | O_CREAT; 272 | fd = open([path fileSystemRepresentation], flags, mode); 273 | } 274 | if (fd == -1) return nil; 275 | return [[[self alloc] initWithFileDescriptor:fd 276 | closeOnDealloc:YES] autorelease]; 277 | } 278 | 279 | - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { 280 | @synchronized(self) { 281 | NSString *line = [NSString stringWithFormat:@"%@\n", msg]; 282 | [self writeData:[line dataUsingEncoding:NSUTF8StringEncoding]]; 283 | } 284 | } 285 | 286 | @end // GTMFileHandleLogWriter 287 | 288 | 289 | @implementation NSArray (GTMArrayCompositeLogWriter) 290 | 291 | - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { 292 | @synchronized(self) { 293 | id child = nil; 294 | GTM_FOREACH_OBJECT(child, self) { 295 | if ([child conformsToProtocol:@protocol(GTMLogWriter)]) 296 | [child logMessage:msg level:level]; 297 | } 298 | } 299 | } 300 | 301 | @end // GTMArrayCompositeLogWriter 302 | 303 | 304 | @implementation GTMLogger (GTMLoggerLogWriter) 305 | 306 | - (void)logMessage:(NSString *)msg level:(GTMLoggerLevel)level { 307 | switch (level) { 308 | case kGTMLoggerLevelDebug: 309 | [self logDebug:@"%@", msg]; 310 | break; 311 | case kGTMLoggerLevelInfo: 312 | [self logInfo:@"%@", msg]; 313 | break; 314 | case kGTMLoggerLevelError: 315 | [self logError:@"%@", msg]; 316 | break; 317 | case kGTMLoggerLevelAssert: 318 | [self logAssert:@"%@", msg]; 319 | break; 320 | default: 321 | // Ignore the message. 322 | break; 323 | } 324 | } 325 | 326 | @end // GTMLoggerLogWriter 327 | 328 | 329 | @implementation GTMLogBasicFormatter 330 | 331 | - (NSString *)stringForFunc:(NSString *)func 332 | withFormat:(NSString *)fmt 333 | valist:(va_list)args 334 | level:(GTMLoggerLevel)level { 335 | // Performance note: We may want to do a quick check here to see if |fmt| 336 | // contains a '%', and if not, simply return 'fmt'. 337 | return [[[NSString alloc] initWithFormat:fmt arguments:args] autorelease]; 338 | } 339 | 340 | @end // GTMLogBasicFormatter 341 | 342 | 343 | @implementation GTMLogStandardFormatter 344 | 345 | - (id)init { 346 | if ((self = [super init])) { 347 | dateFormatter_ = [[NSDateFormatter alloc] init]; 348 | [dateFormatter_ setFormatterBehavior:NSDateFormatterBehavior10_4]; 349 | [dateFormatter_ setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSS"]; 350 | pname_ = [[[NSProcessInfo processInfo] processName] copy]; 351 | pid_ = [[NSProcessInfo processInfo] processIdentifier]; 352 | } 353 | return self; 354 | } 355 | 356 | - (void)dealloc { 357 | [dateFormatter_ release]; 358 | [pname_ release]; 359 | [super dealloc]; 360 | } 361 | 362 | - (NSString *)stringForFunc:(NSString *)func 363 | withFormat:(NSString *)fmt 364 | valist:(va_list)args 365 | level:(GTMLoggerLevel)level { 366 | GTMLOGGER_ASSERT(dateFormatter_ != nil); 367 | NSString *tstamp = nil; 368 | @synchronized (dateFormatter_) { 369 | tstamp = [dateFormatter_ stringFromDate:[NSDate date]]; 370 | } 371 | return [NSString stringWithFormat:@"%@ %@[%d/%p] [lvl=%d] %@ %@", 372 | tstamp, pname_, pid_, pthread_self(), 373 | level, (func ? func : @"(no func)"), 374 | [super stringForFunc:func withFormat:fmt valist:args level:level]]; 375 | } 376 | 377 | @end // GTMLogStandardFormatter 378 | 379 | 380 | @implementation GTMLogLevelFilter 381 | 382 | // Check the environment and the user preferences for the GTMVerboseLogging key 383 | // to see if verbose logging has been enabled. The environment variable will 384 | // override the defaults setting, so check the environment first. 385 | // COV_NF_START 386 | static BOOL IsVerboseLoggingEnabled(void) { 387 | static NSString *const kVerboseLoggingKey = @"GTMVerboseLogging"; 388 | static char *env = NULL; 389 | if (env == NULL) 390 | env = getenv([kVerboseLoggingKey UTF8String]); 391 | 392 | if (env && env[0]) { 393 | return (strtol(env, NULL, 10) != 0); 394 | } 395 | 396 | return [[NSUserDefaults standardUserDefaults] boolForKey:kVerboseLoggingKey]; 397 | } 398 | // COV_NF_END 399 | 400 | // In DEBUG builds, log everything. If we're not in a debug build we'll assume 401 | // that we're in a Release build. 402 | - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { 403 | #if DEBUG 404 | return YES; 405 | #endif 406 | 407 | BOOL allow = YES; 408 | 409 | switch (level) { 410 | case kGTMLoggerLevelDebug: 411 | allow = NO; 412 | break; 413 | case kGTMLoggerLevelInfo: 414 | allow = (IsVerboseLoggingEnabled() == YES); 415 | break; 416 | case kGTMLoggerLevelError: 417 | allow = YES; 418 | break; 419 | case kGTMLoggerLevelAssert: 420 | allow = YES; 421 | break; 422 | default: 423 | allow = YES; 424 | break; 425 | } 426 | 427 | return allow; 428 | } 429 | 430 | @end // GTMLogLevelFilter 431 | 432 | 433 | @implementation GTMLogNoFilter 434 | 435 | - (BOOL)filterAllowsMessage:(NSString *)msg level:(GTMLoggerLevel)level { 436 | return YES; // Allow everything through 437 | } 438 | 439 | @end // GTMLogNoFilter 440 | -------------------------------------------------------------------------------- /Classes/Utilities/MBDataRequest.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBDataRequest.h 3 | // HTTPTransfer 4 | // 5 | // Created by Michael Schwarz on 28.07.10. 6 | // Copyright 2010 Karl-Franzens Uni Graz. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MBDataRequestDelegate.h" 11 | #import "ASIHTTPRequest.h" 12 | #import "ASIHTTPRequestDelegate.h" 13 | 14 | typedef enum MBDataContentCategory { 15 | MBClubsCategory, 16 | MBNewsCategory, 17 | MBMuseumCategory, 18 | MBEventsCategory, 19 | MBClubEventsCategory, 20 | MBClassicsCategory, 21 | MBYoungClassicsCategory, 22 | MBMuseumShopCategory, 23 | MBStoryCategory, 24 | MBExhibitionCategory, 25 | } MBDataContentCategory; 26 | 27 | 28 | @interface MBDataRequest : NSObject { 29 | 30 | //Defines, which content category the request delivers. 31 | MBDataContentCategory contentCategory_; 32 | 33 | //Delegate, implementing the MBDataRequestDelegate Protocol 34 | id delegate_; 35 | 36 | //Data-Array consisting the requestet content 37 | NSMutableArray *contentData_; 38 | 39 | //String consisting the XML file to parse 40 | NSString *xmlString_; 41 | 42 | 43 | 44 | 45 | } 46 | #pragma mark Properties 47 | @property(retain, nonatomic) id delegate; 48 | 49 | 50 | +(void) shouldUseLocalMemory:(BOOL)shouldUse; 51 | 52 | #pragma mark init / dealloc 53 | 54 | // Init Methods 55 | - (id)initWithMBContentCategory:(MBDataContentCategory)contentCategory; 56 | 57 | // Convenience constructor 58 | + (id)requestWithMBContentCategory:(MBDataContentCategory)contentCategory; 59 | 60 | 61 | // Run a request in the background 62 | - (void)start; 63 | 64 | - (NSArray *)requestData; 65 | 66 | @end 67 | -------------------------------------------------------------------------------- /Classes/Utilities/MBDataRequest.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBDataRequest.m 3 | // HTTPTransfer 4 | // 5 | // Created by Michael Schwarz on 28.07.10. 6 | // Copyright 2010 Karl-Franzens Uni Graz. All rights reserved. 7 | // 8 | 9 | #import "MBDataRequest.h" 10 | #import "TBXML.h" 11 | 12 | 13 | 14 | //Set true, if downloaded and parsed array data is saved locally. 15 | static BOOL localMemoryUsed=YES; 16 | 17 | 18 | // Private stuff 19 | @interface MBDataRequest () 20 | //Delivers a locally saved Category Array if ttl is OK, if ttl is not ok, or array not saved -> return nil 21 | -(NSMutableArray *)deliverSavedArrayForFilename:(NSString *)localFilename ConsideringTTL:(NSTimeInterval)ttl ; 22 | 23 | - (NSString *)documentsDirectory; 24 | 25 | - (void)parseXMLString; 26 | @end 27 | 28 | 29 | @implementation MBDataRequest 30 | 31 | @synthesize delegate=delegate_; 32 | 33 | +(void) shouldUseLocalMemory:(BOOL)shouldUse 34 | { 35 | localMemoryUsed = shouldUse; 36 | } 37 | 38 | - (id)initWithMBContentCategory:(MBDataContentCategory)contentCategory 39 | { 40 | self = [super init]; 41 | if (self != nil) { 42 | contentData_=nil; 43 | xmlString_=nil; 44 | contentCategory_=contentCategory; 45 | } 46 | return self; 47 | } 48 | 49 | 50 | 51 | + (id)requestWithMBContentCategory:(MBDataContentCategory)contentCategory 52 | { 53 | return [[[self alloc] initWithMBContentCategory:contentCategory] autorelease]; 54 | } 55 | 56 | 57 | - (void)start 58 | { 59 | 60 | NSTimeInterval ttl=TTL_ETERNAL; //Time To Live 61 | NSString *localMBFilename=nil; 62 | NSString *remoteXMLFilename=nil; 63 | 64 | 65 | switch (contentCategory_) { 66 | case MBClubsCategory: 67 | localMBFilename = MBFILE_CLUBS; 68 | remoteXMLFilename = XML_REMOTE_CLUBS; 69 | ttl = TTL_CLUBS; 70 | break; 71 | case MBNewsCategory: 72 | localMBFilename = MBFILE_NEWS; 73 | remoteXMLFilename = XML_REMOTE_NEWS; 74 | ttl = TTL_NEWS; 75 | break; 76 | case MBMuseumCategory: //Special Category - XML instead of remote, included in the bundle 77 | localMBFilename = MBFILE_MUSEUM; 78 | xmlString_ = [[NSString alloc] initWithContentsOfFile:XML_LOCAL_MUSEUM encoding:NSUTF8StringEncoding error:nil ]; 79 | ttl = TTL_ETERNAL; 80 | break; 81 | case MBEventsCategory: 82 | localMBFilename = MBFILE_EVENTS; 83 | remoteXMLFilename = XML_REMOTE_EVENTS; 84 | ttl = TTL_EVENTS; 85 | break; 86 | case MBClubEventsCategory: 87 | localMBFilename = MBFILE_CLUB_EVENTS; 88 | remoteXMLFilename = XML_REMOTE_CLUB_EVENTS; 89 | ttl = TTL_EVENTS; 90 | break; 91 | case MBClassicsCategory: 92 | localMBFilename = MBFILE_CLASSICS; 93 | remoteXMLFilename = XML_REMOTE_CLASSICS; 94 | ttl = TTL_CLASSICS; 95 | break; 96 | case MBYoungClassicsCategory: 97 | localMBFilename = MBFILE_YOUNGCLASSICS; 98 | remoteXMLFilename = XML_REMOTE_YOUNGCLASSICS; 99 | ttl = TTL_CLASSICS; 100 | break; 101 | case MBMuseumShopCategory: 102 | localMBFilename = MBFILE_MUSEUMSHOP; 103 | remoteXMLFilename = XML_REMOTE_MUSEUMSHOP; 104 | ttl = TTL_MUSEUMSHOP; 105 | break; 106 | case MBStoryCategory: 107 | localMBFilename = MBFILE_CLUB_STORIES; 108 | remoteXMLFilename = XML_REMOTE_CLUB_STORIES; 109 | ttl = TTL_CLUB_STORIES; 110 | break; 111 | case MBExhibitionCategory: 112 | localMBFilename = MBFILE_EXHIBITIONS; 113 | remoteXMLFilename = XML_REMOTE_EXHIBITIONS; 114 | ttl = TTL_EXHIBITIONS; 115 | break; 116 | 117 | default: 118 | NSLog(@"MBDataRequest/start: Unknown contentCategory"); 119 | break; 120 | } 121 | 122 | if(localMemoryUsed) 123 | contentData_=[self deliverSavedArrayForFilename:localMBFilename ConsideringTTL:ttl]; 124 | 125 | if (contentData_ != nil) { //Finished - deliver Request 126 | if(delegate_ && [delegate_ respondsToSelector:@selector(requestFinished:)]) 127 | [delegate_ requestFinished:self]; 128 | } 129 | 130 | 131 | if (xmlString_ == nil) { //if not museum categorie - load the xml file 132 | NSURL *url=[NSURL URLWithString:remoteXMLFilename]; 133 | ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 134 | [request setDelegate:self]; 135 | [request startAsynchronous]; 136 | NSLog(@"MBDataRequest/start: StartedXMLTransfer"); 137 | }else{ 138 | NSThread *parserThread = [[[NSThread alloc] initWithTarget:self selector:@selector(parseXMLString) object:nil] autorelease]; 139 | [parserThread start]; 140 | } 141 | 142 | 143 | 144 | } 145 | 146 | 147 | #pragma mark ASIHTTPRequestDelegate Implementations 148 | - (void)requestFinished:(ASIHTTPRequest *)request 149 | { 150 | // Use when fetching text data 151 | NSLog(@"MBDataRequest/requestFinished: XML-File transferred"); 152 | xmlString_ = [[request responseString]retain]; 153 | 154 | NSThread *parserThread = [[[NSThread alloc] initWithTarget:self selector:@selector(parseXMLString) object:nil] autorelease]; 155 | 156 | [parserThread start]; 157 | } 158 | 159 | - (void)requestFailed:(ASIHTTPRequest *)request 160 | { 161 | NSError *error = [request error]; 162 | NSLog(@"ERROR, %@",[error localizedDescription]); 163 | } 164 | 165 | 166 | - (void)parseXMLString{ 167 | NSLog(@"MBDataRequest/parseXMLString: Start with parsing "); 168 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; //New Pool for the thread 169 | 170 | // TBXML * tbxml = [TBXML tbxmlWithXMLString:xmlString_] ; 171 | // TBXMLElement * rootXMLElement = tbxml.rootXMLElement; 172 | 173 | // NSString *elementName = [NSString stringWithUTF8String:rootXMLElement->name]; 174 | // NSLog(elementName); 175 | 176 | 177 | //NSData *xmlData = [xmlString_ dataUsingEncoding:NSUTF8StringEncoding]; 178 | 179 | // NSLog(xmlString_); 180 | 181 | //NSLog(@"%d", [xmlString_ length]); 182 | 183 | //NGDOMDocument *doc = [[NGDOMDocument alloc] initWithData:xmlData]; 184 | 185 | 186 | // NSLog(@"MBDataRequest/parseXMLString: End parsing "); 187 | [pool release]; 188 | 189 | if(delegate_ && [delegate_ respondsToSelector:@selector(requestFinished:)]) 190 | [delegate_ requestFinished:self]; 191 | 192 | 193 | 194 | } 195 | 196 | 197 | -(NSMutableArray *)deliverSavedArrayForFilename:(NSString *)localFilename ConsideringTTL:(NSTimeInterval)ttl 198 | { 199 | NSString *fullPathName; 200 | NSFileManager *fileManager = [NSFileManager defaultManager]; 201 | NSDate *fileLastModified; 202 | 203 | NSLog(@"MBDataRequest/deliverSavedArrayForFilename: Search for saved Array! "); 204 | 205 | fullPathName = [[self documentsDirectory] stringByAppendingPathComponent:localFilename]; 206 | 207 | if ([fileManager fileExistsAtPath:fullPathName]) { //if file does not exist 208 | return(nil); 209 | } 210 | 211 | fileLastModified = [[fileManager fileAttributesAtPath:localFilename traverseLink:YES] objectForKey:NSFileModificationDate]; 212 | int interval = (int)[fileLastModified timeIntervalSinceNow]; 213 | 214 | if (abs(interval) > ttl && ttl != TTL_ETERNAL) { //if time intervall from last download is > (Time To Live) 215 | return(nil); 216 | } 217 | 218 | NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:fullPathName]; 219 | 220 | return [array autorelease]; 221 | } 222 | 223 | 224 | - (NSArray *)requestData 225 | { 226 | return (NSArray *)contentData_; 227 | } 228 | 229 | - (NSString *)documentsDirectory { 230 | return [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]; 231 | } 232 | 233 | @end 234 | -------------------------------------------------------------------------------- /Classes/Utilities/MBDataRequestDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBDataRequestDelegate.h 3 | // HTTPTransfer 4 | // 5 | // Created by Michael Schwarz on 28.07.10. 6 | // Copyright 2010 Karl-Franzens Uni Graz. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class MBDataRequest; 12 | 13 | @protocol MBDataRequestDelegate 14 | 15 | - (void)requestFinished:(MBDataRequest *)request; 16 | - (void)requestFailed:(MBDataRequest *)request; 17 | 18 | @optional 19 | 20 | - (void)requestStarted:(MBDataRequest *)request; 21 | - (void)requestReceivedResponseHeaders:(MBDataRequest *)request; 22 | 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Classes/Utilities/Object Additions/NSString-TruncateToWidth.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString-TruncateToWidth.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface NSString (TruncateToWidth) 13 | 14 | - (NSString*)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font; 15 | 16 | @end -------------------------------------------------------------------------------- /Classes/Utilities/Object Additions/NSString-TruncateToWidth.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString-TruncateToWidth.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import "NSString-TruncateToWidth.h" 10 | 11 | 12 | #define ellipsis @"…" 13 | 14 | @implementation NSString (TruncateToWidth) 15 | 16 | - (NSString*)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font { 17 | // Create copy that will be the returned result 18 | NSMutableString *truncatedString = [[self mutableCopy] autorelease]; 19 | 20 | // Make sure string is longer than requested width 21 | if ([self sizeWithFont:font].width > width) { 22 | // Accommodate for ellipsis we'll tack on the end 23 | width -= [ellipsis sizeWithFont:font].width; 24 | 25 | // Get range for last character in string 26 | NSRange range = {truncatedString.length - 1, 1}; 27 | 28 | // Loop, deleting characters until string fits within width 29 | while ([truncatedString sizeWithFont:font].width > width) { 30 | // Delete character at end 31 | [truncatedString deleteCharactersInRange:range]; 32 | 33 | // Move back another character 34 | range.location--; 35 | } 36 | 37 | // Append ellipsis 38 | [truncatedString replaceCharactersInRange:range withString:ellipsis]; 39 | } 40 | 41 | return truncatedString; 42 | } 43 | 44 | @end -------------------------------------------------------------------------------- /Classes/Utilities/Object Additions/UIColor-Components.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor-Components.h 3 | // CocoaSnippets 4 | // 5 | // Created by Matthias Tretter on 26.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | 10 | 11 | @interface UIColor (Components) 12 | - (NSNumber *)redColorComponent; 13 | - (NSNumber *)greenColorComponent; 14 | - (NSNumber *)blueColorComponent; 15 | @end 16 | -------------------------------------------------------------------------------- /Classes/Utilities/Object Additions/UIColor-Components.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIColor-Components.m 3 | // CocoaSnippets 4 | // 5 | // Created by Matthias Tretter on 26.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import "UIColor-Components.h" 10 | 11 | 12 | @implementation UIColor (Components) 13 | - (NSNumber *)redColorComponent { 14 | CGColorRef color = [self CGColor]; 15 | 16 | int numComponents = CGColorGetNumberOfComponents(color); 17 | 18 | if (numComponents == 4) 19 | { 20 | const CGFloat *components = CGColorGetComponents(color); 21 | CGFloat floatcolor = components[0]; 22 | return [[[NSNumber alloc] initWithFloat:floatcolor] autorelease]; 23 | } 24 | 25 | return nil; 26 | } 27 | 28 | - (NSNumber *)greenColorComponent { 29 | CGColorRef color = [self CGColor]; 30 | 31 | int numComponents = CGColorGetNumberOfComponents(color); 32 | 33 | if (numComponents == 4) 34 | { 35 | const CGFloat *components = CGColorGetComponents(color); 36 | CGFloat floatcolor = components[1]; 37 | return [[[NSNumber alloc] initWithFloat:floatcolor] autorelease]; 38 | } 39 | 40 | return nil; 41 | } 42 | 43 | 44 | - (NSNumber *)blueColorComponent { 45 | CGColorRef color = [self CGColor]; 46 | 47 | int numComponents = CGColorGetNumberOfComponents(color); 48 | 49 | if (numComponents == 4) 50 | { 51 | const CGFloat *components = CGColorGetComponents(color); 52 | CGFloat floatcolor = components[2]; 53 | return [[[NSNumber alloc] initWithFloat:floatcolor] autorelease]; 54 | } 55 | 56 | return nil; 57 | } 58 | @end 59 | -------------------------------------------------------------------------------- /Classes/Utilities/Object Additions/UIDevice-Helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIDevice-Helper.h 3 | // FirstUniversal 4 | // 5 | // Created by Matthias Tretter on 26.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | 10 | #import 11 | 12 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 13 | #pragma mark - 14 | #pragma mark Category for extending UIDevice Information 15 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | 17 | @interface UIDevice (Helper) 18 | - (BOOL)isJailbroken; 19 | - (BOOL)isIPad; 20 | - (BOOL)isPhone; 21 | 22 | - (BOOL)isMultitaskingAvailable; 23 | - (BOOL)isHardwareEncryptionAvailable; 24 | - (BOOL)isNetworkAvailable; 25 | - (BOOL)isStillCameraAvailable; 26 | - (BOOL)isVideoCameraAvailable; 27 | - (BOOL)isAudioInputAvailable; 28 | - (BOOL)isProximitySensorAvailable; 29 | - (BOOL)isScreenLockingActivated; 30 | - (BOOL)isClassAvailable:(NSString *) className; 31 | - (BOOL)isExternalScreenAttached; 32 | 33 | - (void)activateScreenLocking; 34 | - (void)deactivateScreenLocking; 35 | @end -------------------------------------------------------------------------------- /Classes/Utilities/Object Additions/UIDevice-Helper.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIDevice-Helper.m 3 | // FirstUniversal 4 | // 5 | // Created by Matthias Tretter on 26.07.10. 6 | // Copyright (c) 2010 m.yellow. All rights reserved. 7 | // 8 | 9 | #import "UIDevice-Helper.h" 10 | 11 | 12 | @implementation UIDevice (Helper) 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | #pragma mark - 16 | #pragma mark Checking Jailbreak Status 17 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | - (BOOL)isJailbroken { 20 | BOOL jailbroken = NO; 21 | NSString *cydiaPath = @"/Applications/Cydia.app"; 22 | NSString *aptPath = @"/private/var/lib/apt/"; 23 | 24 | if ([[NSFileManager defaultManager] fileExistsAtPath:cydiaPath]) { 25 | jailbroken = YES; 26 | } 27 | 28 | if ([[NSFileManager defaultManager] fileExistsAtPath:aptPath]) { 29 | jailbroken = YES; 30 | } 31 | 32 | return jailbroken; 33 | } 34 | 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | #pragma mark - 37 | #pragma mark Checking Device Type 38 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 39 | 40 | - (BOOL)isIPad { 41 | static BOOL hasCheckediPadStatus = NO; 42 | static BOOL isRunningOniPad = NO; 43 | 44 | if (!hasCheckediPadStatus) { 45 | if ([self respondsToSelector:@selector(userInterfaceIdiom)]) { 46 | if ([self userInterfaceIdiom] == UIUserInterfaceIdiomPad) { 47 | isRunningOniPad = YES; 48 | } 49 | } 50 | 51 | hasCheckediPadStatus = YES; 52 | } 53 | 54 | return isRunningOniPad; 55 | } 56 | 57 | - (BOOL)isPhone { 58 | return [[self model] rangeOfString:@"iPhone" options:NSCaseInsensitiveSearch].location != NSNotFound; 59 | } 60 | 61 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 62 | #pragma mark - 63 | #pragma mark Checking Hardware/Software Features 64 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 65 | 66 | - (BOOL)isMultitaskingAvailable { 67 | /*static BOOL hasCheckedMultitaskingStatus = NO; 68 | static BOOL multitaskingAvailable = NO; 69 | 70 | if (!hasCheckedMultitaskingStatus) { 71 | if ([self respondsToSelector:@selector(isMultitaskingSupported)]) { 72 | multitaskingAvailable = [self isMultitaskingSupported]; 73 | } 74 | 75 | hasCheckedMultitaskingStatus = YES; 76 | } 77 | 78 | return multitaskingAvailable;*/ 79 | return NO; 80 | } 81 | 82 | - (BOOL)isHardwareEncryptionAvailable { 83 | /* TODO: Get the value of the protectedDataAvailable property in the shared UIApplication object. */ 84 | 85 | [self doesNotRecognizeSelector:_cmd]; 86 | return NO; 87 | } 88 | 89 | - (BOOL)isNetworkAvailable { 90 | /* TODO: Use the reachability interfaces of the System Configuration framework to determine the current network connectivity. 91 | For an example of how to use the System Configuration framework, see Reachability. */ 92 | 93 | [self doesNotRecognizeSelector:_cmd]; 94 | return NO; 95 | } 96 | 97 | - (BOOL)isStillCameraAvailable { 98 | return [UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]; 99 | } 100 | 101 | - (BOOL)isVideoCameraAvailable { 102 | /* TODO: 103 | Use the isSourceTypeAvailable: method of the UIImagePicker- Controller class to determine if a camera is available and then use the availableMediaTypesForSourceType: method to request the types for the UIImagePickerControllerSourceTypeCamera source. If the returned array contains the kUTTypeMovie key, video capture is available. For more information, see Device Features Programming Guide. */ 104 | 105 | [self doesNotRecognizeSelector:_cmd]; 106 | return NO; 107 | } 108 | 109 | - (BOOL)isAudioInputAvailable { 110 | /* TODO: In iOS 3 and later, use the AVAudioSession class to determine if audio input is available. This class accounts for many different sources of audio input on iOS-based devices, including built-in microphones, headset jacks, and connected accessories. For more information, see AVAudioSession Class Reference. */ 111 | 112 | [self doesNotRecognizeSelector:_cmd]; 113 | return NO; 114 | } 115 | 116 | - (BOOL)isProximitySensorAvailable { 117 | return self.proximityMonitoringEnabled; 118 | } 119 | 120 | - (BOOL)isScreenLockingActivated { 121 | return ![UIApplication sharedApplication].idleTimerDisabled; 122 | } 123 | 124 | - (BOOL)isClassAvailable:(NSString *)className { 125 | return NSClassFromString(className) != nil; 126 | } 127 | 128 | - (BOOL)isExternalScreenAttached { 129 | return UIScreen.screens.count > 1; 130 | } 131 | 132 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 133 | #pragma mark - 134 | #pragma mark Changing Device Values 135 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 136 | 137 | - (void)activateScreenLocking { 138 | [UIApplication sharedApplication].idleTimerDisabled = NO; 139 | } 140 | 141 | - (void)deactivateScreenLocking { 142 | [UIApplication sharedApplication].idleTimerDisabled = YES; 143 | } 144 | 145 | 146 | @end 147 | 148 | -------------------------------------------------------------------------------- /Classes/Utilities/Singleton/SynthesizeSingleton.h: -------------------------------------------------------------------------------- 1 | // 2 | // SynthesizeSingleton.h 3 | // CocoaWithLove 4 | // 5 | // Created by Matt Gallagher on 20/10/08. 6 | // Copyright 2009 Matt Gallagher. All rights reserved. 7 | // 8 | // Permission is given to use this source code file without charge in any 9 | // project, commercial or otherwise, entirely at your risk, with the condition 10 | // that any redistribution (in part or whole) of source code must retain 11 | // this copyright and permission notice. Attribution in compiled projects is 12 | // appreciated but not required. 13 | // 14 | 15 | #define SYNTHESIZE_SINGLETON_FOR_CLASS(classname) \ 16 | \ 17 | static classname *shared##classname = nil; \ 18 | \ 19 | + (classname *)shared##classname \ 20 | { \ 21 | @synchronized(self) \ 22 | { \ 23 | if (shared##classname == nil) \ 24 | { \ 25 | shared##classname = [[self alloc] init]; \ 26 | } \ 27 | } \ 28 | \ 29 | return shared##classname; \ 30 | } \ 31 | \ 32 | + (id)allocWithZone:(NSZone *)zone \ 33 | { \ 34 | @synchronized(self) \ 35 | { \ 36 | if (shared##classname == nil) \ 37 | { \ 38 | shared##classname = [super allocWithZone:zone]; \ 39 | return shared##classname; \ 40 | } \ 41 | } \ 42 | \ 43 | return nil; \ 44 | } \ 45 | \ 46 | - (id)copyWithZone:(NSZone *)zone \ 47 | { \ 48 | return self; \ 49 | } \ 50 | \ 51 | - (id)retain \ 52 | { \ 53 | return self; \ 54 | } \ 55 | \ 56 | - (NSUInteger)retainCount \ 57 | { \ 58 | return NSUIntegerMax; \ 59 | } \ 60 | \ 61 | - (void)release \ 62 | { \ 63 | } \ 64 | \ 65 | - (id)autorelease \ 66 | { \ 67 | return self; \ 68 | } 69 | -------------------------------------------------------------------------------- /Classes/Utilities/XML/NSDataAdditions.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @interface NSData (NSDataAdditions) 5 | 6 | // ================================================================================================ 7 | // Created by Tom Bradley on 21/10/2009. 8 | // Version 1.4 9 | // 10 | // Copyright (c) 2009 Tom Bradley 11 | // 12 | // Permission is hereby granted, free of charge, to any person obtaining a copy 13 | // of this software and associated documentation files (the "Software"), to deal 14 | // in the Software without restriction, including without limitation the rights 15 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 16 | // copies of the Software, and to permit persons to whom the Software is 17 | // furnished to do so, subject to the following conditions: 18 | // 19 | // The above copyright notice and this permission notice shall be included in 20 | // all copies or substantial portions of the Software. 21 | // 22 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 28 | // THE SOFTWARE. 29 | // ================================================================================================ 30 | 31 | + (NSData *) dataWithUncompressedContentsOfFile:(NSString *)aFile; 32 | 33 | 34 | 35 | // ================================================================================================ 36 | // base64.h 37 | // ViewTransitions 38 | // 39 | // Created by Neo on 5/11/08. 40 | // Copyright 2008 Kaliware, LLC. All rights reserved. 41 | // 42 | // FOUND HERE http://idevkit.com/forums/tutorials-code-samples-sdk/8-nsdata-base64-extension.html 43 | // ================================================================================================ 44 | + (NSData *) dataWithBase64EncodedString:(NSString *) string; 45 | - (id) initWithBase64EncodedString:(NSString *) string; 46 | 47 | - (NSString *) base64Encoding; 48 | - (NSString *) base64EncodingWithLineLength:(unsigned int) lineLength; 49 | 50 | 51 | 52 | // ================================================================================================ 53 | // NSData+gzip.h 54 | // Drip 55 | // 56 | // Created by Nur Monson on 8/21/07. 57 | // Copyright 2007 theidiotproject. All rights reserved. 58 | // 59 | // FOUND HERE http://code.google.com/p/drop-osx/source/browse/trunk/Source/NSData%2Bgzip.h 60 | // ================================================================================================ 61 | - (NSData *)gzipDeflate; 62 | - (NSData *)gzipInflate; 63 | 64 | 65 | 66 | @end -------------------------------------------------------------------------------- /Classes/Utilities/XML/NSDataAdditions.m: -------------------------------------------------------------------------------- 1 | 2 | #import "NSDataAdditions.h" 3 | 4 | #import 5 | 6 | 7 | @implementation NSData (NSDataAdditions) 8 | 9 | // ================================================================================================ 10 | // Created by Tom Bradley on 21/10/2009. 11 | // Version 1.4 12 | // 13 | // Copyright (c) 2009 Tom Bradley 14 | // 15 | // Permission is hereby granted, free of charge, to any person obtaining a copy 16 | // of this software and associated documentation files (the "Software"), to deal 17 | // in the Software without restriction, including without limitation the rights 18 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | // copies of the Software, and to permit persons to whom the Software is 20 | // furnished to do so, subject to the following conditions: 21 | // 22 | // The above copyright notice and this permission notice shall be included in 23 | // all copies or substantial portions of the Software. 24 | // 25 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 31 | // THE SOFTWARE. 32 | // ================================================================================================ 33 | 34 | + (NSData *) dataWithUncompressedContentsOfFile:(NSString *)aFile { 35 | 36 | NSData * result; 37 | 38 | if ([[aFile pathExtension] isEqualToString:@"gz"]) { 39 | NSData * compressedData = [NSData dataWithContentsOfFile:aFile]; 40 | result = [compressedData gzipInflate]; 41 | } 42 | else 43 | result = [NSData dataWithContentsOfFile:aFile]; 44 | 45 | return result; 46 | } 47 | 48 | 49 | 50 | 51 | 52 | // ================================================================================================ 53 | // base64.m 54 | // ViewTransitions 55 | // 56 | // Created by Neo on 5/11/08. 57 | // Copyright 2008 Kaliware, LLC. All rights reserved. 58 | // 59 | // Created by khammond on Mon Oct 29 2001. 60 | // Formatted by Timothy Hatcher on Sun Jul 4 2004. 61 | // Copyright (c) 2001 Kyle Hammond. All rights reserved. 62 | // Original development by Dave Winer. 63 | // 64 | // FOUND HERE http://idevkit.com/forums/tutorials-code-samples-sdk/8-nsdata-base64-extension.html 65 | // ================================================================================================ 66 | 67 | static char encodingTable[64] = { 68 | 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', 69 | 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', 70 | 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', 71 | 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' }; 72 | 73 | 74 | + (NSData *) dataWithBase64EncodedString:(NSString *) string { 75 | NSData *result = [[NSData alloc] initWithBase64EncodedString:string]; 76 | return [result autorelease]; 77 | } 78 | 79 | - (id) initWithBase64EncodedString:(NSString *) string { 80 | NSMutableData *mutableData = nil; 81 | 82 | if( string ) { 83 | unsigned long ixtext = 0; 84 | unsigned long lentext = 0; 85 | unsigned char ch = 0; 86 | unsigned char inbuf[4], outbuf[3]; 87 | short i = 0, ixinbuf = 0; 88 | BOOL flignore = NO; 89 | BOOL flendtext = NO; 90 | NSData *base64Data = nil; 91 | const unsigned char *base64Bytes = nil; 92 | 93 | // Convert the string to ASCII data. 94 | base64Data = [string dataUsingEncoding:NSASCIIStringEncoding]; 95 | base64Bytes = [base64Data bytes]; 96 | mutableData = [NSMutableData dataWithCapacity:[base64Data length]]; 97 | lentext = [base64Data length]; 98 | 99 | while( YES ) { 100 | if( ixtext >= lentext ) break; 101 | ch = base64Bytes[ixtext++]; 102 | flignore = NO; 103 | 104 | if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A'; 105 | else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26; 106 | else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52; 107 | else if( ch == '+' ) ch = 62; 108 | else if( ch == '=' ) flendtext = YES; 109 | else if( ch == '/' ) ch = 63; 110 | else flignore = YES; 111 | 112 | if( ! flignore ) { 113 | short ctcharsinbuf = 3; 114 | BOOL flbreak = NO; 115 | 116 | if( flendtext ) { 117 | if( ! ixinbuf ) break; 118 | if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1; 119 | else ctcharsinbuf = 2; 120 | ixinbuf = 3; 121 | flbreak = YES; 122 | } 123 | 124 | inbuf [ixinbuf++] = ch; 125 | 126 | if( ixinbuf == 4 ) { 127 | ixinbuf = 0; 128 | outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 ); 129 | outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 ); 130 | outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F ); 131 | 132 | for( i = 0; i < ctcharsinbuf; i++ ) 133 | [mutableData appendBytes:&outbuf[i] length:1]; 134 | } 135 | 136 | if( flbreak ) break; 137 | } 138 | } 139 | } 140 | 141 | self = [self initWithData:mutableData]; 142 | return self; 143 | } 144 | 145 | #pragma mark - 146 | 147 | - (NSString *) base64Encoding { 148 | return [self base64EncodingWithLineLength:0]; 149 | } 150 | 151 | - (NSString *) base64EncodingWithLineLength:(unsigned int) lineLength { 152 | const unsigned char *bytes = [self bytes]; 153 | NSMutableString *result = [NSMutableString stringWithCapacity:[self length]]; 154 | unsigned long ixtext = 0; 155 | unsigned long lentext = [self length]; 156 | long ctremaining = 0; 157 | unsigned char inbuf[3], outbuf[4]; 158 | short i = 0; 159 | short charsonline = 0, ctcopy = 0; 160 | unsigned long ix = 0; 161 | 162 | while( YES ) { 163 | ctremaining = lentext - ixtext; 164 | if( ctremaining <= 0 ) break; 165 | 166 | for( i = 0; i < 3; i++ ) { 167 | ix = ixtext + i; 168 | if( ix < lentext ) inbuf[i] = bytes[ix]; 169 | else inbuf [i] = 0; 170 | } 171 | 172 | outbuf [0] = (inbuf [0] & 0xFC) >> 2; 173 | outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4); 174 | outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6); 175 | outbuf [3] = inbuf [2] & 0x3F; 176 | ctcopy = 4; 177 | 178 | switch( ctremaining ) { 179 | case 1: 180 | ctcopy = 2; 181 | break; 182 | case 2: 183 | ctcopy = 3; 184 | break; 185 | } 186 | 187 | for( i = 0; i < ctcopy; i++ ) 188 | [result appendFormat:@"%c", encodingTable[outbuf[i]]]; 189 | 190 | for( i = ctcopy; i < 4; i++ ) 191 | [result appendFormat:@"%c",'=']; 192 | 193 | ixtext += 3; 194 | charsonline += 4; 195 | 196 | if( lineLength > 0 ) { 197 | if (charsonline >= lineLength) { 198 | charsonline = 0; 199 | [result appendString:@"\n"]; 200 | } 201 | } 202 | } 203 | 204 | return result; 205 | } 206 | 207 | 208 | 209 | // ================================================================================================ 210 | // NSData+gzip.m 211 | // Drip 212 | // 213 | // Created by Nur Monson on 8/21/07. 214 | // Copyright 2007 theidiotproject. All rights reserved. 215 | // 216 | // FOUND HERE http://code.google.com/p/drop-osx/source/browse/trunk/Source/NSData%2Bgzip.m 217 | // 218 | // Also Check http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html 219 | // ================================================================================================ 220 | 221 | #pragma mark - 222 | #pragma mark GZIP 223 | 224 | - (NSData *)gzipDeflate 225 | { 226 | if ([self length] == 0) return self; 227 | 228 | z_stream strm; 229 | 230 | strm.zalloc = Z_NULL; 231 | strm.zfree = Z_NULL; 232 | strm.opaque = Z_NULL; 233 | strm.total_out = 0; 234 | strm.next_in=(Bytef *)[self bytes]; 235 | strm.avail_in = [self length]; 236 | 237 | // Compresssion Levels: 238 | // Z_NO_COMPRESSION 239 | // Z_BEST_SPEED 240 | // Z_BEST_COMPRESSION 241 | // Z_DEFAULT_COMPRESSION 242 | 243 | if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK) return nil; 244 | 245 | NSMutableData *compressed = [NSMutableData dataWithLength:16384]; // 16K chunks for expansion 246 | 247 | do { 248 | 249 | if (strm.total_out >= [compressed length]) 250 | [compressed increaseLengthBy: 16384]; 251 | 252 | strm.next_out = [compressed mutableBytes] + strm.total_out; 253 | strm.avail_out = [compressed length] - strm.total_out; 254 | 255 | deflate(&strm, Z_FINISH); 256 | 257 | } while (strm.avail_out == 0); 258 | 259 | deflateEnd(&strm); 260 | 261 | [compressed setLength: strm.total_out]; 262 | return [NSData dataWithData:compressed]; 263 | } 264 | 265 | - (NSData *)gzipInflate 266 | { 267 | if ([self length] == 0) return self; 268 | 269 | unsigned full_length = [self length]; 270 | unsigned half_length = [self length] / 2; 271 | 272 | NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; 273 | BOOL done = NO; 274 | int status; 275 | 276 | z_stream strm; 277 | strm.next_in = (Bytef *)[self bytes]; 278 | strm.avail_in = [self length]; 279 | strm.total_out = 0; 280 | strm.zalloc = Z_NULL; 281 | strm.zfree = Z_NULL; 282 | 283 | if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; 284 | while (!done) 285 | { 286 | // Make sure we have enough room and reset the lengths. 287 | if (strm.total_out >= [decompressed length]) 288 | [decompressed increaseLengthBy: half_length]; 289 | strm.next_out = [decompressed mutableBytes] + strm.total_out; 290 | strm.avail_out = [decompressed length] - strm.total_out; 291 | 292 | // Inflate another chunk. 293 | status = inflate (&strm, Z_SYNC_FLUSH); 294 | if (status == Z_STREAM_END) done = YES; 295 | else if (status != Z_OK) break; 296 | } 297 | if (inflateEnd (&strm) != Z_OK) return nil; 298 | 299 | // Set real length. 300 | if (done) 301 | { 302 | [decompressed setLength: strm.total_out]; 303 | return [NSData dataWithData: decompressed]; 304 | } 305 | else return nil; 306 | } 307 | 308 | @end 309 | 310 | -------------------------------------------------------------------------------- /Classes/Utilities/XML/TBXML.h: -------------------------------------------------------------------------------- 1 | // ================================================================================================ 2 | // TBXML.h 3 | // Fast processing of XML files 4 | // 5 | // ================================================================================================ 6 | // Created by Tom Bradley on 21/10/2009. 7 | // Version 1.4 8 | // 9 | // Copyright (c) 2009 Tom Bradley 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to deal 13 | // in the Software without restriction, including without limitation the rights 14 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | // copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | // THE SOFTWARE. 28 | // ================================================================================================ 29 | 30 | 31 | // ================================================================================================ 32 | // Defines 33 | // ================================================================================================ 34 | #define MAX_ELEMENTS 100 35 | #define MAX_ATTRIBUTES 100 36 | 37 | #define TBXML_ATTRIBUTE_NAME_START 0 38 | #define TBXML_ATTRIBUTE_NAME_END 1 39 | #define TBXML_ATTRIBUTE_VALUE_START 2 40 | #define TBXML_ATTRIBUTE_VALUE_END 3 41 | #define TBXML_ATTRIBUTE_CDATA_END 4 42 | 43 | // ================================================================================================ 44 | // Structures 45 | // ================================================================================================ 46 | typedef struct _TBXMLAttribute { 47 | char * name; 48 | char * value; 49 | struct _TBXMLAttribute * next; 50 | } TBXMLAttribute; 51 | 52 | typedef struct _TBXMLElement { 53 | char * name; 54 | char * text; 55 | 56 | TBXMLAttribute * firstAttribute; 57 | 58 | struct _TBXMLElement * parentElement; 59 | 60 | struct _TBXMLElement * firstChild; 61 | struct _TBXMLElement * currentChild; 62 | 63 | struct _TBXMLElement * nextSibling; 64 | struct _TBXMLElement * previousSibling; 65 | 66 | } TBXMLElement; 67 | 68 | typedef struct _TBXMLElementBuffer { 69 | TBXMLElement * elements; 70 | struct _TBXMLElementBuffer * next; 71 | struct _TBXMLElementBuffer * previous; 72 | } TBXMLElementBuffer; 73 | 74 | typedef struct _TBXMLAttributeBuffer { 75 | TBXMLAttribute * attributes; 76 | struct _TBXMLAttributeBuffer * next; 77 | struct _TBXMLAttributeBuffer * previous; 78 | } TBXMLAttributeBuffer; 79 | 80 | // ================================================================================================ 81 | // TBXML Public Interface 82 | // ================================================================================================ 83 | @interface TBXML : NSObject { 84 | 85 | @private 86 | TBXMLElement * rootXMLElement; 87 | 88 | TBXMLElementBuffer * currentElementBuffer; 89 | TBXMLAttributeBuffer * currentAttributeBuffer; 90 | 91 | long currentElement; 92 | long currentAttribute; 93 | 94 | char * bytes; 95 | long bytesLength; 96 | } 97 | 98 | @property (nonatomic, readonly) TBXMLElement * rootXMLElement; 99 | 100 | + (id)tbxmlWithURL:(NSURL*)aURL; 101 | + (id)tbxmlWithXMLString:(NSString*)aXMLString; 102 | + (id)tbxmlWithXMLData:(NSData*)aData; 103 | + (id)tbxmlWithXMLFile:(NSString*)aXMLFile; 104 | + (id)tbxmlWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension; 105 | 106 | - (id)initWithURL:(NSURL*)aURL; 107 | - (id)initWithXMLString:(NSString*)aXMLString; 108 | - (id)initWithXMLData:(NSData*)aData; 109 | - (id)initWithXMLFile:(NSString*)aXMLFile; 110 | - (id)initWithXMLFile:(NSString*)aXMLFile fileExtension:(NSString*)aFileExtension; 111 | 112 | @end 113 | 114 | // ================================================================================================ 115 | // TBXML Static Functions Interface 116 | // ================================================================================================ 117 | 118 | @interface TBXML (StaticFunctions) 119 | 120 | + (NSString*) elementName:(TBXMLElement*)aXMLElement; 121 | + (NSString*) textForElement:(TBXMLElement*)aXMLElement; 122 | + (NSString*) valueOfAttributeNamed:(NSString *)aName forElement:(TBXMLElement*)aXMLElement; 123 | 124 | + (NSString*) attributeName:(TBXMLAttribute*)aXMLAttribute; 125 | + (NSString*) attributeValue:(TBXMLAttribute*)aXMLAttribute; 126 | 127 | + (TBXMLElement*) nextSiblingNamed:(NSString*)aName searchFromElement:(TBXMLElement*)aXMLElement; 128 | + (TBXMLElement*) childElementNamed:(NSString*)aName parentElement:(TBXMLElement*)aParentXMLElement; 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /Classes/View Controller/MBPageScrollVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBScrollingVC.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MBPageScrollView.h" 11 | 12 | 13 | @interface MBPageScrollVC : UIViewController { 14 | MBPageScrollView *pageScrollView_; 15 | } 16 | 17 | // Properties 18 | @property (nonatomic, retain) IBOutlet MBPageScrollView *pageScrollView; 19 | 20 | // Methods 21 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated; 22 | 23 | @end -------------------------------------------------------------------------------- /Classes/View Controller/MBPageScrollVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBScrollingVC.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "MBPageScrollVC.h" 10 | #import "AppDelegate.h" 11 | 12 | 13 | 14 | @implementation MBPageScrollVC 15 | 16 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 17 | #pragma mark - 18 | #pragma mark Synthesized Properties 19 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 20 | 21 | @synthesize pageScrollView = pageScrollView_; 22 | 23 | 24 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | #pragma mark - 26 | #pragma mark View Controller Lifecycle 27 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | // the designated initializer 30 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 31 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 32 | pageScrollView_ = [[MBPageScrollView alloc] initWithFrame:MBApplicationFrame() 33 | dataSource:MBApplicationDelegate 34 | delegate:MBApplicationDelegate]; 35 | 36 | 37 | [self.view addSubview:self.pageScrollView]; 38 | } 39 | 40 | return self; 41 | } 42 | 43 | - (void)dealloc { 44 | RELEASE(pageScrollView_); 45 | 46 | [super dealloc]; 47 | } 48 | 49 | - (void)viewDidUnload { 50 | [super viewDidUnload]; 51 | // Release any retained subviews of the main view. 52 | self.pageScrollView = nil; 53 | } 54 | 55 | - (void)didReceiveMemoryWarning { 56 | // Releases the view if it doesn't have a superview. 57 | [super didReceiveMemoryWarning]; 58 | 59 | // Release any cached data, images, etc that aren't in use. 60 | [self.pageScrollView releaseCachedController]; 61 | } 62 | 63 | /* 64 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 65 | - (void)viewDidLoad { 66 | [super viewDidLoad]; 67 | } 68 | */ 69 | 70 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 71 | #pragma mark - 72 | #pragma mark Rotation 73 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 74 | 75 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 76 | // support all orientations on iPad, Portrait on iPhone 77 | return ROTATE_ON_IPAD; 78 | } 79 | 80 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 81 | [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 82 | 83 | [self.pageScrollView willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 84 | 85 | // call willRotate for all created view controllers 86 | for (id vc in self.pageScrollView.viewControllers) { 87 | if ((NSNull *)vc != [NSNull null]) { 88 | [vc willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration]; 89 | 90 | // make every other viewController invisible during animation 91 | // this prevents that the next vc appears at the edge of the screen when rotating to Landscape 92 | if (vc != self.pageScrollView.currentController) { 93 | [vc view].alpha = 0.0; 94 | } 95 | } 96 | } 97 | } 98 | 99 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 100 | [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; 101 | 102 | [self.pageScrollView didRotateFromInterfaceOrientation:fromInterfaceOrientation]; 103 | 104 | // call didRotate for all created view controllers 105 | for (id vc in self.pageScrollView.viewControllers) { 106 | if ((NSNull *)vc != [NSNull null]) { 107 | [vc didRotateFromInterfaceOrientation:fromInterfaceOrientation]; 108 | 109 | // make view controller visible again 110 | if (vc != self.pageScrollView.currentController) { 111 | [vc view].alpha = 1.0; 112 | } 113 | } 114 | } 115 | } 116 | 117 | 118 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 119 | #pragma mark - 120 | #pragma mark Action Methods 121 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 122 | 123 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated { 124 | [self.pageScrollView loadPage:page animated:animated]; 125 | } 126 | 127 | @end 128 | -------------------------------------------------------------------------------- /Classes/View Controller/MBScrollingDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBScrollingProvider.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | #pragma mark - 13 | #pragma mark Protocol for Providing View Controllers for MBScrollingVC on demand 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | @protocol MBScrollingDelegate 17 | // the number of view controllers 18 | - (NSUInteger)numberOfControllers; 19 | // specific view controller for a given page 20 | - (UIViewController *)viewControllerForPage:(NSUInteger)page; 21 | @end 22 | -------------------------------------------------------------------------------- /Classes/View Controller/MBScrollingVC.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBScrollingVC.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MBScrollingDelegate.h" 11 | 12 | 13 | @interface MBScrollingVC : UIViewController { 14 | id delegate_; 15 | 16 | UIScrollView *scrollView_; 17 | UIPageControl *pageControl_; 18 | NSMutableArray *viewControllers_; 19 | 20 | // To be used when scrolls originate from the UIPageControl 21 | BOOL pageControlUsed; 22 | // page Number before Rotation starts 23 | NSInteger pageBeforeRotation; 24 | // frame of the application (whole display size) 25 | CGRect applicationFrame; 26 | } 27 | 28 | // Properties 29 | @property (nonatomic, retain) IBOutlet UIScrollView *scrollView; 30 | @property (nonatomic, retain) IBOutlet UIPageControl *pageControl; 31 | @property (nonatomic, retain) NSMutableArray *viewControllers; 32 | 33 | // Initializer 34 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil viewControllerProvider:(id)provider; 35 | 36 | // Methods 37 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated; 38 | 39 | // Action Methods 40 | - (IBAction)changePage:(id)sender; 41 | 42 | @end 43 | 44 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 45 | #pragma mark - 46 | #pragma mark Class Extension for Private Methods 47 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 48 | 49 | @interface MBScrollingVC () 50 | - (void)p_deviceDidRotate:(NSNotification *)notification; 51 | - (CGRect)p_framePosition:(CGRect)frame forPage:(int)page; 52 | 53 | - (void)p_resizeScrollViewForOrientation:(UIInterfaceOrientation)orientation; 54 | - (void)p_resizeScrollViewForPortrait; 55 | - (void)p_resizeScrollViewForLandscape; 56 | - (void)p_repositionSubViews; 57 | - (void)p_initScrollView; 58 | 59 | - (void)p_loadScrollViewWithPage:(int)page; 60 | @end -------------------------------------------------------------------------------- /Classes/View Controller/MBScrollingVC.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBScrollingVC.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "MBScrollingVC.h" 10 | 11 | 12 | @implementation MBScrollingVC 13 | 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | #pragma mark - 16 | #pragma mark Synthesized Properties 17 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 18 | 19 | @synthesize scrollView = scrollView_; 20 | @synthesize pageControl = pageControl_; 21 | @synthesize viewControllers = viewControllers_; 22 | 23 | 24 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 25 | #pragma mark - 26 | #pragma mark View Controller Lifecycle 27 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 28 | 29 | // the designated initializer 30 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil viewControllerProvider:(id)provider { 31 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 32 | delegate_ = provider; 33 | applicationFrame = [[UIScreen mainScreen] applicationFrame]; 34 | 35 | // view controllers are created lazily 36 | // in the meantime, load the array with placeholders which will be replaced on demand 37 | NSMutableArray *controllers = [NSMutableArray arrayWithCapacity:[delegate_ numberOfControllers]]; 38 | 39 | for (NSUInteger i = 0; i<[delegate_ numberOfControllers]; i++) { 40 | [controllers addObject:[NSNull null]]; 41 | } 42 | 43 | self.viewControllers = controllers; 44 | 45 | [self p_initScrollView]; 46 | } 47 | 48 | return self; 49 | } 50 | 51 | // The designated initializer of the base class, therefore it is overridden 52 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 53 | return [self initWithNibName:nibNameOrNil bundle:nibBundleOrNil viewControllerProvider:nil]; 54 | } 55 | 56 | - (void)dealloc { 57 | RELEASE(viewControllers_); 58 | RELEASE(scrollView_); 59 | RELEASE(pageControl_); 60 | 61 | [super dealloc]; 62 | } 63 | 64 | - (void)viewDidUnload { 65 | [super viewDidUnload]; 66 | // Release any retained subviews of the main view. 67 | self.viewControllers = nil; 68 | self.scrollView = nil; 69 | self.pageControl = nil; 70 | } 71 | 72 | - (void)didReceiveMemoryWarning { 73 | // Releases the view if it doesn't have a superview. 74 | [super didReceiveMemoryWarning]; 75 | 76 | // Release any cached data, images, etc that aren't in use. 77 | } 78 | 79 | 80 | /* 81 | // Implement loadView to create a view hierarchy programmatically, without using a nib. 82 | - (void)loadView { 83 | } 84 | */ 85 | 86 | /* 87 | // Implement viewDidLoad to do additional setup after loading the view, typically from a nib. 88 | - (void)viewDidLoad { 89 | [super viewDidLoad]; 90 | } 91 | */ 92 | 93 | 94 | - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { 95 | // support all orientations on iPad, Portrait on iPhone 96 | return ROTATE_ON_IPAD; 97 | } 98 | 99 | 100 | 101 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 102 | #pragma mark - 103 | #pragma mark Action Methods 104 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 105 | 106 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated { 107 | //TODO: implement loading of a specific page with animation 108 | CGRect frame = self.scrollView.frame; 109 | frame.origin.x = frame.size.width * page; 110 | frame.origin.y = 0; 111 | [self.scrollView scrollRectToVisible:frame animated:animated]; 112 | } 113 | 114 | - (IBAction)changePage:(id)sender { 115 | NSLog(@"change page"); 116 | int page = self.pageControl.currentPage; 117 | 118 | // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) 119 | [self p_loadScrollViewWithPage:page - 1]; 120 | [self p_loadScrollViewWithPage:page]; 121 | [self p_loadScrollViewWithPage:page + 1]; 122 | 123 | // update the scroll view to the appropriate page 124 | CGRect frame = self.scrollView.frame; 125 | frame.origin.x = frame.size.width * page; 126 | frame.origin.y = 0; 127 | [self.scrollView scrollRectToVisible:frame animated:YES]; 128 | 129 | // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above. 130 | pageControlUsed = YES; 131 | } 132 | 133 | 134 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 135 | #pragma mark - 136 | #pragma mark ScrollViewDelegate Methods 137 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 138 | 139 | - (void)scrollViewDidScroll:(UIScrollView *)sender { 140 | // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in 141 | // which a scroll event generated from the user hitting the page control triggers updates from 142 | // the delegate method. We use a boolean to disable the delegate logic when the page control is used. 143 | if (pageControlUsed) { 144 | // do nothing - the scroll was initiated from the page control, not the user dragging 145 | return; 146 | } 147 | 148 | // Switch the indicator when more than 50% of the previous/next page is visible 149 | CGFloat pageWidth = self.scrollView.frame.size.width; 150 | int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 151 | 152 | self.pageControl.currentPage = page; 153 | 154 | // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) 155 | [self p_loadScrollViewWithPage:page - 1]; 156 | [self p_loadScrollViewWithPage:page]; 157 | [self p_loadScrollViewWithPage:page + 1]; 158 | 159 | // A possible optimization would be to unload the views+controllers which are no longer visible 160 | } 161 | 162 | // At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl 163 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 164 | pageControlUsed = NO; 165 | } 166 | 167 | // At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl 168 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 169 | pageControlUsed = NO; 170 | } 171 | 172 | 173 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 174 | #pragma mark - 175 | #pragma mark Private Methods 176 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 177 | 178 | - (void)p_deviceDidRotate:(NSNotification *)notification { 179 | UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 180 | 181 | // save the page and restore it after the rotation 182 | pageBeforeRotation = self.pageControl.currentPage; 183 | 184 | [self p_resizeScrollViewForOrientation:orientation]; 185 | } 186 | 187 | - (CGRect)p_framePosition:(CGRect)frame forPage:(int)page { 188 | // Calculate frame position 189 | frame.origin.x = frame.size.width * page; 190 | frame.origin.y = 0; 191 | 192 | return frame; 193 | } 194 | 195 | - (void)p_resizeScrollViewForOrientation:(UIInterfaceOrientation)orientation { 196 | // only resize Scrollview for Landscape on iPad 197 | if ([[UIDevice currentDevice] isIPad] && UIInterfaceOrientationIsLandscape(orientation)) { 198 | [self p_resizeScrollViewForLandscape]; 199 | } else { 200 | [self p_resizeScrollViewForPortrait]; 201 | } 202 | } 203 | 204 | - (void)p_resizeScrollViewForPortrait { 205 | self.scrollView.frame = CGRectMake(applicationFrame.origin.x, applicationFrame.origin.y, 206 | applicationFrame.size.width, applicationFrame.size.height); 207 | 208 | self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.viewControllers.count, 209 | self.scrollView.frame.size.height); 210 | 211 | [self p_repositionSubViews]; 212 | } 213 | 214 | - (void)p_resizeScrollViewForLandscape { 215 | self.scrollView.frame = CGRectMake(applicationFrame.origin.y, applicationFrame.origin.x, 216 | applicationFrame.size.height, applicationFrame.size.width); 217 | 218 | self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.viewControllers.count, 219 | self.scrollView.frame.size.height); 220 | 221 | [self p_repositionSubViews]; 222 | } 223 | 224 | - (void)p_repositionSubViews { 225 | self.pageControl.center = CGPointMake(applicationFrame.size.width / 2, 30.0); 226 | 227 | // Reposition all loaded frames 228 | for (int i = 0; i < [self.viewControllers count]; i++) { 229 | UIViewController* vc = [self.viewControllers objectAtIndex:i]; 230 | 231 | if((NSNull *)vc != [NSNull null]) { 232 | // Calculate the position of the frame depending on orientation 233 | vc.view.frame = [self p_framePosition:vc.view.frame forPage:i]; 234 | } 235 | } 236 | 237 | // Move the scrollview viewport to the location the user was on before the resize 238 | //if(pageBeforeRotation >= 0) { 239 | // if([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeLeft) { 240 | // self.scrollView.contentOffset = CGPointMake(0, (6-pageBeforeRotation)*self.scrollView.frame.size.height); 241 | // } else if([[UIDevice currentDevice] orientation] == UIInterfaceOrientationLandscapeRight) { 242 | // self.scrollView.contentOffset = CGPointMake(0, pageBeforeRotation*self.scrollView.frame.size.height); 243 | // } else { 244 | self.scrollView.contentOffset = CGPointMake(pageBeforeRotation*self.scrollView.frame.size.width, 0); 245 | // } 246 | // } 247 | } 248 | 249 | - (void)p_initScrollView { 250 | // init scrollview 251 | self.scrollView = [[[UIScrollView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]] autorelease]; 252 | self.scrollView.pagingEnabled = YES; 253 | [self p_resizeScrollViewForOrientation:[[UIDevice currentDevice] orientation]]; 254 | 255 | self.scrollView.showsHorizontalScrollIndicator = NO; 256 | self.scrollView.showsVerticalScrollIndicator = NO; 257 | self.scrollView.scrollsToTop = NO; 258 | self.scrollView.delegate = self; 259 | self.scrollView.backgroundColor = [UIColor blueColor]; 260 | [self.view addSubview:self.scrollView]; 261 | 262 | // init pageControl 263 | self.pageControl = [[[UIPageControl alloc] initWithFrame:CGRectZero] autorelease]; 264 | self.pageControl.center = CGPointMake(self.scrollView.frame.size.width / 2, 30.0); 265 | self.pageControl.autoresizingMask = UIViewAutoresizingFlexibleWidth; 266 | self.pageControl.contentMode = UIViewContentModeScaleToFill; 267 | self.pageControl.numberOfPages = self.viewControllers.count; 268 | self.pageControl.currentPage = 0; 269 | [self.pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged]; 270 | [self.view addSubview:self.pageControl]; 271 | 272 | 273 | // load the visible page - pages are created on demand 274 | [self p_loadScrollViewWithPage:0]; 275 | // load the page on either side to avoid flashes when the user starts scrolling 276 | [self p_loadScrollViewWithPage:1]; 277 | } 278 | 279 | - (void)p_loadScrollViewWithPage:(int)page { 280 | if (page < 0 || page >= self.viewControllers.count) { 281 | return; 282 | } 283 | 284 | // replace the placeholder if necessary 285 | UIViewController *controller = [self.viewControllers objectAtIndex:page]; 286 | 287 | if ((NSNull *)controller == [NSNull null]) { 288 | controller = [delegate_ viewControllerForPage:page]; 289 | [self.viewControllers replaceObjectAtIndex:page withObject:controller]; 290 | } 291 | 292 | // add the controller's view to the scroll view 293 | if (controller.view.superview == nil) { 294 | // Position the new frame depending on the interface orientation 295 | controller.view.frame = [self p_framePosition:self.scrollView.frame forPage:page]; 296 | 297 | [self.scrollView addSubview:controller.view]; 298 | } 299 | } 300 | 301 | 302 | @end 303 | -------------------------------------------------------------------------------- /Classes/View Controller/Table View Delegates & Data Sources/MBOverviewSectionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBOverviewSectionDelegate.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MBSectionDelegate.h" 11 | 12 | 13 | @interface MBOverviewSectionDelegate : MBSectionDelegate { 14 | 15 | } 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Classes/View Controller/Table View Delegates & Data Sources/MBOverviewSectionDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBOverviewSectionDelegate.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "MBOverviewSectionDelegate.h" 10 | #import "MyViewController.h" 11 | 12 | 13 | @implementation MBOverviewSectionDelegate 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | #pragma mark - 17 | #pragma mark Initialization 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | - (id)initWithViewController:(UIViewController *)viewController cellTitles:(NSArray *)cellTitles { 21 | if (self = [super initWithViewController:viewController cellTitles:cellTitles]) { 22 | accessoryType_ = UITableViewCellAccessoryDisclosureIndicator; 23 | } 24 | 25 | return self; 26 | } 27 | 28 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | #pragma mark - 30 | #pragma mark Table view delegate 31 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 34 | if (![self p_isFooterCellAtIndexPath:indexPath]) { 35 | MBApplicationDelegate.scrollEnabled = NO; 36 | 37 | if (indexPath.row == 0) { 38 | MyViewController *vc = [[[MyViewController alloc] initWithPageNumber:10 pop:YES] autorelease]; 39 | [self.viewController.navigationController pushViewController:vc animated:YES]; 40 | } else { 41 | MyViewController *vc = [[[MyViewController alloc] initWithPageNumber:10 pop:NO] autorelease]; 42 | [self.viewController presentModalViewController:vc animated:YES]; 43 | } 44 | 45 | } 46 | 47 | [tableView deselectRowAtIndexPath:indexPath animated:YES]; 48 | } 49 | 50 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 51 | #pragma mark - 52 | #pragma mark Private Methods 53 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | 55 | - (void)p_setUpFooterCell:(UITableViewCell *)cell { 56 | [super p_setUpFooterCell:cell]; 57 | cell.textLabel.text = @""; 58 | } 59 | 60 | - (void)p_loadFooterImages { 61 | leftFooterImage_ = nil; 62 | rightFooterImage_ = nil; 63 | } 64 | 65 | - (void)p_didClickOnLeftFooterButton { 66 | // TODO: show impressum 67 | NSLog(@"left"); 68 | } 69 | 70 | - (void)p_didClickOnRightFooterButton { 71 | // do nothing 72 | NSLog(@"right"); 73 | } 74 | 75 | 76 | @end 77 | -------------------------------------------------------------------------------- /Classes/View Controller/Table View Delegates & Data Sources/MBSectionDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBTableViewDelegate.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | #pragma mark - 13 | #pragma mark Base Class for all Delegates and DataSources for Sections 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | @interface MBSectionDelegate : NSObject { 17 | NSMutableArray *cellTitles_; 18 | UITableViewCellAccessoryType accessoryType_; 19 | UIViewController *viewController_; 20 | 21 | UIImage *leftFooterImage_; 22 | UIImage *rightFooterImage_; 23 | 24 | NSInteger marginRight_; 25 | } 26 | 27 | @property(nonatomic,readonly) NSInteger numberOfRows; 28 | @property(nonatomic,retain) NSMutableArray *cellTitles; 29 | @property(nonatomic,readonly) IBOutlet UIViewController *viewController; 30 | 31 | - (id)initWithViewController:(UIViewController *)viewController cellTitles:(NSArray *)cellTitles; 32 | 33 | @end 34 | 35 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 36 | #pragma mark - 37 | #pragma mark Class Extension for Private Methods 38 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 39 | 40 | @interface MBSectionDelegate () 41 | - (BOOL)p_isFooterCellAtIndexPath:(NSIndexPath *)indexPath; 42 | - (void)p_setUpFooterCell:(UITableViewCell *)cell; 43 | - (void)p_setUpCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath; 44 | 45 | - (void)p_loadFooterImages; 46 | 47 | - (void)p_didClickOnLeftFooterButton; 48 | - (void)p_didClickOnRightFooterButton; 49 | @end -------------------------------------------------------------------------------- /Classes/View Controller/Table View Delegates & Data Sources/MBSectionDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBTableViewDelegate.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "MBSectionDelegate.h" 10 | 11 | 12 | #define TAG_LEFT_BUTTON 1 13 | #define TAG_RIGHT_BUTTON 2 14 | 15 | #define MARGIN_RIGHT_IPAD 72 16 | #define MARGIN_RIGHT_IPHONE 30 17 | 18 | @implementation MBSectionDelegate 19 | 20 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 21 | #pragma mark - 22 | #pragma mark Synthesized Properties 23 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 24 | 25 | @synthesize cellTitles = cellTitles_; 26 | @synthesize viewController = viewController_; 27 | 28 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | #pragma mark - 30 | #pragma mark Lifecycle 31 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | - (id)initWithViewController:(UIViewController *)viewController cellTitles:(NSArray *)cellTitles; { 34 | if (self = [super init]) { 35 | viewController_ = [viewController retain]; 36 | cellTitles_ = [cellTitles mutableCopy]; 37 | accessoryType_ = UITableViewCellAccessoryNone; 38 | marginRight_ = [[UIDevice currentDevice] isIPad] ? MARGIN_RIGHT_IPAD : MARGIN_RIGHT_IPHONE; 39 | 40 | [self p_loadFooterImages]; 41 | } 42 | 43 | return self; 44 | } 45 | 46 | - (void)dealloc { 47 | RELEASE(cellTitles_); 48 | RELEASE(viewController_); 49 | 50 | [super dealloc]; 51 | } 52 | 53 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 54 | #pragma mark - 55 | #pragma mark Table view data source 56 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 57 | 58 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { 59 | return 1; 60 | } 61 | 62 | - (NSInteger)numberOfRows { 63 | return self.cellTitles.count + 1; 64 | } 65 | 66 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 67 | return [self numberOfRows]; 68 | } 69 | 70 | // change the colors of the footer-cell 71 | - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { 72 | if ([self p_isFooterCellAtIndexPath:indexPath]) { 73 | [cell.textLabel setTextAlignment:UITextAlignmentCenter]; 74 | [cell.textLabel setTextColor:[UIColor whiteColor]]; 75 | [cell setBackgroundColor:[UIColor colorWithRed:0.51 green:0.54 blue:0.576 alpha:1.0]]; 76 | } 77 | } 78 | 79 | // Customize the appearance of table view cells. 80 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 81 | static NSString *cellIDFooter = @"CellIDFooter"; 82 | static NSString *cellID = @"CellIDSection"; 83 | 84 | 85 | BOOL isFooterCell = [self p_isFooterCellAtIndexPath:indexPath]; 86 | UITableViewCell *cell = nil; 87 | 88 | // step 1: is there a reusable cell? 89 | if (isFooterCell) { 90 | cell = [tableView dequeueReusableCellWithIdentifier:cellIDFooter]; 91 | } else { 92 | cell = [tableView dequeueReusableCellWithIdentifier:cellID]; 93 | } 94 | 95 | 96 | // step 2: no? -> create new cell 97 | if (cell == nil) { 98 | if (isFooterCell) { 99 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIDFooter] autorelease]; 100 | 101 | if (leftFooterImage_ != nil) { 102 | // create custom button 103 | UIButton *left = [UIButton buttonWithType:UIButtonTypeCustom]; 104 | // set tag 105 | left.tag = TAG_LEFT_BUTTON; 106 | // set frame 107 | left.frame = CGRectMake(10.0, cell.bounds.size.height / 2 - leftFooterImage_.size.height / 2, 108 | leftFooterImage_.size.width, leftFooterImage_.size.height); 109 | // target-action 110 | [left addTarget:self action:@selector(p_didClickOnLeftFooterButton) forControlEvents:UIControlEventTouchUpInside]; 111 | // add to cell 112 | [cell.contentView addSubview:left]; 113 | } 114 | 115 | if (rightFooterImage_ != nil) { 116 | // create custom button 117 | UIButton *right = [UIButton buttonWithType:UIButtonTypeCustom]; 118 | // set tag 119 | right.tag = TAG_RIGHT_BUTTON; 120 | 121 | NSLog(@"width: %f",tableView.frame.size.width); 122 | // set frame 123 | right.frame = CGRectMake(tableView.frame.size.width - rightFooterImage_.size.width - marginRight_, cell.bounds.size.height / 2 - rightFooterImage_.size.height / 2, 124 | rightFooterImage_.size.width, rightFooterImage_.size.height); 125 | // target-action 126 | [right addTarget:self action:@selector(p_didClickOnRightFooterButton) forControlEvents:UIControlEventTouchUpInside]; 127 | // add to cell 128 | [cell.contentView addSubview:right]; 129 | } 130 | } else { 131 | cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID] autorelease]; 132 | cell.accessoryType = accessoryType_; 133 | } 134 | } 135 | 136 | // step 3: set up cell values 137 | if (isFooterCell) { 138 | [self p_setUpFooterCell:cell]; 139 | } else { 140 | [self p_setUpCell:cell atIndexPath:indexPath]; 141 | } 142 | 143 | return cell; 144 | } 145 | 146 | 147 | // Override to support conditional editing of the table view. 148 | - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { 149 | return NO; 150 | } 151 | 152 | 153 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 154 | #pragma mark - 155 | #pragma mark Table view delegate 156 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 157 | 158 | - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { 159 | // footer cell is not selectable 160 | if ([self p_isFooterCellAtIndexPath:indexPath]) { 161 | return nil; 162 | } 163 | 164 | return indexPath; 165 | } 166 | 167 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 168 | // disables the scrollview so that is looks like if there is a new ViewController 169 | MBApplicationDelegate.scrollEnabled = NO; 170 | } 171 | 172 | 173 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 174 | #pragma mark - 175 | #pragma mark Private Methods 176 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 177 | 178 | - (BOOL)p_isFooterCellAtIndexPath:(NSIndexPath *)indexPath { 179 | return indexPath.row == self.numberOfRows - 1; 180 | } 181 | 182 | - (void)p_setUpFooterCell:(UITableViewCell *)cell { 183 | cell.textLabel.text = [NSString stringWithFormat:@"%d/%d", [MBApplicationDelegate currentPage], [MBApplicationDelegate numberOfPages]]; 184 | 185 | if (leftFooterImage_ != nil) { 186 | UIButton *left = (UIButton *) [cell viewWithTag:TAG_LEFT_BUTTON]; 187 | [left setImage:leftFooterImage_ forState:UIControlStateNormal]; 188 | } 189 | 190 | if (rightFooterImage_ != nil) { 191 | UIButton *right = (UIButton *) [cell viewWithTag:TAG_RIGHT_BUTTON]; 192 | [right setImage:rightFooterImage_ forState:UIControlStateNormal]; 193 | } 194 | } 195 | 196 | - (void)p_setUpCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 197 | cell.textLabel.text = [self.cellTitles objectAtIndex:indexPath.row]; 198 | } 199 | 200 | - (void)p_loadFooterImages { 201 | [self doesNotRecognizeSelector:_cmd]; 202 | } 203 | 204 | - (void)p_didClickOnLeftFooterButton { 205 | // scroll to specific page 206 | [MBApplicationDelegate loadPage:MBApplicationDelegate.currentPage-1 animated:YES]; 207 | } 208 | 209 | - (void)p_didClickOnRightFooterButton { 210 | // scroll to specific page 211 | [MBApplicationDelegate loadPage:MBApplicationDelegate.currentPage+1 animated:YES]; 212 | } 213 | 214 | @end 215 | -------------------------------------------------------------------------------- /Classes/Views/MBPageScrollView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBPageScrollView.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 12 | #pragma mark - 13 | #pragma mark Protocol for Providing View Controllers for MBScrollingVC on demand 14 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 15 | 16 | @protocol MBPageScrollViewDataSource 17 | // the number of view controllers 18 | - (NSUInteger)numberOfPages; 19 | // specific view controller for a given page 20 | - (UIViewController *)viewControllerForPage:(NSUInteger)page; 21 | @end 22 | 23 | @protocol MBPageScrollViewDelegate 24 | // is called when the View Scrolls to a given page 25 | - (void)didScrollToPage:(int)page; 26 | @end 27 | 28 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | #pragma mark - 30 | #pragma mark Generic View for Scrolling through Pages 31 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 32 | 33 | @interface MBPageScrollView : UIView { 34 | id dataSource_; 35 | id delegate_; 36 | 37 | UIScrollView *scrollView_; 38 | UIPageControl *pageControl_; 39 | NSMutableArray *viewControllers_; 40 | 41 | // To be used when scrolls originate from the UIPageControl 42 | BOOL pageControlUsed_; 43 | // inidicates if a rotation is currently in progress 44 | BOOL isRotating_; 45 | // page Number before Rotation starts 46 | NSInteger pageBeforeRotation_; 47 | // frame of the PageScrollView 48 | CGRect viewFrame_; 49 | } 50 | 51 | // Properties 52 | @property (nonatomic, retain) IBOutlet UIScrollView *scrollView; 53 | @property (nonatomic, retain) IBOutlet UIPageControl *pageControl; 54 | @property (nonatomic, retain) NSMutableArray *viewControllers; 55 | @property (nonatomic, readonly) UIViewController *currentController; 56 | 57 | // Initializer 58 | - (id)initWithFrame:(CGRect)frame dataSource:(id)dataSource delegate:(id)delegate; 59 | - (void)releaseCachedController; 60 | 61 | // Methods 62 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated; 63 | 64 | // Action Methods 65 | - (IBAction)changePage:(id)sender; 66 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration; 67 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; 68 | 69 | @end 70 | 71 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 72 | #pragma mark - 73 | #pragma mark Class Extension for Private Methods 74 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 75 | 76 | @interface MBPageScrollView () 77 | - (CGRect)p_framePosition:(CGRect)frame forPage:(int)page; 78 | 79 | - (void)p_resizeScrollViewForOrientation:(UIInterfaceOrientation)orientation; 80 | - (void)p_resizeScrollViewForPortrait; 81 | - (void)p_resizeScrollViewForLandscape; 82 | - (void)p_repositionSubViews; 83 | - (void)p_initScrollView; 84 | 85 | - (void)p_loadScrollViewWithPage:(int)page; 86 | @end -------------------------------------------------------------------------------- /Classes/Views/MBPageScrollView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBPageScrollView.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 28.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "MBPageScrollView.h" 10 | #import "AppDelegate.h" 11 | 12 | 13 | @implementation MBPageScrollView 14 | 15 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 16 | #pragma mark - 17 | #pragma mark Synthesized Properties 18 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 19 | 20 | @synthesize scrollView = scrollView_; 21 | @synthesize pageControl = pageControl_; 22 | @synthesize viewControllers = viewControllers_; 23 | 24 | 25 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 26 | #pragma mark - 27 | #pragma mark View Lifecycle 28 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 29 | 30 | - (id)initWithFrame:(CGRect)frame dataSource:(id)dataSource delegate:(id)delegate { 31 | if ((self = [super initWithFrame:frame])) { 32 | dataSource_ = dataSource; 33 | delegate_ = delegate; 34 | viewFrame_ = frame; 35 | isRotating_ = pageControlUsed_ = NO; 36 | 37 | // view controllers are created lazily 38 | // in the meantime, load the array with placeholders which will be replaced on demand 39 | viewControllers_ = [[NSMutableArray alloc] initWithCapacity:[dataSource_ numberOfPages]]; 40 | 41 | for (NSUInteger i = 0; i<[dataSource_ numberOfPages]; i++) { 42 | [viewControllers_ addObject:[NSNull null]]; 43 | } 44 | 45 | [self p_initScrollView]; 46 | 47 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 48 | self.contentMode = UIViewContentModeScaleToFill; 49 | } 50 | 51 | return self; 52 | } 53 | 54 | - (id)initWithFrame:(CGRect)frame { 55 | return [self initWithFrame:frame dataSource:MBApplicationDelegate delegate:MBApplicationDelegate]; 56 | } 57 | 58 | - (void)releaseCachedController { 59 | // Calculate the current page in scroll view 60 | int currentPage = self.pageControl.currentPage; 61 | 62 | // unload the pages which are no longer visible 63 | for (int i = 0; i < [self.viewControllers count]; i++) { 64 | UIViewController *viewController = [self.viewControllers objectAtIndex:i]; 65 | 66 | if((NSNull *)viewController != [NSNull null]) { 67 | if(i < currentPage-1 || i > currentPage+1) { 68 | [viewController.view removeFromSuperview]; 69 | [self.viewControllers replaceObjectAtIndex:i withObject:[NSNull null]]; 70 | } 71 | } 72 | } 73 | } 74 | 75 | - (void)dealloc { 76 | RELEASE(viewControllers_); 77 | RELEASE(scrollView_); 78 | RELEASE(pageControl_); 79 | 80 | [super dealloc]; 81 | } 82 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 83 | #pragma mark - 84 | #pragma mark Action Methods 85 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 86 | 87 | - (void)loadPage:(NSUInteger)page animated:(BOOL)animated { 88 | CGRect frame = self.scrollView.frame; 89 | frame.origin.x = frame.size.width * page; 90 | frame.origin.y = 0; 91 | 92 | [self.scrollView scrollRectToVisible:frame animated:animated]; 93 | } 94 | 95 | - (IBAction)changePage:(id)sender { 96 | int page = self.pageControl.currentPage; 97 | 98 | // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) 99 | [self p_loadScrollViewWithPage:page - 1]; 100 | [self p_loadScrollViewWithPage:page]; 101 | [self p_loadScrollViewWithPage:page + 1]; 102 | 103 | // update the scroll view to the appropriate page 104 | [self loadPage:page animated:YES]; 105 | 106 | // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above. 107 | pageControlUsed_ = YES; 108 | // inform the delegate 109 | [delegate_ didScrollToPage:page]; 110 | } 111 | 112 | - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 113 | isRotating_ = YES; 114 | } 115 | 116 | - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 117 | UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 118 | 119 | isRotating_ = NO; 120 | 121 | // save the page and restore it after the rotation 122 | pageBeforeRotation_ = self.pageControl.currentPage; 123 | 124 | [self p_resizeScrollViewForOrientation:orientation]; 125 | [self p_loadScrollViewWithPage:pageBeforeRotation_]; 126 | 127 | //LogRect(@"self.frame", self.frame); 128 | //LogRect(@"self.scrollView.frame", self.scrollView.frame); 129 | } 130 | 131 | - (UIViewController *)currentController { 132 | return [self.viewControllers objectAtIndex:self.pageControl.currentPage]; 133 | } 134 | 135 | 136 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 137 | #pragma mark - 138 | #pragma mark ScrollViewDelegate Methods 139 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 140 | 141 | - (void)scrollViewDidScroll:(UIScrollView *)sender { 142 | // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in 143 | // which a scroll event generated from the user hitting the page control triggers updates from 144 | // the delegate method. We use a boolean to disable the delegate logic when the page control is used. 145 | if (pageControlUsed_ || isRotating_) { 146 | // do nothing - the scroll was initiated from the page control, not the user dragging 147 | return; 148 | } 149 | 150 | // Switch the indicator when more than 50% of the previous/next page is visible 151 | CGFloat pageWidth = self.scrollView.frame.size.width; 152 | int oldpage = self.pageControl.currentPage; 153 | int page = floor((self.scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1; 154 | 155 | self.pageControl.currentPage = page; 156 | 157 | // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling) 158 | [self p_loadScrollViewWithPage:page - 1]; 159 | [self p_loadScrollViewWithPage:page]; 160 | [self p_loadScrollViewWithPage:page + 1]; 161 | 162 | // A possible optimization would be to unload the views+controllers which are no longer visible 163 | 164 | // inform the delegate if page changed 165 | if (page != oldpage) { 166 | [delegate_ didScrollToPage:page]; 167 | } 168 | } 169 | 170 | // At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl 171 | - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { 172 | pageControlUsed_ = NO; 173 | } 174 | 175 | // At the end of scroll animation, reset the boolean used when scrolls originate from the UIPageControl 176 | - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { 177 | pageControlUsed_ = NO; 178 | } 179 | 180 | 181 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 182 | #pragma mark - 183 | #pragma mark Private Methods 184 | /////////////////////////////////////////////////////////////////////////////////////////////////////// 185 | 186 | - (CGRect)p_framePosition:(CGRect)frame forPage:(int)page { 187 | // Calculate frame position 188 | frame.origin.x = frame.size.width * page; 189 | frame.origin.y = 0; 190 | 191 | //LogRect(@"vc.frame", frame); 192 | 193 | return frame; 194 | } 195 | 196 | - (void)p_resizeScrollViewForOrientation:(UIInterfaceOrientation)orientation { 197 | // only resize Scrollview for Landscape on iPad 198 | if ([[UIDevice currentDevice] isIPad] && UIInterfaceOrientationIsLandscape(orientation)) { 199 | [self p_resizeScrollViewForLandscape]; 200 | } else { 201 | [self p_resizeScrollViewForPortrait]; 202 | } 203 | } 204 | 205 | - (void)p_resizeScrollViewForPortrait { 206 | self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.viewControllers.count, 207 | self.scrollView.frame.size.height); 208 | 209 | [self p_repositionSubViews]; 210 | } 211 | 212 | - (void)p_resizeScrollViewForLandscape { 213 | self.scrollView.contentSize = CGSizeMake(self.scrollView.frame.size.width * self.viewControllers.count, 214 | self.scrollView.frame.size.height); 215 | 216 | [self p_repositionSubViews]; 217 | } 218 | 219 | - (void)p_repositionSubViews { 220 | // Reposition all loaded frames 221 | for (int i = 0; i < [self.viewControllers count]; i++) { 222 | UIViewController* vc = [self.viewControllers objectAtIndex:i]; 223 | 224 | if((NSNull *)vc != [NSNull null]) { 225 | // Calculate the position of the frame depending on orientation 226 | vc.view.frame = [self p_framePosition:vc.view.frame forPage:i]; 227 | } 228 | } 229 | 230 | // display same page after rotation than before 231 | self.scrollView.contentOffset = CGPointMake(pageBeforeRotation_*self.scrollView.frame.size.width, 0); 232 | } 233 | 234 | - (void)p_initScrollView { 235 | // init scrollview 236 | //TODO: Startup BUG - Landscape - 237 | //Fix works only for iPad - for iPhone replace CGRect with MBRectMake 238 | //self.scrollView = [[[UIScrollView alloc] initWithFrame:CGRectMake(0.,0.,768.,1024.)] autorelease]; 239 | self.scrollView = [[[UIScrollView alloc] initWithFrame:MBApplicationFrame()] autorelease]; 240 | self.scrollView.pagingEnabled = YES; 241 | [self p_resizeScrollViewForOrientation:[[UIDevice currentDevice]orientation]]; 242 | 243 | self.scrollView.showsHorizontalScrollIndicator = NO; 244 | self.scrollView.showsVerticalScrollIndicator = NO; 245 | self.scrollView.scrollsToTop = NO; 246 | self.scrollView.delegate = self; 247 | // TODO: 248 | self.scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 249 | self.scrollView.contentMode = UIViewContentModeScaleToFill; 250 | [self addSubview:self.scrollView]; 251 | 252 | // init pageControl 253 | self.pageControl = [[[UIPageControl alloc] initWithFrame:CGRectMake(0,0,viewFrame_.size.width, 30)] autorelease]; 254 | self.pageControl.center = CGPointMake(self.scrollView.frame.size.width / 2, 30.0); 255 | self.pageControl.autoresizingMask = UIViewAutoresizingFlexibleWidth; 256 | self.pageControl.contentMode = UIViewContentModeScaleToFill; 257 | self.pageControl.numberOfPages = self.viewControllers.count; 258 | self.pageControl.currentPage = 0; 259 | [self.pageControl addTarget:self action:@selector(changePage:) forControlEvents:UIControlEventValueChanged]; 260 | [self addSubview:self.pageControl]; 261 | 262 | 263 | // lazy loading - commented out 264 | // load the visible page - pages are created on demand 265 | //[self p_loadScrollViewWithPage:0]; 266 | // load the page on either side to avoid flashes when the user starts scrolling 267 | //[self p_loadScrollViewWithPage:1]; 268 | 269 | // load all pages on startup 270 | for (int i=0;i<[dataSource_ numberOfPages];i++) { 271 | [self p_loadScrollViewWithPage:i]; 272 | } 273 | } 274 | 275 | - (void)p_loadScrollViewWithPage:(int)page { 276 | if (page < 0 || page >= self.viewControllers.count) { 277 | return; 278 | } 279 | 280 | // replace the placeholder if necessary 281 | UIViewController *controller = [self.viewControllers objectAtIndex:page]; 282 | 283 | if ((NSNull *)controller == [NSNull null]) { 284 | controller = [dataSource_ viewControllerForPage:page]; 285 | [self.viewControllers replaceObjectAtIndex:page withObject:controller]; 286 | } 287 | 288 | // add the controller's view to the scroll view 289 | if (controller.view.superview == nil) { 290 | // Position the new frame depending on the interface orientation 291 | controller.view.frame = [self p_framePosition:self.scrollView.frame forPage:page]; 292 | 293 | [self.scrollView addSubview:controller.view]; 294 | } 295 | } 296 | 297 | 298 | 299 | @end 300 | -------------------------------------------------------------------------------- /Classes/Views/MBSectionBackgroundView.h: -------------------------------------------------------------------------------- 1 | // 2 | // MBSectionView.h 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface MBSectionBackgroundView : UIView { 13 | NSString *imageName_; 14 | UIImage *image_; 15 | UIImage *imageLandscape_; 16 | } 17 | 18 | // Properties 19 | @property (nonatomic, retain) NSString *imageName; 20 | @property (nonatomic, retain) IBOutlet UIImage *image; 21 | @property (nonatomic, retain) IBOutlet UIImage *imageLandscape; 22 | 23 | - (id)initWithFrame:(CGRect)frame imageName:(NSString *)imageName; 24 | 25 | @end -------------------------------------------------------------------------------- /Classes/Views/MBSectionBackgroundView.m: -------------------------------------------------------------------------------- 1 | // 2 | // MBSectionView.m 3 | // Mercedes 4 | // 5 | // Created by Matthias Tretter on 29.07.10. 6 | // Copyright 2010 YellowSoft. All rights reserved. 7 | // 8 | 9 | #import "MBSectionBackgroundView.h" 10 | 11 | 12 | @implementation MBSectionBackgroundView 13 | 14 | @synthesize imageName = imageName_; 15 | @synthesize image = image_; 16 | @synthesize imageLandscape = imageLandscape_; 17 | 18 | 19 | - (id)initWithFrame:(CGRect)frame imageName:(NSString *)imageName { 20 | if ((self = [super initWithFrame:frame])) { 21 | imageName_ = [imageName copy]; 22 | image_ = imageLandscape_ = nil; 23 | 24 | self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; 25 | self.contentMode = UIViewContentModeRedraw; //UIViewContentModeScaleToFill; 26 | } 27 | 28 | return self; 29 | } 30 | 31 | - (id)initWithFrame:(CGRect)frame { 32 | return [self initWithFrame:frame imageName:nil]; 33 | } 34 | 35 | 36 | // Only override drawRect: if you perform custom drawing. 37 | // An empty implementation adversely affects performance during animation. 38 | - (void)drawRect:(CGRect)rect { 39 | UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation]; 40 | 41 | if (UIInterfaceOrientationIsPortrait(orientation)) { 42 | if (self.image == nil) { 43 | self.image = MBImageNamed(self.imageName); 44 | } 45 | 46 | [self.image drawInRect:rect]; 47 | } else { 48 | if (self.imageLandscape == nil) { 49 | self.imageLandscape = MBImageNamedForOrientation(self.imageName, UIInterfaceOrientationLandscapeLeft); 50 | } 51 | 52 | [self.imageLandscape drawInRect:rect]; 53 | } 54 | } 55 | 56 | 57 | - (void)dealloc { 58 | RELEASE(imageName_); 59 | RELEASE(imageLandscape_); 60 | RELEASE(image_); 61 | 62 | [super dealloc]; 63 | } 64 | 65 | 66 | @end -------------------------------------------------------------------------------- /Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleDocumentTypes 10 | 11 | CFBundleExecutable 12 | ${EXECUTABLE_NAME} 13 | CFBundleIconFiles 14 | 15 | CFBundleIconFiles~ipad 16 | 17 | CFBundleIdentifier 18 | com.yourcompany.${PRODUCT_NAME:identifier} 19 | CFBundleInfoDictionaryVersion 20 | 6.0 21 | CFBundleName 22 | ${PRODUCT_NAME} 23 | CFBundlePackageType 24 | APPL 25 | CFBundleSignature 26 | ???? 27 | CFBundleURLTypes 28 | 29 | CFBundleVersion 30 | 1.3 31 | LSRequiresIPhoneOS 32 | 33 | NSMainNibFile 34 | MainWindow 35 | UIInterfaceOrientation 36 | UIInterfaceOrientationPortrait 37 | UIInterfaceOrientation~ipad 38 | UIInterfaceOrientationPortrait 39 | UIStatusBarHidden 40 | 41 | UIStatusBarStyle 42 | UIStatusBarStyleDefault 43 | UISupportedInterfaceOrientations 44 | 45 | UISupportedInterfaceOrientations~ipad 46 | 47 | UTExportedTypeDeclarations 48 | 49 | UTImportedTypeDeclarations 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/xcuserdata/Matthias.xcuserdatad/xcbreakpoints/Breakpoints.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/xcuserdata/Matthias.xcuserdatad/xcschemes/Mercedes.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 11 | 12 | 14 | 15 | /> 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/xcuserdata/Matthias.xcuserdatad/xcschemes/PageControl.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 11 | 12 | 14 | 15 | /> 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/xcuserdata/Matthias.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Mercedes.xcscheme 8 | 9 | orderHint 10 | 1 11 | 12 | PageControl.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | Classic.app 21 | 22 | Mercedes.app 23 | 24 | PageControl.app 25 | 26 | PageScrollView.app 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/xcuserdata/philip.xcuserdatad/xcschemes/Mercedes.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 11 | 12 | 14 | 15 | /> 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /PageScrollView.xcodeproj/xcuserdata/philip.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | Mercedes.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | Classic.app 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /Prefix.pch: -------------------------------------------------------------------------------- 1 | 2 | #ifdef __OBJC__ 3 | #import 4 | #import 5 | 6 | #import "AppDelegate.h" 7 | #import "Constants.h" 8 | #import "Macros.h" 9 | #import "UIDevice-Helper.h" 10 | #import "ImageHelper.h" 11 | #endif 12 | -------------------------------------------------------------------------------- /de.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myell0w/PageScrollView/c358807f1da00c85862ec7af6ac681c63fcf5421/de.lproj/Localizable.strings -------------------------------------------------------------------------------- /en.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myell0w/PageScrollView/c358807f1da00c85862ec7af6ac681c63fcf5421/en.lproj/Localizable.strings -------------------------------------------------------------------------------- /images/backgrounds/Home-iPad-L.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myell0w/PageScrollView/c358807f1da00c85862ec7af6ac681c63fcf5421/images/backgrounds/Home-iPad-L.png -------------------------------------------------------------------------------- /images/backgrounds/Home-iPad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myell0w/PageScrollView/c358807f1da00c85862ec7af6ac681c63fcf5421/images/backgrounds/Home-iPad.png -------------------------------------------------------------------------------- /images/backgrounds/Home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myell0w/PageScrollView/c358807f1da00c85862ec7af6ac681c63fcf5421/images/backgrounds/Home.png -------------------------------------------------------------------------------- /images/iTunesArtwork: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/myell0w/PageScrollView/c358807f1da00c85862ec7af6ac681c63fcf5421/images/iTunesArtwork -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | 5 | int main(int argc, char *argv[]) { 6 | NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 7 | int retVal = UIApplicationMain(argc, argv, nil, nil); 8 | [pool release]; 9 | return retVal; 10 | } 11 | --------------------------------------------------------------------------------