Giter Club home page Giter Club logo

ios6ptl's Introduction

This is the sample code to iOS 6 Programming Pushing the Limits by Rob Napier and Mugunth Kumar.

###Licensing

The sample code to iOS 6 Programming Pushing the Limits is licensed under the MIT License:

Copyright (c) 2012 Rob Napier and Mugunth Kumar

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

ios6ptl's People

Contributors

jaythrash avatar martinezdelariva avatar mugunthkumar avatar rnapier avatar yas375 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ios6ptl's Issues

ch06 -TableViewPerformance - drawInRect method slows down scrolling

In CustomDrawnCell.m method
[_thumbnail drawInRect:CGRectMake(12, 4, 35, 35)];

slows down scrolling drastically(debugged with CoreAnimation instrument). Framerate can drop to 8fps

Is that because of iOS6.png image is too big? Or custom drawing with CG is not so fast anymore?

Tested both on 4S and 5.

isMenuItemsStale stalenessLevel issue

Talking about ch24/iHotelApp/iHotelApp/ directory.

AppCache.m:

+(BOOL) isMenuItemsStale
{
...
NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:@"MenuItems.archive"];    
NSTimeInterval stalenessLevel = [[[[NSFileManager defaultManager] attributesOfItemAtPath:archivePath error:nil] fileModificationDate] timeIntervalSinceNow];
...
}

stalenessLevel is computed from the time of the last modification of the corresponding data file. Thus, in order to have the correct time value, we need that every new data are written to local file as soon as we receive it from the remote engine in iHotelAppMenuViewController viewWillAppear method. But this is not done sooner than in viewWillDisappear method.

This "post-write" strategy is taken also in AppCache cacheData:toFile: method, where (see [leastRecentlyUsedCacheData writeToFile:archivePath atomically:YES];) the data gets written to disk only after it can't remain in memory any more.

When combined with "pre-write" stalenessLevel concept, some stale data are declared as not stale.

Fix is rather simple provided one caching strategy will be chosen as preferred.

Code excerpts follow.

iHotelAppMenuViewController:

-(void) viewWillAppear:(BOOL)animated {

  self.menuItems = [AppCache getCachedMenuItems];  
  [self.tableView reloadData];

  if([AppCache isMenuItemsStale] || !self.menuItems) {

    [AppDelegate.engine fetchMenuItemsOnSucceeded:^(NSMutableArray *listOfModelBaseObjects) {

      self.menuItems = listOfModelBaseObjects;
      [self.tableView reloadData];
    } onError:^(NSError *engineError) {
      [UIAlertView showWithError:engineError];
    }];
  }

  [super viewWillAppear:animated];
}

-(void) viewWillDisappear:(BOOL)animated {

  [AppCache cacheMenuItems:self.menuItems];
  [super viewWillDisappear:animated];
}

AppCache.m:

+(void) cacheData:(NSData*) data toFile:(NSString*) fileName
{
  [memoryCache setObject:data forKey:fileName];
  if([recentlyAccessedKeys containsObject:fileName])
  {
    [recentlyAccessedKeys removeObject:fileName];
  }

  [recentlyAccessedKeys insertObject:fileName atIndex:0];

  if([recentlyAccessedKeys count] > kCacheMemoryLimit)
  {
    NSString *leastRecentlyUsedDataFilename = [recentlyAccessedKeys lastObject];
    NSData *leastRecentlyUsedCacheData = [memoryCache objectForKey:leastRecentlyUsedDataFilename];
    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:fileName];  
    [leastRecentlyUsedCacheData writeToFile:archivePath atomically:YES];

    [recentlyAccessedKeys removeLastObject];
    [memoryCache removeObjectForKey:leastRecentlyUsedDataFilename];
  }
}

+(BOOL) isMenuItemsStale
{
  // if it is in memory cache, it is not stale
  if([recentlyAccessedKeys containsObject:@"MenuItems.archive"])
    return NO;

    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:@"MenuItems.archive"];  

  NSTimeInterval stalenessLevel = [[[[NSFileManager defaultManager] attributesOfItemAtPath:archivePath error:nil] fileModificationDate] timeIntervalSinceNow];

  return stalenessLevel > kMenuStaleSeconds;
}

isMenuItemsStale return issue

Talking about ch24/iHotelApp/iHotelApp/ directory.

Since fileModificationDate is the date from the past it returns negative value when sent a message timeIntervalSinceNow. Return statement thus evaluates always to NO. I think return fabs(stalenessLevel) > kMenuStaleSeconds; should do the job.

AppCache.m:

