NSString to UIImage

I had the need to take a regular old NSString and get a UIImage representation of that text. It seems like a relatively straightforward thing to do, so here is the code that I put together:

+ (UIImage *)imageWithView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}
 
+ (UIImage *)imageWithString:(NSString *)theString font:(UIFont *)theFont color:(UIColor *)theColor
{
    UILabel *tempLabel = [[UILabel alloc] initWithFrame:CGRectZero];
    tempLabel.backgroundColor = [UIColor clearColor];
    tempLabel.textColor = theColor;
    tempLabel.font = theFont;
    tempLabel.text = theString;
    [tempLabel sizeToFit];
 
    return [self imageWithView:tempLabel];
}

As an added bonus, if you happen to be using Font Awesome in your iOS project (and let’s be honest, if you aren’t, you should be), here is a bonus method:

+ (UIImage *)imageWithFontAwesomeIcon:(NSString *)faIcon fontSize:(CGFloat)fontSize color:(UIColor *)fontColor
{
    return [self imageWithString:[NSString fontAwesomeIconStringForIconIdentifier:faIcon]
                            font:[UIFont fontWithName:kFontAwesomeFamilyName size:fontSize]
                           color:fontColor];
}

BTW, Happy Birthday to Brian Setzer, who is a fantastic guitar player and singer.

UITextView font in IB not respected

One thing that I found to be a bit odd is that, with the latest Xcode 5 and iOS 7 SDK, if you create a UITextView inside of a UITableViewCell in Interface Builder, and change the font of the text view, it will not use your changed font in the simulator or on a device. After checking with Stack Overflow, I found that if I ticked the Selectable property for my UITextView, all of a sudden it started to respect the new font that I had selected. I am not sure if that is a bug or by design, anyone have any ideas or cite documentation one way or the other?

BTW, Happy Birthday to Leonard Nimoy. Live long and prosper.

Use NIB-based UITableViewCell properly

I like to create my complex UITableViewCell objects in their own NIB files, as it helps me keep things well organized. Unfortunately, I felt like I was not able to use NIB-based UITableViewCell properly, as the implementation of this was always a bit clunky in my opinion, since I was relegated to doing something like this:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *CellIdentifier = @"CellIdentifier";
 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) 
    {
        [[NSBundle mainBundle] loadNibNamed:@"MyCustomCell" owner:self options:NULL];
        cell = myCustomCell;
        self.myCustomCell = nil;
    }
 
    // do something here with the cell
 
    return cell;
}

Ugh, this was a bit messy. You had to make sure that your MyCustomCell.xib file had the file’s owner pointing back to your view controller class, and that you set up an IBOutlet to the cell.

The ability to take a project and require the latest version of iOS can be a refreshing thing, as it allows one to come up to the latest APIs and practices without having to maintain painful backward compatibility. Just such a thing happened today as I learned about the proper way to use a UITableViewCell from a NIB file.

This process involves registering a class or NIB file to work with a UITableView, hooked in through the cell identifier. To set up this registration, you would do something like this in your viewDidLoad method:

UINib *nib = [UINib nibWithNibName:@"MyCustomCell" bundle:nil];
[_theTableView registerNib:nib forCellReuseIdentifier:CellIdentifier];

(Just make sure to set up your CellIdentifier NSString variable as a global in the class or as a static in the same area that you register the NIB.) And then, the cellForRowAtIndexPath method has a little less heft to it:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
 
    // do something here with the cell
 
    return cell;
}

Because you have registered the NIB file with the cell identifier on your table view, the dequeueReusableCellWithIdentifier method knows how to either reuse or create a cell without having to explicitly do it in code. I like less heft.

BTW, Happy St. Patrick’s Day to everyone, Irish and non-Irish alike. Please be safe out there and don’t do anything dumb, which is actually a good rule to live by the other 364.24 days of the year as well.

Core Data error: The operation couldn’t be completed. (Cocoa error 19.)

Well, it has been over a year since I last had a customer with a corrupted database problem. Which means that I guess I was overdue. And what problem it is.

My customer is reporting that they now get the following error on their iPad when they try to do something with their database:

cocoa_error_19

Just in case you can’t read the text in the photo, it says:

The operation couldn’t be completed. (Cocoa error 19).

After some trouble getting the file (it is over 4 GB, not easy to e-mail), I saw a bunch of errors pop up in my debug console, including the dreaded “The database disk image is malformed”, which to me indicated that I needed to try and repair the database file. So I punched up my blog post from February of last year to try and run a repair on it.

