Sunday, October 11, 2009

iPhone dev Stupidity 65: Where's the images saved?

~/Library/Application Support/iPhone Simulator/User/Media

iPhone dev Stupidity 64: Crop image from image


- (UIImage*)imageByCropping: (CGRect)rect


{


UIImage * imageToCrop = self;


// convert the rect from screen coords to Quartz 2D coords


rect = CGRectMake(rect.origin.x, self.height - rect.origin.y - rect.size.height, rect.size.width, rect.size.height);



//create a context to do our clipping in


UIGraphicsBeginImageContext(rect.size);


CGContextRef currentContext = UIGraphicsGetCurrentContext();



//create a rect with the size we want to crop the image to


//the X and Y here are zero so we start at the beginning of our


//newly created context


CGRect clippedRect = CGRectMake(0, 0, rect.size.width, rect.size.height);


CGContextClipToRect( currentContext, clippedRect);



//create a rect equivalent to the full size of the image


//offset the rect by the X and Y we want to start the crop


//from in order to cut off anything before them


CGRect drawRect = CGRectMake(rect.origin.x * -1,


rect.origin.y * -1,


imageToCrop.size.width,


imageToCrop.size.height);



//draw the image to our clipped context using our offset rect


CGContextDrawImage(currentContext, drawRect, imageToCrop.CGImage);



//pull the image from our cropped context


UIImage *cropped = UIGraphicsGetImageFromCurrentImageContext();



//pop the context to get back to the default


UIGraphicsEndImageContext();



//Note: this is autoreleased


return cropped;


}



iPhone dev Stupidity 63: Quartz 2D Coords


iPhone dev Stupidity 62: draw on bitmap

Start a new context:

UIGraphicsBeginImageContext(origPic.size);

...

UIImage *newPic = UIGraphicsGetImageFromCurrentImageContext(); 

UIGraphicsEndImageContext();



iPhone dev Stupidity 61: Font

1. Font list supported by iPhone:




From DaringFireball, detailed list here.

  • American Typewriter
  • American Typewriter Condensed
  • Arial
  • Arial Rounded MT Bold
  • Courier New
  • Georgia
  • Helvetica -> iPhone UI use this font
  • Marker Felt
  • Times New Roman
  • Trebuchet MS
  • Verdana
  • Zapfino

2. How to make it bold

You need to pass in the name of the specific font within the family. Use the "fontNamesForFamilyName" method of UIFont to get a list of names.

The naming scheme is not consistent. Here are some examples of bold font names:

"Helvetica-Bold"
"TimesNewRomanPS-BoldMT"
"Arial-BoldMT"
"CourierNewPS-BoldMT"
"Georgia-Bold"

iPhone dev Stupidity 60: Global object lives in NIB

Global object doesn't have a good place to live - you can use singleton.

You can also setup a slot in interface builder for it. 

In my project, I add an IBOutlet for TemplateDB (the sqlite3 wrapper) in Category View Controller.

The pro of this way is that you don't need to write extra code to insure there's only one instance. And the link is set up in interface builder - which means it's kind of data.

iPhone dev Stupidity 59: multi-line label

From here:

myLabel.numberOfLines = 0;

iPhone dev Stupidity 58: sqlite3 programming

iPhone SDK Tutorial: Reading data from a SQLite Database

iPhone dev Stupidity 57: Illegal char in SQL

illegal char in SQL statement is '
you can replace it with '' (two ')

iPhone dev Stupidity 56: Sqlite3 Lua binding

Lua scripting for Sqlite3

1. using sqlite3 binder: lsqlite3
    fix the make file to link with lua.a - (the default is liblua51 which might be for win/linux)
    make it will produce a lsqlite3.bundle which is not in the lua path

2. fix luaconf.h to add *.bundle in search path(from lua-users.org)

    #define LUA_CPATH_DEFAULT \
     "./?.bundle;"  LUA_CDIR"?.bundle;" LUA_CDIR"loadall.bundle;" \
     "./?.so;"  LUA_CDIR"?.so;" LUA_CDIR"loadall.so"

    Then:
    > make macosx
    > make install

Now you can require 'lsqlite3' to script more.

The test suite of lsqlite3 can pass while there's many non-aligned pointer release error (which doesn't matter very much).



iPhone dev Stupidity 55: SQL in 10 Min

Tips from Sam's Teach Yourself SQL in 10 Minutes:

Lesson 3:
* it is perfectly legal to sort data by a column that is not retrieved.
* If you want to sort descending on multiple columns, be sure each column has its own DESC keyword.