+(BOOL) isMenuItemsStale
{
...  
    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:@"MenuItems.archive"];  

  NSTimeInterval stalenessLevel = [[[[NSFileManager defaultManager] attributesOfItemAtPath:archivePath error:nil] fileModificationDate] timeIntervalSinceNow];

  return stalenessLevel > kMenuStaleSeconds;
}
@end

isMenuItemsStale shortcut issue

Talking about ch24/iHotelApp/iHotelApp/ directory.

What is the reason for declaring, that if data is in memory cache, it is not stale? As in AppCache.m:

+(BOOL) isMenuItemsStale
{
  // if it is in memory cache, it is not stale
  if([recentlyAccessedKeys containsObject:@"MenuItems.archive"])
    return NO;
...
}

Below I have extracted all code excerpts to visualize at least two unclear points with this declaration, each of which, when confirmed, would invalidate it.

Point 1:
Data can be in the memory long enough (i.e. longer than kMenuStaleSeconds) to get stale.

Point 2:
Prior to call [AppCache isMenuItemsStale] in the view controller viewWillApear method there is a call to [AppCache getCachedMenuItems] which inserts the data into memory cache and also into recentlyAccessedKeys in case it was not there. Call to [AppCache isMenuItemsStale] thus returns NO in all cases.

I think the whole if statement should be removed.

Thanks!

iHotellAppMenuViewController.m:

-(void) viewWillAppear:(BOOL)animated {

  self.menuItems = [AppCache getCachedMenuItems];  
  [self.tableView reloadData];

  if([AppCache isMenuItemsStale] || !self.menuItems) {

    [AppDelegate.engine fetchMenuItemsOnSucceeded:^(NSMutableArray *listOfModelBaseObjects) {

      self.menuItems = listOfModelBaseObjects;
      [self.tableView reloadData];
    } onError:^(NSError *engineError) {
      [UIAlertView showWithError:engineError];
    }];
  }

  [super viewWillAppear:animated];
}

AppCache.m:

+(NSMutableArray*) getCachedMenuItems
{
  return [NSKeyedUnarchiver unarchiveObjectWithData:[self dataForFile:@"MenuItems.archive"]];
}

+(NSData*) dataForFile:(NSString*) fileName
{
  NSData *data = [memoryCache objectForKey:fileName];  
  if(data) return data; // data is present in memory cache

    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:fileName];
  data = [NSData dataWithContentsOfFile:archivePath];

  if(data)
    [self cacheData:data toFile:fileName]; // put the recently accessed data to memory cache

  return data;
}

+(void) cacheData:(NSData*) data toFile:(NSString*) fileName
{
  [memoryCache setObject:data forKey:fileName];
  if([recentlyAccessedKeys containsObject:fileName])
  {
    [recentlyAccessedKeys removeObject:fileName];
  }

  [recentlyAccessedKeys insertObject:fileName atIndex:0];

  if([recentlyAccessedKeys count] > kCacheMemoryLimit)
  {
    NSString *leastRecentlyUsedDataFilename = [recentlyAccessedKeys lastObject];
    NSData *leastRecentlyUsedCacheData = [memoryCache objectForKey:leastRecentlyUsedDataFilename];
    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:fileName];  
    [leastRecentlyUsedCacheData writeToFile:archivePath atomically:YES];

    [recentlyAccessedKeys removeLastObject];
    [memoryCache removeObjectForKey:leastRecentlyUsedDataFilename];
  }
}

+(BOOL) isMenuItemsStale
{
  // if it is in memory cache, it is not stale
  if([recentlyAccessedKeys containsObject:@"MenuItems.archive"])
    return NO;

    NSString *archivePath = [[AppCache cacheDirectory] stringByAppendingPathComponent:@"MenuItems.archive"];  

  NSTimeInterval stalenessLevel = [[[[NSFileManager defaultManager] attributesOfItemAtPath:archivePath error:nil] fileModificationDate] timeIntervalSinceNow];

  return stalenessLevel > kMenuStaleSeconds;
}

Missing sample code for chapter 21

Hi,
It seems the sample code for chapter 21 (Storyboard + Custom Transitions) is still missing.
Could you please fix this? thanks.

Edit: This issue has been fixed. You can put it as solved. Thanks.

UIRectFill() uses fill color, not stroke color

On p142:

[[UIColor redColor] setStroke];
CGContextSaveGState(UIGraphicsGetCurrentContext());
[[UIColor blackColor] setStroke];
CGContextRestoreGState(UIGraphicsGetCurrentContext());
UIRectFill(CGRectMake(10, 10, 100, 100)); // Red

The calls to setStroke should be setFill. Thanks to Tan Yuguo for finding this.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.