Tips & Lessons Learned
========================================

You can find a list of constants that can be applied to attributed strings
here:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/NSAttributedString_UIKit_Additions/Reference/Reference.html#//apple_ref/doc/uid/TP40011688


Memory Management
----------------------------------------

http://loufranco.com/blog/files/managing-memory-iphone.html

However, the rules are really simple, and now that I know them, I never run into memory management issues: 

* Declare all of your object pointer @properties as retain unless you have a really good reason not to. Then the setter that is generated will automatically call retain when you assign. When you reassign, it knows to call release on the old value.
* In your dealloc, assign all of your @properties to nil. This has the effect of calling release on the current values if they are not already nil.
* alloc returns an object with a reference count of 1 -- so you have to balance with a release.
* If you alloc, then you should try to release in that same function. To retain the value, assign it to something that retains. Exceptions are if you are a factory function that is returning a value up to be retained by the caller.
* Obviously, each retain call needs a release.
* Built-in convenience functions return objects that are autoreleased. That means you shouldn't call release on them -- the framework will call release at some point (they are registered in an autorelease pool that that is serviced when you return back to the framework). If you created the object without an alloc/init pair, you don't need to call release unless the docs say you do (but they probably don't)
* Check all of your work with the leak detector. Also, if you crash, you're probably doing it wrong -- I will have more to say on that soon.

UITextField
----------------------------------------

Force a UITextField to only allow a certain number of characters. Make sure class is a UITextFieldDelegate.
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
    if (textField.text.length >= 4 && range.length == 0)
        return NO;
    return YES;	
}

Localising Applications
----------------------------------------

http://www.iphonesdkarticles.com/2008/11/localizing-iphone-apps.html

Lessons Learned
----------------------------------------
Do not set a non-pointer value to nil. It will always say incompatible pointer
type "NSInteger and void*" or something along those lines.

You can safely call [tableView reloadData] in viewWillAppear: method without
having the cells being written twice to the view. My fear was that the data is
already set to be written at the time the view first appears and that by putting
reloadData method in viewWillAppear: it would make the contents refresh more
than they needed to. This is not the case. I performed a test where I put a
NSLog in tableView:cellForRowAtIndexPath for every cell. It only printed out the
cell contents once.

Modal window code which implements the modal delegate of the particular view:

- (void)didDismissPathModal:(PathCategory *)path
{
    // @todo Refresh list
    /*
    // Add URL to the list
    [[self directoryContents] addObject:path];

    // Add the new row
    NSUInteger rowNum = [_contents count] - 1;
    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObjects:[NSIndexPath indexPathForRow:rowNum inSection:0], nil] withRowAnimation:UITableViewRowAnimationRight];
    */
    [self dismissModalViewControllerAnimated:YES];
}

You can not declare a variable in a switch...case statement. Declare the variable
outside of the statement. You can then have as many statements in the case
statement. Note, you can declare a variable but you then have to put the entire
statement in a closure.

Localization

When localizing an application, the easiest way to do this is to select the
Info.plist file, open the Utilities pane, under the Localization group click
the + button and add the language you want.

The application's Documents directory can be found at:
~/Library/Application Support/iPhone Simulator/[iOS_VERSION]/Applications/[APP_ID]

Copy

What happens when you copy an object and then use the setter method? Will this cause a memory leak?
[self setName:[newName copy]];

Also, what is the best way to copy values when conforming to NSCopying? do I
simply retain the value of the original value? Or do I make a copy of the original
object's value?
[copy setName:[[self name] copy]];

Determine if x in text field is clicked and fire an event after it is clicked.

- (BOOL)textFieldShouldClear:(UITextField *)textField {
    [self performSelector:@selector(searchBarCancelButtonClicked:) withObject:self.searchBar afterDelay: 0.1];
    return YES;
}

Custom table background:
If you want a image to be a background of a table view you can try this. tableview.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @"tableBg.png"]]

Installing Custom Fonts
----------------------------------------

iOS 3.2 and later support this. Straight from the What's New in iPhone OS 3.2 doc:

Custom Font Support
Applications that want to use custom fonts can now include those fonts in their application bundle and register those fonts with the system by including the UIAppFonts key in their Info.plist file. The value of this key is an array of strings identifying the font files in the application’s bundle. When the system sees the key, it loads the specified fonts and makes them available to the application.

Once the fonts have been set in the Info.plist, you can use your custom fonts as any other font in IB or programatically. 

There is an ongoing thread on Apple Developer Forums: 
https://devforums.apple.com/thread/37824 (login required)

And here's an excellent and simple 3 steps tutorial on how to achieve this (http://kgriff.posterous.com/45359635).