Lesson 4:
* Making the client application (or development language) do the databases job will dramatically impact application performance and will create applications that cannot scale properly. In addition, if data is filtered at the client, the server has to send unneeded data across the network connections, resulting in a waste of network bandwidth usage.
* because AND ranks higher in the order of evaluation, the wrong operators were joined together.
* The biggest advantage of IN is that the IN operator can contain another SELECT statement, enabling you to build highly dynamic WHERE clauses.

Lesson 6:
* The brackets ([]) wildcard is not supported by all DBMSs. - SQLite3 doesn't support it.
* Search patterns that begin with wildcards are the slowest to process.

Lesson 7:
* || is actually the preferred syntax, so more and more DBMSs are implementing support for it. - SQLite3 doesn't support the + syntax.
* an unnamed column cannot be used within a client application because the client has no way to refer to that column. To solve this problem, SQL supports column aliases. An alias is just that, an alternative name for a field or value. Aliases are assigned with the AS keyword.

Lession 8:
* If you do decide to use functions, make sure you comment your code well, so that at a later date you (or another developer) will know exactly what SQL implementation you were writing to* SQLite3 core functions at: http://www.sqlite.org/lang_corefunc.html

Lesson 9:
* Use COUNT(column) to count the number of rows that have values in a specific column, ignoring NULLvalues.* When specifying alias names to contain the results of an aggregate function, try to not use the name of an actual column in the table. Although there is nothing actually illegal about doing so, many SQL implementations do not support this and will generate obscure error messages if you do so.

Lesson 10:
* Every column listed in GROUP BY must be a retrieved column or a valid expression (but not an aggregate function).
* The difference between HAVING and WHERE Here's another way to look it:WHERE filters before data is grouped, and HAVING filters after data is grouped. This is an important distinction; rows that are eliminated by a WHERE clause will not be included in the group. This could change the calculated values which in turn could affect which groups are filtered based on the use of those values in the HAVING clause.
* you should make that distinction yourself. Use HAVING only in conjunction withGROUP BY clauses. Use WHERE for standard row-level filtering.

Lesson 11:
* Breaking up the queries over multiple lines and indenting the lines appropriately as shown here can greatly simplify working with subqueries.
* Subquery SELECT statements can only retrieve a single column. Attempting to retrieve multiple columns will return an error.

Lesson 13:
* It is also worth noting that table aliases are only used during query execution. Unlike column aliases, table aliases are never returned to the client.
* Self joins are often used to replace statements using subqueries that retrieve data from the same table as the outer statement. Although the end result is the same, many DBMSs process joins far more quickly than they do subqueries. It is usually worth experimenting with both to determine which performs better.

Lesson 14:
* The UNION automatically removes any duplicate rows from the query result set (in other words, it behaves just as do multiple WHERE clause conditions in a single SELECT would).

Lesson 15:
* Always Use a Columns List As a rule, never use INSERT without explicitly specifying the column list. This will greatly increase the probability that your SQL will continue to function in the event that table changes occur.

Lesson 16:
* Before you use a WHERE clause with an UPDATE or a DELETE, first test it with a SELECT to make sure it is filtering the right records—it is far too easy to write incorrect WHERE clauses.
Lesson 18:
* Performance Issues Because views contain no data, any retrieval needed to execute a query must be processed every time the view is used. If you create complex views with multiple joins and filters, or if you nest views, you may find that performance is dramatically degraded. Be sure you test execution before deploying applications that use views extensively.
* Using views, you can write the underlying SQL once and then reuse it as needed.
* views are easy to create and even easier to use. Used correctly, views can greatly simplify complex data manipulation.

Lesson 19:
* Because stored procedures are usually stored in a compiled form, the DBMS has to do less work to process the command. This results in improved performance.

Lesson 21:
* Cursors are used primarily by interactive applications in which users need to scroll up and down through screens of data, browsing or making changes.

Lesson 22:
* Performing client-side checks is a time-consuming process. Having the DBMS do the checks for you is far more efficient.
* Primary key values can never be reused. If a row is deleted from the table, its primary key must not be assigned to any new rows.
* After a foreign key is defined, your DBMS does not allow the deletion of rows that have related rows in other tables. * Cascading delete. If enabled, this feature deletes all related data when a row is deleted from a table.
* Indexes improve the performance of retrieval operations, but they degrade the performance of data insertion, modification, and deletion. When these operations are executed, the DBMS has to update the index dynamically.
* Indexes are used for data filtering and for data sorting. If you frequently sort data in a specific order, that data might be a candidate for indexing.* It is always a good idea to revisit indexes on a regular basis to fine-tune them as needed.
* As a rule, constraints are processed more quickly than triggers, so whenever possible, use constraints instead.



