Caleb Madrigal

Programming, Hacking, Math, and Art

 

NSArray+FP

I realized that I utilize the [NSArray head] and [NSArray tail] functions in various code snippets, but haven.t shared the actual code for that category. So here is my NSArray+FPcode.

NSArray+FP.h

#import <Foundation/Foundation.h>
typedef id(^MapBlock)(id);
@interface NSArray (FP)
- (NSArray *)map:(MapBlock)block;
- (id)head;
- (NSArray *)tail;
@end

NSArray+FP.m

#import "NSArray+FP.h"
@implementation NSArray (FP)

- (NSArray *)map:(MapBlock)block {
    NSMutableArray *resultArray = [[NSMutableArray alloc] init];
    for (id object in self) {
        [resultArray addObject:block(object)];
    }
    return resultArray;
}

- (id)head
{
    return [self objectAtIndex:0];
}

- (NSArray *)tail
{
    NSRange tailRange;
    tailRange.location = 1;
    tailRange.length = [self count] - 1;
    return [self subarrayWithRange:tailRange];
}

@end

Functional programming to deal with asynchronicity in Objective-C

In the last few weeks, I've used the [ALAssetsLibrary loadImages:callback:] method to load a list of images. For what I was doing, I wanted to wait till all the images were loaded before proceeding. I found that I could solve this problem very elegantly using a recursive solution:

- (void)loadImages:(NSArray *)imageUrls loadedImages:(NSArray *)loadedImages 
                                        callback:(void(^)(NSArray *))callback
{
    if (imageUrls == nil || [imageUrls count] == 0) {
        callback(loadedImages);
    }
    else {
        NSURL *head = [imageUrls head];
        __unsafe_unretained id unretained_self = self;        
        ALAssetsLibrary* library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:head resultBlock:^(ALAsset *asset) {
            ALAssetRepresentation *assetRepresentation = asset.defaultRepresentation;

            UIImage *image = [UIImage imageWithCGImage:assetRepresentation.fullResolutionImage 
                              scale:assetRepresentation.scale
                              orientation:(UIImageOrientation)assetRepresentation.orientation];

            [unretained_self loadImages:[imageUrls tail] loadedImages:[loadedImages 
                arrayByAddingObject:image] callback:callback];
        } failureBlock:^(NSError *error) {
            [unretained_self loadImages:[imageUrls tail] loadedImages:loadedImages callback:callback];
        }];
    }
}

In ...

How to reference self in a block in Objective-C

When using ARC (automatic reference counting) in Objective-C, you need to be careful to avoid causing retain cycles. One place where a retain cycle can occur is where self is referenced in a block. To avoid a retain cycle, you can use the __unsafe_unretained modifier as such:

__unsafe_unretained id unretained_self = self;
reachability = [Reachability reachabilityWithHostname:@"maps.google.com"];
reachability.reachableBlock = ^(Reachability *r) {
    dispatch_async(dispatch_get_main_queue(), ^{
        SurveyFormController *myself = unretained_self;
        self.mapView.reachable = YES;
        [myself configureView];
    });
};

String to Base64 String in Objective-C

Today, I needed to convert an ASCII-encoded NSString to a base64 NSString. I found a number of methods that convert from an NSString to a Base64 NSData, or from NSData to a Base64 string, but couldn't find one that did exactly what I needed. So here is a method that simply converts an NSString to a Base64 NSString:

+ (NSString *)base64String:(NSString *)str
{
    NSData *theData = [str dataUsingEncoding: NSASCIIStringEncoding];
    const uint8_t* input = (const uint8_t*)[theData bytes];
    NSInteger length = [theData length];

    static char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    NSMutableData* data = [NSMutableData dataWithLength:((length + 2) / 3) * 4];
    uint8_t* output = (uint8_t*)data.mutableBytes;

    NSInteger i;
    for (i=0; i < length; i += 3) {
        NSInteger value = 0;
        NSInteger j;
        for (j = i; j < (i + 3); j++) {
            value <<= 8;

            if (j < length) {
                value |= (0xFF & input[j]);
            }
        }

        NSInteger theIndex ...

Map in Objective-C

Today, I was faced with an issue several times where I had an array of items of one type, and had to convert this into an array of items of a different type. This made me really want a map() function. So I added one to NSArray like so:

NSArray+FP.h

#import <Foundation/Foundation.h>
typedef id(^MapBlock)(id);
@interface NSArray (FP)
- (NSArray *)map:(MapBlock)block;
@end

NSArray+FP.m

#import "NSArray+FP.h"
@implementation NSArray (FP)
- (NSArray *)map:(MapBlock)block {
    NSMutableArray *resultArray = [[NSMutableArray alloc] init];
    for (id object in self) {
        [resultArray addObject:block(object)];
    }
    return resultArray;
}
@end

So now, I can do this!

NSArray *strArray = [NSArray arrayWithObjects:@"1",@"1",@"2",@"3",@"5",@"8",nil];
NSArray *numArray = [strArray map:^id(id object) {
    NSString *str = object;
    return [NSNumber ...

How to place custom image in UITextField in iOS

Here is how to put an image in the right portion of a UITextField:

UITextField *textField = [[UITextField alloc] initWithFrame:CGRectMake(55, 10, 660, 30)];
textField.rightViewMode = UITextFieldViewModeWhileEditing;

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 15, 15)];
imageView.image = [UIImage imageNamed:@"invalidFieldCircle"];
textField.rightView = imageView;

This also assumes that an image called "invalidFieldCircle.png" is in your project's "Resources" directory, which should be located just below the main project directory (you may have to create it).

Force weak reference in Objective-C

Today, I was trying to add an object to an NSDictionary and force it to be a weak reference. This can be done with the [NSValue valueWithNonretainedObject] call:

NSValue *weakRef = [NSValue valueWithNonretainedObject:loadDelegate];
NSDictionary *userInfo = [[NSDictionary alloc] initWithObjectsAndKeys:weakRef, @"loadDelegate", nil];