Here are the steps transcribed:

Add your custom font files into your project using XCode as a resource
Add a key to your info.plist file called UIAppFonts.
Make this key an array
For each font you have, enter the full name of your font file (including the extension) as items to the UIAppFonts array
Save info.plist
Now in your application you can simply call [UIFont fontWithName:@"CustomFontName" size:12] to get the custom font to use with your UILabels and UITextViews, etc…
Also: Make sure the fonts are in your Copy Bundle Resources.

//	==============================================================
//	resizedImage
//	==============================================================
// Return a scaled down copy of the image.  

UIImage* resizedImage(UIImage *inImage, CGRect thumbRect)
{
	CGImageRef			imageRef = [inImage CGImage];
	CGImageAlphaInfo	alphaInfo = CGImageGetAlphaInfo(imageRef);
	
	// There's a wierdness with kCGImageAlphaNone and CGBitmapContextCreate
	// see Supported Pixel Formats in the Quartz 2D Programming Guide
	// Creating a Bitmap Graphics Context section
	// only RGB 8 bit images with alpha of kCGImageAlphaNoneSkipFirst, kCGImageAlphaNoneSkipLast, kCGImageAlphaPremultipliedFirst,
	// and kCGImageAlphaPremultipliedLast, with a few other oddball image kinds are supported
	// The images on input here are likely to be png or jpeg files
	if (alphaInfo == kCGImageAlphaNone)
		alphaInfo = kCGImageAlphaNoneSkipLast;

	// Build a bitmap context that's the size of the thumbRect
	CGContextRef bitmap = CGBitmapContextCreate(
				NULL,
				thumbRect.size.width,		// width
				thumbRect.size.height,		// height
				CGImageGetBitsPerComponent(imageRef),	// really needs to always be 8
				4 * thumbRect.size.width,	// rowbytes
				CGImageGetColorSpace(imageRef),
				alphaInfo
		);

	// Draw into the context, this scales the image
	CGContextDrawImage(bitmap, thumbRect, imageRef);

	// Get an image from the context and a UIImage
	CGImageRef	ref = CGBitmapContextCreateImage(bitmap);
	UIImage*	result = [UIImage imageWithCGImage:ref];

	CGContextRelease(bitmap);	// ok if NULL
	CGImageRelease(ref);

	return result;
}


    
    /*
     * @todo Change the view depending on the whether the device is an iPhone
     * or iPad.
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
     *
     */

Enabling AutoCorrection on the fly
--------------------------------------------------------------------------------

This will hopefully allow auto-correction and friends to be used at the same
time as Vim.

Comment from developer:
I had the same problem. The solution is very simple but not documented: You can
only change the properties defined in the UITextInputTraits protocol while the
UITextView in question is NOT the first responder. The following lines fixed it for me:

[self.textView resignFirstResponder];
self.textView.autocorrectionType = UITextAutocorrectionTypeNo;
[self.textView becomeFirstResponder];
Hope this helps somebody.


To merge two dictionaries together:
[myNewDictionary addEntriesFromDictionary:dictionary];


    I found a VERY interesting attribute of the UITextView. When you type a
    letter it ALWAYS uses the attribute directly to the left to determine what
    attributes to apply to the newly inserted text. That is incredibly interesting.


AttributedTextRanges
--------------------------------------------------------------------------------

  o This is meant to increase performance on single line comments where the single
    line comments are repeated multiple times on the same line (ex: ///////////)
    This will increase the performance by orders of magnitude. At the moment it
    is _extremely_ slow.
  o This should speed up highlighting greatly for line comments, strings and
    block comments. Generally only one range needs to be applied to a group of
    words. Because of this it will reduce 99.99% of the calls to ONE call rather
    than N number of words -- which could be hundreds of words.
  o This should also apply to ranges where there is NO state such that anything
    that is not within a range will have their attributes accumulated.
  o It's possible that by checking when states change this would be the point
    where ranges are turned on/off. I will need to do a bit of research, but rather
    than adding a bunch of specialized logic for strings, comments, etc. it may
    be just as easy to check only the state word-by-word and accumulate changes
    that way.
  o Make sure to update both methods that highlight code.
  o Add firstLine, numVisibleLines and numVisibleRows in UITextView. This should
    provide enough info to NSTextStorage to actually do something interesting
    w/ text. numVisibleLines are the actual number of lines. numVisibleRows is
    the total number of rows that are visible in the view. Even though 3 three
    lines are visible they would span 9 rows.
  - Modifying large files is slow. There MUST be a way to prevent iOS from drawing
    or even worrying about the excess text. This is rediculous. It should not
    take that much power to draw a few lines of code, regardless of the size of
    the file.