iPhone dev Stupidity 54: Convert rect of zero size

When the rect's width/height is zero, UIView method: convertRect:toView: will not work - it just returns the rect passed in.

To fix:

- (CGRect) extConvertRect: (CGRect) rect toView: (UIView *) view{


if(rect.size.width == 0 || rect.size.height == 0){


CGPoint lt = [self convertPoint: rect.origin toView: view];


return CGRectMake(lt.x, lt.y, rect.size.width, rect.size.height);


}else{


return [self convertRect:rect toView: view];


}


}


iPhone dev Stupidity 53: Read the Human Interface Guide

Sure there's lots of "SHOULD" in the HIG:


"Note that although the touch and hold gesture is the primary way users reveal the edit menu, they can also double-tap a word in a text view to select it and reveal the menu at the same time. If you support the menu in a custom view, you should respond to both gestures. In addition, you can define the object that is selected by default when the user double taps."


"If you support the Cut, Copy, and Paste commands in your application, you should also support undo and redo (described in“Supporting Undo and Redo”). This is because the edit menu does not require confirmation before the actions are performed and users often expect to be able to undo recent operations if they change their minds."


And sure, they're very good advice - unless you just want get rejected by app store.

iPhone dev Stupidity 52: Print frame in GDB

To print the frame in gdb:


(gdb) p (CGRect)[self frame]


$1 = {


  origin = {


    x = 12, 


    y = 150


  }, 


  size = {


    width = 72, 


    height = 49


  }


}



You can also 
 po self

iPhone dev Stupidity 51: Unit test - how to debug?

XCode doesn't support iPhone unittest very well. 

After trying very hard to setup the SenUnitTest for iPhone, you'll find it can not be injected test - which means your app can't link into the unittest target for symbol resolving. Then you give up and build a non-injected unittest target, build and the test runs. It seems everything is OK.

But when there's a failure, you CAN'T DEBUG it. XCode's unit test use kind of shell script to drive the testing - the failure is buried far away from the debugger. It's really annoying. Robert Martin once said that with unit test he uses debugger less and less - but he doesn't mean he can live without a debugger.

So I switch to google-toolbox-for-mac. It's really sample - using the same SenUnitTest code with iPhone and without too much setup headache. Just a standalone iPhone app with all your test code in it - no magic.

iPhone dev Stupidity 50: Base SDK when migrating to iPhone OS 3.0

Remember to change the Base SDK, for those frameworks used by your project is relative to this SDK.



XCode doesn't change it for you - If you use some new 3.0 features (like UIPasteboard), XCode will search it from the base SDK folder - which will result a failure when it fails to find the new 3.0 frameworks.

iPhone dev Stupidity 49: Reverse a string

If you don't want to rewrite one, check this:


-(NSString *) reverseString
{
NSMutableString *reversedStr;
int len = [self length];
 
// Auto released string
reversedStr
= [NSMutableString stringWithCapacity:len];
 
// Probably woefully inefficient...
while (len > 0)
[reversedStr appendString:
[NSString stringWithFormat:@"%C", [self characterAtIndex:--len]]];
 
return reversedStr;
}

iPhone dev Stupidity 48: Launching SMS



From [iPhone Developer:Tips]

"Also not supported by the iPod Touch, is the ability to quickly setup the SMS client so that your users can quickly send a text message. It is also possible to provide the body of the text message.

The format looks like this:

sms:${PHONENUMBER_OR_SHORTCODE}

NOTE: Unlike other URLs, an SMS url doesn’t use the “//” syntax. If you add these it will assume it is part of the phone number which is not.

1
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"sms:55555"]];

NOTE: According to the official SMS specification, you should be able to send a body as well as the phone number by including “?body=” parameter on the end of the URL … unfortunately Apple doesn’t seem to support this standard."


There's also an article on Launching your app using custom URL scheme.

iPhone dev Stupidity 47: Pixel position, int or float?

iPhone draws at float level.

If you use int - after some rounding, the pixel will be wrongly positioned.

iPhone dev Stupidity 46: retain vs asign - who's the owner?

Don't use retain just because it's convenient.

If a child holds a reference to it's parent, it's not a retain - from the life time perspective, when the parent get released, the child will be released. It's an assign.

If the child retain the parent: 

parent new 0 -> 1
child -> parent 1 -> 2
parent release 2 -> 1

The parent will have no chance to get released with the extra retain.