Quickies

[categories] [index] [all (418)] [latest]

Cocoa Foundation
  1. Print some information about a block with the private function:

    char *_Block_dump (block_t block);
    

    sample output:

    ^0xbfffd53c (new layout) =
    isa: stack Block
    flags: HASHELP
    refcount: 0
    invoke: 0x4f85
    descriptor: 0x7ed0
    descriptor->reserved: 0
    descriptor->size: 32
    descriptor->copy helper: 0x4f1d
    descriptor->dispose helper: 0x4ed3
    
  2. static MyClass *sharedInstance = nil;
    
    + (MyClass)sharedInstance {
    
        if (sharedInstance == nil) {
            sharedInstance = [[self alloc] init];
        }
    
        return sharedInstance;
    }
    
  3. NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
    
    [queue addOperationWithBlock:^{
        CGFloat n = [self resultOfSomeMassiveComputation];
    
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            [self updateOnMainThreadWithResult:n];
        }];
    }];
    
  4. // MyClass.h
    extern NSString * const kMyString;
    
    // MyClass.m
    NSString * const kMyString = @"xxx";
    
  5. #ifdef DEBUG
    #define MyLog(fmt, ...) NSLog((@"%@ [Line %d] %s " fmt), [self class], __LINE__, __FUNCTION__, ##__VA_ARGS__);
    #define MyLogError(fmt, ...) NSLog((@"[Error] %@ [Line %d] %s " fmt), [self class], __LINE__, __FUNCTION__, ##__VA_ARGS__);
    #else
    #define MyLog(fmt, ...)
    #define MyLogError(fmt, ...) NSLog((@"[Error] %@ [Line %d] %s " fmt), [self class], __LINE__, __FUNCTION__, ##__VA_ARGS__);
    #endif
    

    but also:

    NSLog(@"-[%@ %s]", isa, SELNAME(_cmd));
    

    -[NSKVONotifying_AppDelegate awakeFromNib]

  6. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_current_queue(), ^{
        NSLog(@"--");
    });
    
  7. $ OBJC_PRINT_IMAGES=YES /Library/XcodeBuilds/Debug/HelloWorld 
    objc[39331]: IMAGES: processing 28 newly-mapped images...
    
    objc[39331]: IMAGES: loading image for /usr/lib/libobjc.A.dylib (supports GC)
    
    objc[39331]: IMAGES: loading image for /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (supports GC)
    
    objc[39331]: IMAGES: loading image for /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (supports GC)
    
    objc[39331]: IMAGES: loading image for /Library/XcodeBuilds/Debug/HelloWorld
    
  8. /Developer/Extras/64BitConversion/ConvertCocoa64 MyClass.m
    
  9. http://www.fscript.org/

    > NSApplication sharedApplication delegate managedObjectContext inspectWithSystem:sys
    

  10. - (NSString *)stringWithoutComments:(NSString *)string {
        NSArray *inputLines = [string componentsSeparatedByString:@"\n"];
        NSPredicate *commentsPredicate = [NSPredicate predicateWithFormat: @"SELF beginswith %@", @"--"];
        NSPredicate *notCommentsPredicate = [NSCompoundPredicate notPredicateWithSubpredicate:commentsPredicate];
        NSArray *filteredLines = [inputLines filteredArrayUsingPredicate:notCommentsPredicate];
        return [filteredLines componentsJoinedByString:@"\n"];
    }
    
  11. NSString *formattedDate = [[NSDate date] descriptionWithCalendarFormat:@"%Y-%m-%d %H:%M:%S"];
    

    2006-11-15 00:26:11

  12. [NSThread currentThread]
    
  13. +[NSThread callStackSymbols]
    
  14. NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleShortVersionString"];
    
  15. NSString *desktop = [NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) objectAtIndex:0];
    
  16. Cache the implementation pointer for -[NSString hasPrefix:]

    SEL hasPrefixSelector = @selector(hasPrefix:);
    BOOL (*hasPrefixIMP) (id, SEL, id) = (BOOL (*) (id, SEL, id))[@"" methodForSelector:hasPrefixSelector];
    

    Use the cached pointer instead of sending the message

    BOOL b = hasPrefixIMP (@"Europe", hasPrefixSelector, @"e");
    
  17. Set values for keys from a dictionary:

    [person setValuesForKeysWithDictionary:d];
    

    Don't raise exceptions when class is not key value coding-compliant for given keys:

    - (void)setValue:(id)value forUndefinedKey:(NSString *)key {
        NSLog(@"-- unhandled key:%@", key);
    }
    
  18. NSDate *startDate = [NSDate date];
    // ...
    NSLog(@"%f seconds elapsed", [[NSDate date] timeIntervalSinceDate:startDate]);
    
  19. void Swizzle(Class class, SEL origSel, SEL newSel) {
        Method origMethod = class_getInstanceMethod(class, origSel);
        Method newMethod = class_getInstanceMethod(class, newSel);
    
        if(class_addMethod(class, origSel, method_getImplementation(newMethod), method_getTypeEncoding(newMethod))) {
            class_replaceMethod(class, newSel, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
        } else {
            method_exchangeImplementations(origMethod, newMethod);
        }
    }
    

    from Mike Ash

    static IMP original_initWithString_;
    
    @implementation NSURL (Ext)
    
    + (void)swizzleMethods { // call this once, early
        original_initWithString_ = method_getImplementation(class_getInstanceMethod([self class], @selector(initWithString:)));
        Swizzle([self class], @selector(initWithString:), @selector(my_initWithString:));
    }
    
    // -[NSURL urlWithString:] will now execute this method
    - (NSURL *)my_initWithString:(NSString *)s {
        NSLog(@"-- my_initWithString: %@", s);
        return original_initWithString_(self, @selector(initWithString:), s);
    }
    
    @end
    
  20. #import <Foundation/Foundation.h>
    
    // gcc -g -Wall -framework Foundation -o nslog nslog.m
    
    int main (void) {
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
        NSLog(@"Hello");
        [pool release];
        return (0);
    }
    
  21. NSArray *addresses = [[NSHost currentHost] addresses];
    NSString *hostName = [[NSProcessInfo processInfo] hostName];
    
  22. NSUInteger dayOfYear = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit
                                                                   inUnit:NSYearCalendarUnit
                                                                  forDate:[NSDate date]];
    
  23. NSProcessInfo *pi = [NSProcessInfo processInfo];
    
    NSLog(@"environment SHELL: %@", [[pi environment] objectForKey:@"SHELL"]);
    NSLog(@"globallyUniqueString: %@", [pi globallyUniqueString]);
    NSLog(@"hostName: %@", [pi hostName]);
    NSLog(@"processIdentifier: %d", [pi processIdentifier]);
    NSLog(@"processName: %@", [pi processName]);
    [pi setProcessName:@"MyProcessNewName"];
    NSLog(@"processName: %@", [pi processName]);
    NSLog(@"operatingSystem: %d", [pi operatingSystem]);
    NSLog(@"operatingSystemName: %@", [pi operatingSystemName]);
    NSLog(@"operatingSystemVersionString: %@", [pi operatingSystemVersionString]);
    NSLog(@"processorCount: %d", [pi processorCount]);
    NSLog(@"activeProcessorCount: %d", [pi activeProcessorCount]);
    NSLog(@"physicalMemory: %qu", [pi physicalMemory]);
    NSLog(@"args: %@", [pi arguments]);
    

    Output:

    environment SHELL: /bin/bash
    globallyUniqueString: F68E72F1-257C-4E93-B23D-BA3A0DD15603-47346-0001600092C640D8
    hostName: nst.local
    processIdentifier: 47346
    processName: Untitled
    processName: MyProcessNewName
    operatingSystem: 5
    operatingSystemName: NSMACHOperatingSystem
    operatingSystemVersionString: Version 10.5.4 (Build 9E17)
    processorCount: 2
    activeProcessorCount: 2
    physicalMemory: 2147483648
    args: (
        "/Library/XCodeBuilds/Debug/Untitled"
    )
    
  24. Show help

    $ export OBJC_HELP=YES
    
    $ /Applications/TextEdit.app/Contents/MacOS/TextEdit
    (...)
    OBJC_HELP: describe available environment variables
    OBJC_PRINT_IMAGES: log image and library names as they are loaded
    OBJC_PRINT_LOAD_METHODS: log calls to class and category +load methods
    OBJC_PRINT_INITIALIZE_METHODS: log calls to class +initialize methods
    OBJC_PRINT_RESOLVED_METHODS: log methods created by +resolveClassMethod: and +resolveInstanceMethod:
    

    Log Objective-C messages

    $ export NSObjCMessageLoggingEnabled=YES
    
    $ /Applications/TextEdit.app/Contents/MacOS/TextEdit
    
    $ tail -f /tmp/msgSends-<pid>
    - NSLock NSLock lock
    + NSThread NSThread currentThread
    - NSThread NSObject hash
    - NSCFArray NSCFArray countByEnumeratingWithState:objects:count:
    - NSLock NSLock unlock
    - NSLock NSLock lock
    + NSThread NSThread currentThread
    - NSThread NSObject hash
    - NSCFArray NSCFArray countByEnumeratingWithState:objects:count:
    - NSLock NSLock unlock
    
  25. NSDictionary *errors;
    NSAppleScript *quitApp;
    
    quitApp = [[NSAppleScript alloc] initWithSource:@"tell application \"AnotherApplication\" to quit"];
    [quitApp executeAndReturnError:&errors];
    [quitApp release];
    
    if(errors != nil) {
       // manage error
    }
    
  26. NSString *s = @"Hello World!";
    NSString *re = @".*l{2}.*";
    NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", re];
    
    NSLog(@"Match: %d", [p evaluateWithObject:s]);
    
  27. Two methods to be added to a NSString category:

    -[NSString captureRegex:]

    - (NSString *)captureRegex:(NSString *)pattern {
    
        NSError *error = nil;
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionDotMatchesLineSeparators error:&error];
        if(regex == nil) {
            NSLog(@"-- %@", error);
            return nil;
        }
    
        NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:self options:0 range:NSMakeRange(0, [self length])];
        if(rangeOfFirstMatch.location == NSNotFound) return nil;
    
        return [self substringWithRange:rangeOfFirstMatch];
    }
    

    -[NSString matchRegex:]

    - (BOOL)matchRegex:(NSString *)pattern {    
    
        NSError *error = nil;
        NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:&error];
        if(regex == nil) {
            NSLog(@"-- %@", error);
            return NO;
        }
    
        NSUInteger n = [regex numberOfMatchesInString:self options:0 range:NSMakeRange(0, [self length])];
        return n == 1;
    }
    
  28. http://regexkit.sourceforge.net/RegexKitLite/

    #import "RegexKitLite.h"
    

    -[NSString captureRegex:]

    - (NSString *)captureRegex:(NSString *)regex {
        NSRange searchRange = NSMakeRange(0, [self length]);
        NSError *error = nil;
        NSRange matchedRange = [self rangeOfRegex:regex options:(RKLMultiline|RKLDotAll) inRange:searchRange capture:1 error:&error];
        if(error) SQLogError(@"-- error: %@", error);
    
        NSString *result = nil;
        if( (matchedRange.location + matchedRange.length) <= [self length] ) {
            result = [self substringWithRange:matchedRange];
        }
    
        return result;
    }
    

    -[NSString matchRegex:]

    - (BOOL)matchRegex:(NSString *)regex {
        NSArray *matches = [self componentsMatchedByRegex:regex];
        return [matches count] == 1;
    }
    
  29. #import <Foundation/Foundation.h>
    
    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    
        NSFileManager *fileManager = [NSFileManager defaultManager];
    
        CFUUIDRef uuid = CFUUIDCreate(NULL);
        NSString *uniqueString = (NSString *)CFUUIDCreateString(NULL, uuid);
        CFRelease(uuid);
    
        NSString *tempFile = [NSString pathWithComponents:
            [NSArray arrayWithObjects: NSTemporaryDirectory(), uniqueString, nil]];
        [fileManager createFileAtPath:tempFile contents:nil attributes:nil];
        NSFileHandle *file = [NSFileHandle fileHandleForWritingAtPath:tempFile];
    
        NSTask *task = [[NSTask alloc] init];
        [task setLaunchPath:@"/usr/bin/perl"];
        [task setArguments:
            [NSArray arrayWithObjects:@"/Users/nst/bin/iso2txt",
                                      @"/Users/nst/Desktop/asd.iso2709",
                                      nil]];
        [task setStandardOutput:file];
        [task launch];
        [task waitUntilExit];
        [task release];
    
        NSLog([NSString stringWithContentsOfFile:tempFile]);
    
        [fileManager removeFileAtPath:tempFile handler:nil];
    
        [pool release];
        return 0;
    }
    
  30. #include <Foundation/NSDebug.h>
    
    [NSAutoreleasePool showPools];
    

    the following function performs the same action:

    _CFAutoreleasePoolPrintPools();
    

    output:

    - -- ---- -------- Autorelease Pools -------- ---- -- -
    ==== top of stack ================
      0x583f3c0 (__NSDate)
      0x583f350 (Measure)
      0x5a24960 (UIWindow) (...)
    ==== top of pool, 23 objects ================
    ==== top of pool, 0 objects ================
    ==== top of pool, 0 objects ================
    - -- ---- -------- ----------------- -------- ---- -- -
    
  31. [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
    
  32. When encountering the error message

    "Variable is not assignable (missing __block type specifier)"
    

    consider actually using the __block type specifier, so that the variable always live in the scope of the blocks declared within the variable lexical scope, and also in the copies of these blocks. It also means that the address of the variable may change over time. See Blocks Programming Topics for more.

    + (NSString *)myMethodWithDictionary:(NSDictionary *)d {
    
        __block NSString *s = nil; // s lives in block storage
    
        [d enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {    
            if( /* condition here */ ) {
                *stop = YES;
                s = @"xxx";
            }
        }];
    
        return s;
    }
    
  33. Thread safe code to be run only once with all other thread waiting at the barrier:

    static dispatch_once_t onceToken;
    
    dispatch_once (&onceToken, ^{
        // ...    
    });
    
  34. $ NSObjCMessageLoggingEnabled=YES /Library/XcodeBuilds/Debug/HelloWorld 
    2009-02-04 10:54:41.728 HelloWorld[39133:10b] Hello, World!
    
    $ cat /tmp/msgSends-39133 
    + NSRecursiveLock NSObject initialize
    + NSRecursiveLock NSObject new
    + NSRecursiveLock NSObject alloc
    ...
    

    Tracing can be activated selectively in code:

    #import <objc/runtime.h>
    
    instrumentObjcMessageSends(YES);
    // messages will be traced here
    instrumentObjcMessageSends(NO);
    
  35. http://en.wikipedia.org/wiki/Universally_Unique_Identifier

    + (NSString *)randomString {
        CFUUIDRef cfuuid = CFUUIDCreate (kCFAllocatorDefault);
        NSString *uuid = (NSString *)CFUUIDCreateString (kCFAllocatorDefault, cfuuid);
        CFRelease (cfuuid);
        return [uuid autorelease];
    }
    

    CFC4B6BA-26C9-4149-89C1-77C2C4865A72

    See also $ uuidgen

  36. dump the headers

    $ class-dump /System/Library/Frameworks/InstantMessage.framework/Versions/A/InstantMessage > InstantMessage.h
    

    add the framework and the headers to the project

    #import "InstantMessage.h"
    

    class-dump

  37. SInt32 MacVersion = 0;
    BOOL isRunningSnowLeopard = NO;
    
    if (Gestalt(gestaltSystemVersionMinor, &MacVersion) == noErr) {
        isRunningSnowLeopard = (MacVersion == 6);
    }
    
    NSLog(@"isRunningSnowLeopard %d", isRunningSnowLeopard);