Unfortunately, I ran into one dead end after another. I was able to dump the data out of the original database file, which produced a text file of over 8 GB. However, no matter what I tried to do to import this data back into a new database, I would end up with an empty new database.

On a lark, I decided to switch to Windows to try and fix the database file. After downloading the tools from the SQLite web site, Here is what I ended up with on my Windows computer:

C:\database>dir
 Volume in drive C is Windows7_OS
 Volume Serial Number is 50B0-39AA
 
 Directory of C:\database
 
03/14/2014  06:27 PM    <DIR>          .
03/14/2014  06:27 PM    <DIR>          ..
03/14/2014  06:16 PM     4,251,181,056 DB.sqlite
03/11/2014  11:33 AM           536,064 sqlite3.exe
03/11/2014  11:34 AM         1,388,032 sqlite3_analyzer.exe
               3 File(s)  4,253,105,152 bytes
               2 Dir(s)  240,466,235,392 bytes free

So I fired up a command prompt and tried to run some SQLite commands:

C:\database>sqlite3
SQLite version 3.8.4.1 2014-03-11 15:27:36
Enter ".help" for usage hints.
Connected to a transient in-memory database.
Use ".open FILENAME" to reopen on a persistent database.
sqlite> .open DB.sqlite
sqlite> .tables
.
.
Some table names listed here
.
.
sqlite> pragma integrity_check;
*** in database main ***
On tree page 1033353 cell 0: Failed to read ptrmap key=-280958431
On tree page 1033353 cell 0: 152 of 407 pages missing from overflow list starting at 1037333
Page 1037588 is never used
Page 1037589 is never used
.
.
You get the idea...
.
.
Page 1037684 is never used
Page 1037685 is never used

After going through the series of steps that I outlined in my message from last year, it appeared to process the 8 GB text file into a new database that was almost the same size as the original database file. Here was what my directory then looked like:

C:\database>dir
 Volume in drive C is Windows7_OS
 Volume Serial Number is 50B0-39AA
 
 Directory of C:\database
 
03/14/2014  06:45 PM    <DIR>          .
03/14/2014  06:45 PM    <DIR>          ..
03/14/2014  06:41 PM     8,428,761,778 dump_all.sql
03/14/2014  06:16 PM     4,251,181,056 DB.sqlite
03/14/2014  06:45 PM     4,239,932,416 DB2.sqlite
03/11/2014  11:33 AM           536,064 sqlite3.exe
03/11/2014  11:34 AM         1,388,032 sqlite3_analyzer.exe
               5 File(s) 16,921,799,346 bytes
               2 Dir(s)  227,795,791,872 bytes free

This had me feeling pretty good. Just to check, here is what I did next:

C:\database>sqlite3 DB2.sqlite
SQLite version 3.8.4.1 2014-03-11 15:27:36
Enter ".help" for usage hints.
sqlite> .tables
.
.
Some table names listed here
.
.
sqlite> select count(*) from table_name;
8716
sqlite> pragma integrity_check;
ok
sqlite> vacuum;
sqlite> .exit

It looks like success. I will have to take this data file and put it back on one of my test iPads when I get back into the office and try it out.

BTW, Happy Pi Day to everyone out there, whether you are a math person or not.

ADDENDUM: After putting the rebuilt SQLite database file back onto my own test iPad and simulator, it worked fine with no issues or cryptic error messages.

UIPopoverController arrow displays incorrectly on iOS 7

This one still doesn’t make sense to me, but I need to put it to bed and move on. When retooling an app for the latest iOS SDK, the UIPopoverController arrow displays incorrectly on iOS 7 in certain instances.

In the case where I need to display a popover controller as the result of the user tapping on a cell in a UITableView, this code has always worked fine in my iPad applications:

[thePopover presentPopoverFromRect:cell.frame inView:theTable permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];

However, after I switched over to using the iOS 7 SDK, the results look like this now:

popover_arrow_incorrect

After a bunch of investigations, I decided to try this just for the heck of it:

CGRect rect = CGRectMake(CGRectGetMaxX(cell.bounds) * 0.9, CGRectGetMidY(cell.bounds), 1.0, 1.0);
[thePopover presentPopoverFromRect:rect inView:cell permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];

With this code change, it now it looks like this:

popover_arrow_correct

And I am happy once again. Although I would still like to know why the original code does not work, if anyone has any ideas please feel free to comment. As you can see from the first image, the popover is positioned correctly (notice the vertical placement of the two line table view inside the popover, it is showing the same in both examples), it is just the arrow that is drawn incorrectly.

