text

UIButton Set BackgroundColor for State

It has driven me insane for a while that Apple’s UIButton class has setBackgroundImage forState method but it doesn’t have setBackgroundColor forState method.  I wrote this quick subclass of UIButton to do just that.  

It is fairly simple, and all you need to do is the following:

[btn setBackgroundColor:[UIColor colorWithRed:.949 green:.914 blue:.859 alpha:1.0] forState:UIControlStateNormal];

[btn setBackgroundColor:[UIColor colorWithRed:.859 green:.765 blue:.616 alpha:1.0] forState:UIControlStateHighlighted];

Just set these two methods along with all the other settings on the UIButton that you would normally have.

You can view the source here:

https://github.com/ayanok/AYUIButton

text

iFlashCardPro - Update Fail!

I finally finished working on an update for iFlashCardPro, which took a while doing a little bit here and there due to being too busy.  I submitted an update to Apple which they approved rather quickly, only to find out that the build crashed upon launch.  

Only to find out that while testing the final build before sending out was not correct, apparently I accidentally deleted the MainWindow.xib file when cleaning up some un-needed files.  But the cache of the build on my device did not trigger a crash.  GG :(

Hopefully I can get Apple to push this fix rather quickly :(

WARNING: warning to anyone who hasn’t updated yet, do not update until 2.0.1 has been approved!

text

UIView Blur fun!

I recently had an issue where I was displaying a UIView within a UIViewController where it would display and all the contents of said view were blurry.  In addition, once rotated the contents would no longer be blurry.  

I spent the last hour trying to figure out what the issue is, soon did I realize using odd numbers for frame sizes is often a no go.  Apparently using odd numbers can allow for the element to be drawn on a half pixel (ie making every blurry).  

A future note to self, don’t do this!  I hope this will help anyone that comes across this issue, I know it wasted some of my time :/

text

Load Images from Web into Control & NSString Category

Up until recently I haven’t had the need to load images into a table view from the web. I will be showing two very useful items to add to your arsenal. That is if you don’t already know this.

One very useful concept in Objective-C is Categories. In short Categories can allow you to extend existing classes. For instance I created a Category that Loads an Image from the web, I extended the NSString class. Instead of a couple lines of code to get the image I now have it in one.

Example:
UIImage *img = [_urlString getImageFromWeb];

Instead of:
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:_str]];
UIImage *image = [UIImage imageWithData:data];

And that is not including any error checking so, it feels much cleaner and quicker to simply create a Category.

Creating a Category is Simple.

“NSString+Categories.h”
@interface NSString (CustomName)
- (UIImage*) getImageFromWeb;
@end

“NSString+Categories.m”

@implementation NSString (CustomName)

- (UIImage*) getImageFromWeb
{
NSString *_str = self;
UIImage *image = nil;

@try {
if ([_str rangeOfString:@”http”].location != NSNotFound)
{
NSData *data = [NSData dataWithContentsOfURL: [NSURL URLWithString:_str]];
image = [UIImage imageWithData:data];
}
}
@catch (NSException * e) {
image = nil;
}

return image;
}

@end

Now you can load an Image in one line!

Now for the fun control! Creating a views loads images from the web without slowing down user interaction is pretty easy. I will be showing you code that I’m currently using in my project so I’m sure you will want to change the naming of the control ect.

Lets start out with the header.

@protocol IFUIImageLoadViewDelegate;

@interface IFUIImageLoadView : UIView
{
UIActivityIndicatorView *aIndicator;
UIImageView *imageView;

id object;
id <IFUIImageLoadViewDelegate> delegate;
}

@property (nonatomic, retain) UIActivityIndicatorView *aIndicator;
@property (nonatomic, retain) UIImageView *imageView;
@property (nonatomic, assign) id <IFUIImageLoadViewDelegate> delegate;
@property (nonatomic, assign) id object;

- (id)initWithFrame:(CGRect)frame imgURLString:(NSString*) _url object:(id) _obj image:(UIImage*) _image;
- (void) downloadImageOnThread:(NSString*) _urlString;
- (void) updateImageView:(UIImage*) _img;

@end

@protocol IFUIImageLoadViewDelegate <NSObject>
@optional
- (void) imageLoadViewFinishedWithImage:(UIImage*) _image forObject:(id) _obj;
@end


This class we are writing is basically just a standard view. I think it looks nice to have the activity indicator spinning while the images are loading so we added that, although this is not necessary. I also have an “object” property which allows me to pass one of the objects that I will be assigning the image to.

Passing in the Object allows me to call the delegate method with the object and the image and store the image. This is very useful in my case, because the user will be downloading the images with the Sets from this web service. Doing this allows the images to only be downloaded once. Also I’m sure you have noticed that the UITableViewCells when scrolled are not just kept in memory they will be reloaded, so we do not want to load these images multiple times if it is not necessary.

The Init for this view we are passing the frame, image string, object we will be assigning the image to and an UIImage Object. The reason we would like to pass an Image to this, is if the image has already been cached in memory we don’t want to download the image again.

.m File:

@implementation IFUIImageLoadView
@synthesize aIndicator, imageView, object, delegate;

