Friday, January 31, 2014

Sorting NSNumbers in a NSArray using sortedArrayUsingComparator block

An efficient method to sort an array is to employ the sortedArrayUsingComparator method for NSArray.

NSArray *myArray = @[@20, @30, @10];
    
NSArray *mySortedArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
     if ([obj1 intValue] > [obj2 intValue])
         return NSOrderedDescending;
     else if ([obj1 intValue] < [obj2 intValue])
         return NSOrderedAscending;
     return NSOrderedSame;
}];
    
NSLog(@"%i",[[mySortedArray objectAtIndex:0] intValue]);
NSLog(@"%i",[[mySortedArray objectAtIndex:1] intValue]);
NSLog(@"%i",[[mySortedArray objectAtIndex:2] intValue]); 
An array of integer literals is created and sorted by calling sortedArrayUsingComparator which accepts a NSComparator block. Objects are compared to one another to sort them in an ascending order and the NSLogs return the values 10, 20 and 30. To sort in a descending order, reverse the ascending and descending statements.

NSArray *myArray = @[@20, @30, @10];
    
NSArray *mySortedArray = [myArray sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
     if ([obj1 intValue] > [obj2 intValue])
         return NSOrderedAscending;
     else if ([obj1 intValue] < [obj2 intValue])
         return NSOrderedDescending;
     return NSOrderedSame;
}];
    
NSLog(@"%i",[[mySortedArray objectAtIndex:0] intValue]);
NSLog(@"%i",[[mySortedArray objectAtIndex:1] intValue]);
NSLog(@"%i",[[mySortedArray objectAtIndex:2] intValue]);

Now the logs show 30, 20 and 10.

Wednesday, January 29, 2014

Placeholder in UITextView

UITextField has a placeholder property but one doesn't exist in UITextView. However, it is possible to overcome this limitation with usage of the UIViewDelegate.
#import 
@interface MyViewController : UIViewController <UITextViewDelegate>
@end
Declare a UITextView property in the class continuation category. Set up the text view, the delegate and add the placeholder text default text for the placeholder.
static NSString *const kPlaceholderText = @"Placeholder";

@interface MyViewController ()
@property (nonatomic, retain) UITextView *myTextView;
@end

UITextView *textViewTemp = [[UITextView alloc] initWithFrame:CGRectMake(10, 80, 300, 115)];
self.myTextView = textViewTemp;
[self.myTextView setDelegate:self];
[self.myTextView setText:kPlaceholderText];
[self.myTextView setTextColor:[UIColor colorWithRed:200/256.0 green:200/256.0 blue:200/256.0 alpha:1.0]];
Now implement the UITextView delegate methods.
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
    if ([self.myTextView.textColor isEqual:[UIColor colorWithRed:200/256.0 green:200/256.0 blue:200/256.0 alpha:1.0]] ){
        self.myTextView.text = @"";
        self.myTextView.textColor = [UIColor blackColor];
    }
    return YES;
}

- (BOOL)textViewShouldEndEditing:(UITextView *)textView
{
    if(self.myTextView.text.length == 0){
        self.myTextView.textColor = [UIColor colorWithRed:200/256.0 green:200/256.0 blue:200/256.0 alpha:1.0];
        self.myTextView.text = kPlaceholderText;
        [self.myTextView resignFirstResponder];
    }
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView
{
    if(self.myTextView.text.length == 0){
        self.myTextView.textColor = [UIColor colorWithRed:200/256.0 green:200/256.0 blue:200/256.0 alpha:1.0];
        self.myTextView.text = kPlaceholderText;
        [self.myTextView resignFirstResponder];
    }
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if([text isEqualToString:@"\n"]) {
        [myTextView resignFirstResponder];
        return NO;
    }
    return YES;
}
textViewShouldBeginEditing looks to see if the existing text is the color of the placeholder text and if so clears out the placeholder text and sets the correct color for the regular text. textViewShouldEndEditing and textViewDidChange checks to see if the text view is empty and sets the placeholder text and color. Finally, shouldChangeTextInRange checks if the user selects return. Implementing the UITextView delegate methods mimics the placeholder behavior of UITextField.

Friday, January 24, 2014

Optional Protocol Methods

Methods in protocols are required by default but can be set to optional using the @optional directive. Here's how to implement optional delegates:

@protocol myProtocol

//@required
-(NSString *)requiredMethod:(MyCustomObject *)myObject;

@optional
-(NSString  *)optionalMethod:(MyCustomObject *)myObject;
@end  
respondsToSelector can be used to see if the optional method exists and if so, react to it.
@interface myClass : aSuperClass 
...
if ([self.delegate respondsToSelector:@selector(optionalMethod:)]) {
   myString = [self.delegate optionalMethod:self];
} else {
   myString = @"Default Value";           
}