BTW, Happy Birthday to Tim Kazurinsky, who was great in his all-too-brief stint on Saturday Night Live, and utterly fantastic in the Police Academy series of films.

Extra space in grouped UITableView on iOS 7

So I noticed that there is a lot of extra space at the header and footer of my UITableView that is in my current project that I am updating to iOS 7. After some frustration, I finally put together this category that I hung off of UITableView:

- (void)ios7Check
{
    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0"))
    {
        self.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.bounds.size.width, 4.0f)];
        self.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.bounds.size.width, 4.0f)];
    }
}

Basically, all you have to do is call this from the viewDidLoad method of your view controller (or table view controller), and fire the ios7Check method like this:

[_theTableView ios7Check];  // if you have an instance variable pointing to your table view

or:

[self.tableView ios7Check];  // if your view controller is a UITableViewController

And you can adjust the spacing of the header and footer by changing the 4.0f values in the method above.

Here is what the grouped table view looks like without the code above, and with the code:

ios7-tableview-header-bigios7-tableview-header-small

EDIT: By the way, don’t try to set your tableHeaderView or tableFooterView frame to a height of 0.0f, as if you do then it just puts in the extra space. It must be that the Cocoa Touch framework sees that you have a zero height view, and just considers it as null. Even a height value of 0.1f is good enough, if you want a table view that cozies right up to the top with no space in between.

BTW, an anniversary farewell to Nelson Briles, who was a pitcher for the Pittsburgh Pirates (and other teams), and was a founding figure of the Pirates Fantasy Camp. Unfortunately he passed away on this day in 2005, so I did not get to meet him since my first Fantasy Camp was in 2011.

Determine which UITableViewCell contains a specified UIControl

If you have UITextField controls inside of a table view cell, and you are hooked into one of the UITextFieldDelegate methods, then you might need to determine which UITableViewCell contains a specified UIControl inside of a delegate method.

The wrong way

Up until now, I have always taken the shortcut of just walking back to the grandparent of the control by doing something like this:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    UITableViewCell *cell = (UITableViewCell *)textField.superview.superview;
 
    // do something here with the cell
 
    return YES;
}

However, when building and running under the iOS 7 SDK, this of course does not work any more.

The right way

After researching this phenomenon a bit more, I found a solution that does not rely on walking the view hierarchy, which by the way kids, is usually never a good idea. Here is a category that I built on top of UIView:

- (UITableViewCell *)findParentCellInTableView:(UITableView *)tableView
{
    UITableViewCell *cell = [self findParentUITableViewCell];
    return cell;
}
 
- (UITableViewCell *)findParentUITableViewCell
{
    if (self.superview && [self.superview isKindOfClass:[UITableViewCell class]])
    {
        return (UITableViewCell *)self.superview;
    }
 
    return [self.superview findParentUITableViewCell];
}

As a result, now my delegate call looks like this:

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    UITableViewCell *cell = [textField findParentCellInTableView:tableView];
 
    // do something here with the cell
 
    return YES;
}

Since I built this category off of UIView, it will work with most common items built on top of UIView or UIControl that you would put in a table view cell, such as UILabel, UITextField, UITextView, etc.

BTW, Happy Anniversary to The Beatles, who first visited the United States 50 years ago today.

EDIT: My first attempt to create the findParentCellInTableView method ended in disaster, as I forgot to take into account the fact that table view cells can scroll off the screen and possible get reused. As a result, I created a method that walks up the view chain more intelligently than simply going to the superview’s superview. As always, please let me know if you have any comments.

How to use a C# .NET interface to send messages between classes

I have used delegates in Objective-C to send message back and forth between classes for years. (And in fact, I did a blog post on Setting up an Objective-C delegate for the iPhone SDK a few years back on this very subject.) Indeed, delegates are a critical part of the Objective-C language, as it is usually good for objects to be able to let other objects know what is going on.

Well now, in my .NET development duties, I have a very similar situation. My code has a bunch of user controls that I use, and I need to have messages sent from one user control to another as the user works with the various pieces of the application.

Of course, in order to keep the compiler happy and get it working, you can do something quick and dirty like putting in an instance variable into the class that points back to your user control, and then when you need to let that user control know what is going on, just use the instance variable reference to call a method in that user control’s class.

But this is not scalable. If you have a bunch of different user controls calling a specific user control, you would have to put a reference to each different type of calling control, and then walk through them and determine which one you need to call in each case.

