title: iOS 5 + iPad 1 = Less Memory Available
body: <p>I have a problem with an existing application for iPad. It is quite sophisticated application written partly native (downloading, local caching and so on), partly using Sencha Touch for UI (without PhoneGap).</p>
  
  <p>Application runs fine on both iPad 1 and iPad 2 under iOS4. But with public release of iOS 5 aproblem appears for iPad 1 users. Application crashes after several seconds of work. Some guys <a href="https://discussions.apple.com/thread/3400742?start=15&amp;tstart=0" rel="nofollow">write</a> that instead of 78 there are only 30 megs of memory available for iPad 1 under iOS 5. And the other blackbox is the UIWebView. Nobody knows its internal limitations.</p>
  
  <p>I have a few ideas how to optimize JavaScript and HTML aspect. For example I've optimized structure and reduce memory allocations in scripts as I could. I've also replaced IMG tags with DIV + background-image. But crashes remains.</p>
  
  <p>Below is the insane solution to the problem.</p>
  
  <p><strong>Solution</strong></p>
  
  <p>There are memory warnings but I can release neither something native nor anything inside JavaScript, I thought. So I decided to do ridiculous thing - to allocate the dummy array of several megabytes and release it on memory warning. This is nuts but it works for me: I could allocate up to 100 megs of RAM on start with simple malloc()</p>
  
  <pre><code>// Member variable
  void* dummy;
  
  // - (void)init    
  dummy = malloc(100000000L);
  </code></pre>
  
  <p>and free it with free() when system asks.</p>
  
  <pre><code>- (void)didReceiveMemoryWarning {
      [super didReceiveMemoryWarning];
  
      if (dummy) {
          free(dummy);
          dummy = nil;
      }
  }
  </code></pre>
  
  <p>This time app works longer. So far so good... Next step - make possible repeated memory freeing.</p>
  
  <pre><code>// Member variable
  NSMutableArray* _memoryWorkaround;
  
  // - (void)init
  int chunkCount = 100;
  int chunkSize = 1L * 1024L * 1024L; // 1 megabyte
  
  _memoryWorkaround = [[NSMutableArray alloc] initWithCapacity:chunkCount];
  
  for (int i = 0; i &lt; chunkCount; i++)
      [_memoryWorkaround addObject:[NSValue valueWithPointer:malloc(chunkSize)]];
  </code></pre>
  
  <p>Here it is - 100 chunks of memory by 1 megabyte allocated. This parameters is subject to revise.</p>
  
  <p>Now we can free up as much memory as needed:</p>
  
  <pre><code>- (void)didReceiveMemoryWarning {
      [super didReceiveMemoryWarning];
  
      if ([_memoryWorkaround count]) {
          NSValue* val = [_memoryWorkaround objectAtIndex:0];
          free([val pointerValue]);
          [_memoryWorkaround removeObject:val];
      }
  }
  </code></pre>
  
  <p>On exit free remaining:</p>
  
  <pre><code>- (void)dealloc {
      if ([_memoryWorkaround count]) {
          for (NSValue* val in _memoryWorkaround)
              free([val pointerValue]);
          [_memoryWorkaround removeAllObjects];
      }
      [_memoryWorkaround release];
      [super dealloc];
  }
  </code></pre>
  
  <p>The last thing to do - is to fill buffer back to chunkCount with NSTimer one by one block.</p>
  
  <p>Seems crazy I know. Is better solution exists?</p>