Showing posts with label NSString. Show all posts
Showing posts with label NSString. Show all posts

Friday, August 5, 2011

Sending 'const NSString *' to parameter of type 'NSString *' discards qualifiers

This is a constant pointer to a NSString object, which btw is immutable by SDK. Pointer cannot be changed to point anywhere else. That was most likely the very reason why you're using const in the first place. This can be used in e.g. isEqualToString without compiler warning.

Monday, February 21, 2011

How to Find MFMailComposeViewController Email Addresses

One of the missing iOS APIs is a way to find out whom did user send email to. Otherwise MFMailComposeViewController is excellent: easy to setup, easy to launch, easy to use and easy to close. You just have no idea what user was doing with it!

I really needed to know who were email recipients. There are several good reasons for this and I just had one of those. So it was time to do some experimenting!

Sunday, January 16, 2011

How to Check if iOS Supports Class, Method or Keyword

iOS is getting fragmented. More devices to support with major iPhone hardware differences (0-2 cameras, no telephony - 3G - CDMA), screen resolutions (original, double, iPad) and especially more older operating system versions out in the wild.

To reach as many users as possible you have to check whether something exists before you try to use it. Customizing code based on iOS version number is possible, but there are other ways to do it.

Wednesday, December 22, 2010

Local Static Variable Lifetime Expectation in Objective-C

Something I learned today, worth remembering for performance reasons. Static variable defined inside a method is actually a global variable, which is visible only inside that method!

What this means is that you can increase your method performance by declaring variable only once and reuse it when needed next time.

Monday, December 20, 2010

How to Detect iOS Version in Code

Bumbed into a case where code crashed iOS 4.0.2, but worked with iOS 4.2. Since crash happened because of missing NSString *const, couldn't use respondsToSelector to choose, which code to run. Decided to simply check what is current iOS version:
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
if (version > 4.0)
{
    // iOS 4.2 specific code
}
else
{
    // iOS 4.0.2 specific code
}
Please note how three part version number gets converted to float:
NSString *s = [[UIDevice currentDevice] systemVersion];
float version = [[[UIDevice currentDevice] systemVersion] floatValue];
NSLog(@"Version: %@ and %f", s, version);
NSLog(@"Version: %@ and %f", @"3.1.3", [@"3.1.3" floatValue]);

Version: 4.0.2 and 4.000000
Version: 3.1.3 and 3.100000
I'm not really happy with the solution, but it works. Can live with that.

Update:

Always run code in real device! My development device iPhone4 with iOS 4.1 returns "4.1" as string, but that gives 4.0999999 as float value !!!

Friday, December 10, 2010

Where is iPhone Simulator NSTemporaryDirectory

Sometimes I need to save temporary files. The problem is cleaning up afterwards: application might crash during debug sessions leaving files, which are accessed on following launch thus messing up normal expected application behaviour.

iOS provides application specific temporary folder. The benefit in using this is that even if the worst case happens and your app fails to clean up temporary files for some reason (try to view 65 MB image, for example), application temporary folder is automatically cleaned out every 3 days. Your application is thus not able to leave behind "zombie" files, which would fill up device harddisk until all available space is used!

Thursday, November 11, 2010

How to Define UITableViewCell reuseIdentifier for loadNibNamed

When you create UITableViewCells, it's important to use reuseIdentified. This lets iOS recycle your table cells, thus improving performance and minimizing memory use. Using it is pretty simple:

static NSString *idCell = @"MyCellId";
cell = (UITableViewCell *)[aTableView dequeueReusableCellWithIdentifier:idCell];
Try to reuse an already existing, but not currently used, cell created earlier with given identifier "MyCellId". If such isn't found, create a new one:
if (cell == nil)
{
    static NSString *nibcell = @"MyCell";
    NSArray *nib = [[NSBundle mainBundle] loadNibNamed:nibCell owner:self options:nil];
    cell = (UITableViewCell *)[nib objectAtIndex:0];
}
This code requires a separate stand-alone XIB, which contains nothing but your UITableViewCell. But how do you define the reuseIdenfier? That property is read-only and created when table cell is created.
reuseIdentifier
A string used to identify a cell that is reusable. (read-only)
@property(nonatomic, readonly, copy) NSString *reuseIdentifier
Open your XIB in Interface Builder, select UITableViewCell object, open "Table View Cell Attributes" (press command-1) and write your hardcoded magical string "MyCellId" into "Identifier" field. Use the same string in your code as reuseIdentifier.

Warning: you should NEVER access objects inside XIB (NIB) by magical index into array! Apple might change "something" in next Xcode release and thus break your code. You should use IBOutlets. You have been warned.

...yes, this is one of those sad "don't do as I do, but as I tell you to" cases...

Tuesday, August 24, 2010

How to Show Text Left and Right in UIWebView

When you need to show text on same line at left and right in UIWebView, this is one way:
NSString *myHtml = [NSString stringWithFormat:
    @"<html><body>"
    "<span style='float:left'>%@</span>"
    "<span style='float:right'>%@</span>"
    @"</body></html>",
    @"I'm left", @"I'm right"];
   
[self.cellWebView loadHTMLString:myHtml baseURL:nil];
Can't use div, since it seems to force a linebreak by default.

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.
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?

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];

Monday, March 22, 2010

Property 'username' attribute in 'ConnectApi' class continuation does not match 'ConnectApi' class property

Want to declare external API as readonly, while internal has to be writable. Done this before, but right now something doesn't work.

Turned out that the reason is missmatch in unwritten default values. The property types must match in both external and internal declaration, including the non-written default values. This is the correct version:
@interface ConnectApi : NSObject
{
    NSString *username;
}
@property (nonatomic, copy, readonly) NSString *username;
...
@interface ConnectApi ()
@property (nonatomic, copy, readwrite) NSString *username;

Thursday, February 25, 2010

How to Disable UIWebView Selection

You could do this by running a short javaScript line at webViewDidFinishLoad, but I find this more elegant: define UIWebView properties in CSS.
NSString *myHtml = [NSString stringWithFormat:
   @"<html><head>"
   "<style type=\"text/css\">"
   // Disable Open/Copy/Cancel alert with long link selection
   "* {"
   "-webkit-touch-callout: none;"
   // Disable selection/Copy of UIWebView
   "-webkit-user-select: none;"
   "}"
   ",</style>"
   "</head><body>%@</body></html>", message.body];
[myWebView loadHTMLString:myHtml baseURL:nil];
As a bonus I left there also how to disable link selection popup.

Wednesday, February 10, 2010

How to Make UIWebView Open target="_blank" Links

There are several ways to do this, here's mine.
NSString *js = @"\
var a = document.getElementsByTagName('a');\
for (var i=0; i<a.length; i++) {\
    a[i].removeAttribute('target');\
}\
";
[self.myWebView stringByEvaluatingJavaScriptFromString:js];
Possible advantage: reduces size of HTML document.

How to Put a Smiley Into Your UILabel

Sometimes iPhone SDK just makes you smile, things you expect to be difficult turn out to be really simple. Take for example a smiley face :)
NSRange range = {NSNotFound, 0};
NSString *s = @"This is a smiley :) face";

range.location = 0;
range.length = [s length];
s = [s stringByReplacingOccurrencesOfString:@":)"
withString:@"\ue415"
options:NSCaseInsensitiveSearch
range:range];

iPhone contains by default a Japanese font, which supports unicode emoji characters. As a result you suddenly have built-in supports for about 460 graphical icons, all of which you can put anywhere as part of any text string!

Here's full list of emoji characters in iPhone. Have fun ;)