C# interface to the rescue. By using a C# interface, you can put an instance variable for your interface into your called class, which will then allow your calling class (which of course follows the interface) to have a method fired in it.

Here is a tutorial using C# for a console application that demonstrates the principles:

using System;
 
namespace ConsoleApplication1
{
    interface IMyClass  // 1
    {
        void PassMessage(string theMessage);
    }
 
    public class MyClass  // 2
    {
        private IMyClass parentClass;  // 3
 
        public void SetParentClass(object c)  // 4
        {
            parentClass = c as IMyClass;
        }
 
        public void Nudge()  // 5
        {
            parentClass.PassMessage("MyClass hath been nudged.");
        }
    }
 
    public class MainClass : IMyClass  // 6
    {
        public void DoStuff()  // 7
        {
            Console.WriteLine("About to DoStuff in MainClass");
            var c = new MyClass();
            c.SetParentClass(this);
            c.Nudge();
 
            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
 
        public void PassMessage(string theMessage)  // 8
        {
            Console.WriteLine("Message passed from MyClass: " + theMessage);
        }
    }
 
    public class Program
    {
        static void Main(string[] args)
        {
            var mainClass = new MainClass();
            mainClass.DoStuff();
        }
 
    }
}

So let’s break this down a bit. The numbers below correspond to the comments in the code above.

1. This is the interface definition. You need to put in here a listing of the methods that you want to be calling, sort of like an abstract class.

2. This is the class definition for the called class, or the class that needs to send a message back to the calling class.

3. Here is where the reference back to the calling class is kept. Since it’s type is an interface, any object that follows that interface can receive the caller’s message.

4. In this method, I am setting the reference back to the calling class. You can do this in the constructor as well if desired.

5. The Nudge method is a method in the called class that when executed, needs to send a message back to the calling class.

6. This is the class definition for the calling class. Notice that it follows the interface above, which requires that you provide the method specified in the interface.

7. This method creates the called class and sets up the interface reference, and then sends the Nudge message to the called class, which in turn calls back by firing the PassMessage method.

8. Here is where I do the processing necessary when the calling class is sending the message.

This is a pretty trivial example, but it should give you an idea on how to start setting up more complex cases.

BTW, Happy Birthday to John Myung, the fantastically talented bass player and founding member of Dream Theater. They are playing in a town near me this spring, but unfortunately I will be out of town and unable to see them. Great sadness.

Codemash 2014 recap

My second Codemash experience is in the books, and was a great conference. Thanks to Jim Holmes and his staff for all of their hard work and effort.

Mostly, I again attended mobile software development sessions, and this year’s lineup was solid. All of the presenters did very good jobs with their presentations.

My biggest disappointment this year was not being able to stay at the Kalahari Resort, which would have been optimal. As it was, I had to drive back and forth between the Kalahari and my hotel. Maybe next year I will just pony up and reserve the hotel before the conference just so that I can be guaranteed of getting a room there.

BTW, Happy Birthday to Andrea Martin, who was comedy genius on SCTV, and also played Moogie on Star Trek: Deep Space 9.

Don’t forget to account for new lines in your iOS NSRegularExpression

The NSRegularExpression class is handy for searching and parsing strings. That is, it is handy until it starts to fail at seemingly random intervals.

I had a regex that was working fine on my small set of initial test data, but when I expanded it to work on a slightly larger and varied set of data, all of a sudden the weather turned a bit cloudy.

After some investigation on Stack Overflow and diving through the Apple documentation, I realized that I should probably add the NSRegularExpressionDotMatchesLineSeparators option to my NSRegularExpression, and the skies turned bright and sunny again.

Here is an example of what I am talking about. In this instance, I am looking to obtain the text in an NSString called theString that is in between the sentinel literals of =BeginTag= and =EndTag=:

NSString *pattern = @"=BeginTag=(.*?)=EndTag=";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
    options:(NSRegularExpressionCaseInsensitive | NSRegularExpressionDotMatchesLineSeparators)
    error:nil];
[regex enumerateMatchesInString:theString options:0 range:NSMakeRange(0, [theString length])
    usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop)
    {
        NSString *s = [theString substringWithRange:[match rangeAtIndex:1]];
        NSLog(@"Enumerated matching string: %@", s);
    }];

If you leave off the NSRegularExpressionDotMatchesLineSeparators flag, and theString contains new line characters in between the sentinels, you end up with no text enumerated with the block.

BTW, Happy Birthday to Steven Spielberg, one of the true geniuses of our time.