- (id)initWithFrame:(CGRect)frame imgURLString:(NSString*) _url object:(id) _obj image:(UIImage*) _image {
if ((self = [super initWithFrame:frame])) {

self.backgroundColor = [UIColor blackColor];
self.layer.cornerRadius = 5.0;
self.layer.borderColor = [[UIColor whiteColor] CGColor];
self.layer.borderWidth = 2.0;

self.object = _obj;

UIImageView *imgV = [[UIImageView alloc] initWithFrame:CGRectMake(2, 2, self.frame.size.width - 4, self.frame.size.width - 4)];
imgV.backgroundColor = [UIColor clearColor];
self.imageView = imgV;
[self addSubview:imgV];
[imgV release];

if (_image == nil)
{
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activity.frame = CGRectMake(self.center.x - (activity.frame.size.width/2), self.center.y - (activity.frame.size.height/2), activity.frame.size.width, activity.frame.size.height);
activity.hidesWhenStopped = YES;
self.aIndicator = activity;
[self addSubview:activity];
[activity release];

[self.aIndicator startAnimating];
[NSThread detachNewThreadSelector:@selector(downloadImageOnThread:) toTarget:self withObject:_url];
}
else
{
self.imageView.image = _image;
}

}
return self;
}

In the init method, I am setting up the view’s styling, UIImageView Property, and the activity Indicator. This is where the UIImage being passed comes in handy, basically if the UIImage you are passing is not nil then use the image vs loading the image from the web.

The next method we want to implement is loading the Image on a Separate thread. Doing so Will not lock up the UI. Look how quick, clean, and easy the NSString category we implemented was!

- (void) downloadImageOnThread:(NSString*) _urlString
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

UIImage *img = [_urlString getImageFromWeb];
[self performSelectorOnMainThread:@selector(updateImageView:) withObject:img waitUntilDone:YES];

[pool release];
}

- (void) updateImageView:(UIImage*) _img
{
self.imageView.image = _img;
[self.aIndicator stopAnimating];

if ([self.delegate respondsToSelector:@selector(imageLoadViewFinishedWithImage:forObject:)])
[self.delegate imageLoadViewFinishedWithImage:_img forObject:self.object];
}

- (void)dealloc {
delegate = nil;
object = nil;
[imageView release], imageView = nil;
[aIndicator release], aIndicator = nil;
[super dealloc];
}

And the final result looks like this.

Source Code

text

Easy Code that I didn’t know

So As I have created custom input views for my text input fields on the iphone I have always had issues with the styling.  IE getting that standard look that Apple uses.  Well ladies and gentlemen had I actually read the documentation (like I should have I would have found this nice gem.  The following image displays what I had wanted.

In order to achieve this all I had to do was the following:

UIToolbar *tool = [[UIToolbar alloc] initWithFrame:self.frame];

tool.barStyle = UIBarStyleBlack;

tool.translucent = YES;

UIBarButtonItem *btnCancel = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel 

  target:self action:@selector(btnCancelPress:)];

UIBarButtonItem *btnSave = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave

  target:self action:@selector(btnSavePress:)];

UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace 

  target:nil action:nil];

NSArray *barItems = [NSArray arrayWithObjects:btnCancel, flexibleSpace, btnSave, nil];

[tool setItems:barItems];

[btnCancel release];

[btnSave release];

[flexibleSpace release];

[self addSubview:tool];

[tool release];

The trick was to set tool.barStyle = UIBarStyleBlack;

If you just left it as default, the toolbar would display with buttons that didn’t animate when clicked.  Or if you set the tint style with default, it would also have the issue of not being able to set the button colors to easily. Also the buttons would not animate when selected.

Tip of the day: Always read the documentation!

text

Things New iOS Developers Should know Part 1

I have been learning and developing for iOS for a bit over a year now, and at my day to day developer job I don’t get the opportunity to work with OOP style programming.  Over time I lost many of the basics that I learned while I was in college that I never should have forgotten.  There is always the case when learning a language of certain aspects of the language acting in a different manor that what you are generally used to.  I have been thinking that there are many things I wish I would have known when developing my first app. 

I look back on the code I had written and realize how terrible it is!  I will be posting links overtime of things that iOS developers should know.  I know many of you experienced developers already know these things, but there maybe some tid bits that you may not have know and could help you in the future.

As we all know development is an on going learning experience, and we must advance our knowledge on programming.  If anyone has other links people may find useful please drop me a line, I would be interested to read these resources.

This morning I found this little Objective-C fact list, and I thought some others may find this information useful.  Give it a read and tell me what you think!

Mac Developer Tips

text

Difficult Bug - Finally solved!

Well the last couple of hours I had a very difficult bug that I just could not figure out.  Basically I had a NSString that was being populated via SQLite.  Over and over my application would crash when trying to set or get the value of the property.  I was getting the following entry in the debugger: 

*** -[CFString _cfTypeID]: message sent to deallocated instance 0x772f970

I have never seen this before, after a while of fiddling I finally figured out where the problem was located.  The following block of code contained the error:

NSString *scan = 

[[NSString alloc] init];

scan = @”“;

char *scanStr = (char*)sqlite3_column_text(stmt, 3);

if (scanStr != nil)

scan = [NSString stringWithUTF8String:scanStr];

 Wait for it, wait for it, do you see it? Well here is something I learned not to do, do not allocate a string and then try to create an autoreleased string later.  I believe doing this messes with the pointers, I could be wrong however. 

Lesson learned do not do this instead do the following:

NSString *scan = 

nil;

scan = @”“;

char *scanStr = (char*)sqlite3_column_text(stmt, 3);

if (scanStr != nil)

scan = [NSString stringWithUTF8String:scanStr];

 

 Doing this will fix your problems, lesson learned and I hope this helps someone!

likes

follow