| NSAlert (4) | NSString (1) | NSTableView (4) |
| NSTask (1) | NSThread (3) | NSValueTransformer (1) |
[NSCursor hide];
[NSCursor unhide];
[NSCursor setHiddenUntilMouseMoves:YES];
NSString *formattedDate = [[NSDate date] descriptionWithCalendarFormat:@"%Y-%m-%d %H:%M:%S"];
2006-11-15 00:26:11
- (IBAction)openPrefsSheet:(id)sender {
[NSApp beginSheet:prefsWindow
modalForWindow:mainWindow
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
[NSApp runModalForWindow:prefsWindow];
[NSApp endSheet:prefsWindow];
[prefsWindow orderOut:self];
}
- (IBAction)closePrefsSheet:(id)sender {
[NSApp stopModal];
}
La classe à archiver doit implémenter le protocole NSCoding
@interface Cat : NSObject < NSCoding > {
...
}
@end
et ses méthodes :
@implementation Cat
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:name forKey:@"Name"];
[encoder encodeObject:dob forKey:@"BirthDate"];
}
- (id)initWithCoder:(NSCoder *)decoder {
// returned values are autoreleased
[self setName: [decoder decodeObjectForKey:@"Name"]];
[self setDob: [decoder decodeObjectForKey:@"BirthDate"]];
return self;
}
@end
L'appellant peut alors archiver et désarchiver :
// archive
[NSKeyedArchiver archiveRootObject:cw toFile:@"/tmp/cArchive"];
// unarchive
Cat *cr = [NSKeyedUnarchiver unarchiveObjectWithFile:@"/tmp/cArchive"];
NSString *s = @"Hello World!";
NSString *re = @".*l{2}.*";
NSPredicate *p = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", re];
NSLog(@"Match: %d", [p evaluateWithObject:s]);
NSDate *date = [NSDate date];
NSCalendarDate *calendarDate = [date dateWithCalendarFormat:nil timeZone:[NSTimeZone defaultTimeZone]];
Créer une classe MyException héritant de NSException, puis :
@try {
NSException *e = [MyException exceptionWithName: @"MyError"
reason: @"I threw this Exception"
userInfo: nil];
@throw e;
} @catch (MyException *e) {
NSLog(@"Exception name : %@", [e name]);
NSLog(@"Exception reason : %@", [e reason]);
}
En Objective-C, la tradition est plutôt au valeurs de retour comme nil, NULL, NO ou aux codes d'erreur.
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleName"]
[[NSProcessInfo processInfo] processName]
NSImage *image = [[NSWorkspace sharedWorkspace] iconForFileType:NSFileTypeForHFSTypeCode(kAlertNoteIcon)];
$ 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
/Developer/Extras/64BitConversion/ConvertCocoa64 MyClass.m
for (NSEntityDescription *entity in [self managedObjectModel]) {
NSLog(@"entity %@", entity.name);
}
Exemple : supprimer les lignes commençant par "--" :
-(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"];
}
[NSImage imageNamed:NSImageNameComputer]
NSString *desktop = [NSSearchPathForDirectoriesInDomains(NSDesktopDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"CFBundleShortVersionString"];
Lots of useful info, thanks to NSProcessInfo.
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"
)
Pareil qu'en C.
int i;
int count;
count = [array count];
for (i = 0; i < count; i++) {
NSLog(@"%@", [array objectAtIndex:i]);
}
Avec un énumérateur.
NSEnumerator *enumerator;
enumerator = [array objectEnumerator];
NSObject *obj;
while (obj = [enumerator nextObject]) {
NSLog(@"%@", obj);
}
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
BOOL appDidLaunch = [ws launchApplication:@"BluePhoneElite"];
Ici dans le cas d'un tableau.
NSBundle *bundle;
NSString *path;
NSArray *usefulData;
bundle = [NSBundle mainBundle];
path = [bundle pathForResource:@"userfulData"
ofType:@"plist"];
usefulData = [[NSArray alloc] initWithContentsOfFile:path];
NSDate *startDate = [NSDate date];
//...
NSLog(@"took %f seconds", [[NSDate date] timeIntervalSinceDate:startDate]);
+ singleton {
static Singleton *instance = nil;
if (instance == nil) {
instance = [[self alloc] init];
}
return instance;
}
NSArray *addresses = [[NSHost currentHost] addresses];
NSString *hostName = [[NSProcessInfo processInfo] hostName];
float dpi = ([image pixelsWide] / [image size].width) * 72.0);
NSWorkspace * ws = [NSWorkspace sharedWorkspace];
NSArray *runningApps = [ws valueForKeyPath:@"launchedApplications.NSApplicationName"];
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:myURLString]];
NSLog(@"%s:%d", __PRETTY_FUNCTION__, __LINE__);
+[AppDelegate initialize]:23
Thank you Stéphane.
NSLog(@"-[%@ %s]", isa, SELNAME(_cmd));
-[NSKVONotifying_AppDelegate awakeFromNib]
NSLog(@"line %d", __LINE__);
La source de données d'un NSTableView doit implémenter les méthodes suivantes :
Retourner le nombre de lignes :
- (int)numberOfRowsInTableView: (NSTableView *)aTableView
Retourner le contenu d'une cellule :
- (id) tableView: (NSTableView *)aTableView
objectValueForTableColumn: (NSTableColumn *)aTableColumn
row: (int)rowIndex
Modifier le contenu d'une cellule (optionnel)
- (void) tableView: (NSTableView *)aTableView
setObjectValue: (id)anObject
forTableColumn: (NSTableColumn *)aTableColumn
row: (int)rowIndex
NSDictionary *errors;
NSAppleScript *quitBPE;
quitBPE = [[NSAppleScript alloc] initWithSource:@"tell application \"BluePhoneElite\" to quit"];
[quitBPE executeAndReturnError:&errors];
[quitBPE release];
if(errors != nil) {
// manage error
}
+ (void)initialize{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:@"NO", @"disableRulerAntiAliasing",
@"YES", @"disableTracksAntiAliasing", nil];
[defaults registerDefaults:appDefaults];
}
if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_0) {
/* On a 10.0.x or earlier system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_1) {
/* On a 10.1 - 10.1.x system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_2) {
/* On a 10.2 - 10.2.x system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_3) {
/* On a 10.3 - 10.3.x system */
} else if (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_4) {
/* On a 10.4 - 10.4.x system */
} else {
/* Leopard or later system */
}
Logs filename, line number, function name and optional arguments.
#define superLog(format, ...) NSLog( @"File=%s Line=%d Function=%s " format, strrchr("/" __FILE__,'/')+1, __LINE__, __PRETTY_FUNCTION__, ## __VA_ARGS__ )
Example:
File=MyClass.m Line=16 Function=-[MyClass awakeFromNib]
$ 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:
instrumentObjcMessageSends(YES);
// messages will be traced here
instrumentObjcMessageSends(NO);
NSMutableArray *array = [NSMutableArray new];
@try {
[array addObject:nil];
} @catch (NSException* e) {
NSLog(@"%@", e);
} @finally {
NSLog(@"over");
}
Comment utiliser le système de préférences, ici dans le cas d'un tableau.
NSUserDefaults *prefs;
NSMutableArray *records;
// read prefs at opening
- (void)awakeFromNib {
prefs = [[NSUserDefaults standardUserDefaults] retain];
if([prefs objectForKey:@"Records"] != nil) {
records = [[NSMutableArray alloc] initWithArray:[prefs arrayForKey:@"Records"]];
} else {
records = [[NSMutableArray alloc] init];
}
}
// save prefs
- (void) saveData {
[prefs setObject:records forKey:@"Records"];
}
// dealloc
- (void) dealloc {
[self saveData]; // just to be sure
[prefs synchronize];
[prefs release];
[records release];
[super dealloc];
}
Ne pas oublier de définir le "bundle identifier name" dans targets / myapp / cmd-i / properties / identifier.
Télécharger un projet XCode de démonstration : CocoaPython.zip.
Utiliser une API non documentée
extraire l'API du framework binaire avec l'utilitaire class-dump, exemple :
class-dump
/System/Library/Frameworks/InstantMessage.framework/Versions/A/InstantMessage
> ~/InstantMessage.h
ajouter le framework au projet
importer l'API
#import "InstantMessage.h"
Rien ne garanti que l'API fonctionne toujours dans les futures versions du système.
~/Library/Caches/Metadata/app.bundle.identifier