Usually sample codes use UIButtonTypeDetailDisclosure as right button, but you can't use that unless you really show additional details. For anything else, you must use a custom button.UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 20, 20)]; [button setImage:[UIImage imageNamed:@"myButton.png"] forState:UIControlStateNormal]; view.rightCalloutAccessoryView = button;
Tuesday, May 25, 2010
How to Create Custom Map Annotation Button
Custom accessory button for MKPinAnnotationView right side, create inside MKMapViewDelegate protocol mapView:viewForAnnotation method:
Labels:
accessory,
delegate,
iphone,
map,
MKMapViewDelegate,
MKPinAnnotationView,
UIButton,
UIButtonTypeDetailDisclosure,
UIImage
Thursday, May 20, 2010
How to sort NSMutableArray alphabetically
NSMutableArray contains dynamic info objects, which are removed and added by user. Removal is easy, but addition should be done in alphabetical order.
What are your priorities: writing YASAIIRL algorithms or other features?
NSInteger myCompare(id item1, id item2, void *context)
{
return [(NSString *)((MyItem *)item1).title
localizedCaseInsensitiveCompare:
(NSString *)((MyItem *)item1).title];
}
- (void)addItem:(MyItem *)aItem
{
[self.myList addObject:aItem];
NSArray *temp = [NSArray arrayWithArray:self.myList];
self.myList = [NSMutableArray arrayWithArray:
[temp sortedArrayUsingFunction:myCompare context:NULL]];
}
Might be more fun to write your own Yet Another Search And Insert In Right Location algorithm, but this was fast to code, safe implementation and guaranteed to work.What are your priorities: writing YASAIIRL algorithms or other features?
Labels:
arrayWithArray,
compare,
iphone,
NSArray,
NSMutableArray,
NSString,
sort
How to reload current UIViewController
Sometimes you might need to reopen currently open UIViewController. There might be a UITableView, but doing just [self.myTable reloadData] might not be enough. Try this:
Of course this will work only, if those methods contain operations you need to do while closing and opening your view.[self viewWillDisappear:NO]; [self viewWillAppear:NO];
Friday, May 14, 2010
What would Steve do?
Developer is not "The User". He is biased towards his own comfort zone and all designs, decisions and recommendations are from technical implementation point of view:
- Feature is boring to do: users wouldn't like it.
- Feature is difficult to do: users wouldn't like it.
- Feature changes architecture: users wouldn't like it.
- Feature removes "my code": users wouldn't like it.
Tuesday, May 11, 2010
Refactor or Die (or burden of maintenance)
Agile development says when something is done, it stays done. Don't touch it again! On the other hand refactoring is an extremely important part of agility. How do you combine these, possibly conflicting requirements?
Refactoring is a planned action. When you develop something, it is done as well as it can be at that specific moment. It is scheduled, planned, designed, implemented, tested, documented and released as well as needs to be at the specific moment. When it's done, it's really done.
Developing a new feature, additional requirements or fixing bugs might bring in new information, which makes it possible to improve something already done. Make it more generic, robust or faster. Search for reusing something old.
Refactoring is a fact of life. Experiment, seek alternatives, gain more experience, receive more detailed information, learn from own mistakes or from experts who have made more mistakes than you. Use this for your advantage. Refactoring is not experimenting, but cleaning up afterwards to the most suitable solution.
Don't refactor for the sake of refactoring. If something works, don't touch it without really good reasons. Developing something twice is quite ok, requires less time than refactoring. More safe. Refactoring has to be an improvement.
When you find need for a third similar object/module, then take a moment to consider advantages and dangers of refactoring. Will the be more similar cases in future, how critical areas are you dealing with, how stable have they been bug and feature wise. Would refactoring be worth the risk and investment of time and effort?
Don't refactor for fun. Only when needed, understanding risks.
Refactoring is a planned action. When you develop something, it is done as well as it can be at that specific moment. It is scheduled, planned, designed, implemented, tested, documented and released as well as needs to be at the specific moment. When it's done, it's really done.
Developing a new feature, additional requirements or fixing bugs might bring in new information, which makes it possible to improve something already done. Make it more generic, robust or faster. Search for reusing something old.
Refactoring is a fact of life. Experiment, seek alternatives, gain more experience, receive more detailed information, learn from own mistakes or from experts who have made more mistakes than you. Use this for your advantage. Refactoring is not experimenting, but cleaning up afterwards to the most suitable solution.
Don't refactor for the sake of refactoring. If something works, don't touch it without really good reasons. Developing something twice is quite ok, requires less time than refactoring. More safe. Refactoring has to be an improvement.
When you find need for a third similar object/module, then take a moment to consider advantages and dangers of refactoring. Will the be more similar cases in future, how critical areas are you dealing with, how stable have they been bug and feature wise. Would refactoring be worth the risk and investment of time and effort?
Don't refactor for fun. Only when needed, understanding risks.
Monday, May 10, 2010
UIWebView with Custom Background Image
Taking UIWebView into use is pretty easy, customizing is a bit more complicated. Here's how you can define your own image as background.
NSString *myHtml = [NSString stringWithFormat:
@"<html><head>"
"<style type=\"text/css\">"
"body{"
"background-image:url(%@);"
"}"
",</style>"
"</head>"
"<body>Hello world</body></html>", imgName];
// baseURL for background image, otherwise nil
NSString *path = [[NSBundle mainBundle] bundlePath];
NSURL *baseURL = [NSURL fileURLWithPath:path];
[self.myWebView loadHTMLString:myHtml baseURL:baseURL];
Tuesday, May 4, 2010
SVN Rollback is Backwards Merge
While debugging interesting side-effects, I decided to take a "shortcut" and rollback project sources to some earlier version. Just checking when the weird behaviour start to happen.
Found out that SVN rollback is actually a backwards merge - with the usual, expected and dreaded merge conflicts.
Successful rollback does not necessarily produce compiling code. You got to do rollback - to same version - couple times to catch all merge conflicts. Seems to depend on order of files.
Looking for SVN replacement.
Found out that SVN rollback is actually a backwards merge - with the usual, expected and dreaded merge conflicts.
Successful rollback does not necessarily produce compiling code. You got to do rollback - to same version - couple times to catch all merge conflicts. Seems to depend on order of files.
Looking for SVN replacement.
Change of Blog Scope
Since iPhone is not everything I do, I have decided to start writing short reminders about other areas, too.
Just FYI, nothing to worry about.
Just FYI, nothing to worry about.
Monday, May 3, 2010
How (not) to Name Your Class API
Basically something you should NOT do: don't start your own API calls with "set" or "get", just in case.
By default - invisible from developer eyes - iPhone SDK @synthesize creates setters and getters for the selected class instance variables. If part of your API allows changing these values somehow, you might accidentally overwrite a default setter or getter.
Perfectly legal thing, something you migth want to do on purpose. Very difficult to debug, if you did that by mistake.
Instead of setVariable you could use changeVariable.
By default - invisible from developer eyes - iPhone SDK @synthesize creates setters and getters for the selected class instance variables. If part of your API allows changing these values somehow, you might accidentally overwrite a default setter or getter.
Perfectly legal thing, something you migth want to do on purpose. Very difficult to debug, if you did that by mistake.
Instead of setVariable you could use changeVariable.
How to Create Delayed Tab Change
Not sure, if it's a good idea, but this is how you create "smooth" tab view changes:
Be careful, style is not an easy thing to achieve!
User will notice something happened as expected and your app will look either stylish or slow, depending on your graphics, UI design and overall implementation.#pragma mark - TabBar controller delegate - (void)tabBarController:(UITabBarController*)tbc didSelectViewController:(UIViewController*)newSelection { [UIView beginAnimations:@"myTabFade" context:nil]; [UIView setAnimationDuration:0.5]; for (UIViewController* vc in tbc.viewControllers) vc.view.alpha = (vc==newSelection) ? 1 : 0; [UIView commitAnimations]; }
Be careful, style is not an easy thing to achieve!
Labels:
alpha,
animation,
delegate,
iphone,
UITabBarController,
UIView,
UIViewController
Subscribe to:
Posts (Atom)