高確率で思い込みによる説明.間違っていることが多い./「無知だったり、勘違いしていたり、底意を押しつけたり、いいかげんだったり、噂や疑惑を信じていたりして、狂気じみてさえいるかもしれません」( http://bit.ly/gs23zg )
2012年6月30日土曜日
colored token in NSTokenField
http://edotprintstacktrace.tumblr.com/post/26420382864/nstokenattachmentcell-extention-h-import
http://www.google.co.jp/search?q=NSTokenAttachmentCell.h
2011年10月29日土曜日
Sample: Nest of 'WebScriptObject ( Javascript associative array ) to NSDictionary' or 'WebScriptObject ( Javascript array ) to NSArray ) '
SampleAppDelegate.h
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
@interface SampleAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
}
@property (assign) IBOutlet NSWindow *window;
+ (id)structueWithWebScriptObject:(WebScriptObject *)obj
webScriptObject:(WebScriptObject *)scriptObj;
@end
SampleAppDelegate.m
#import "SampleAppDelegate.h"
@implementation SampleAppDelegate
@synthesize window;
+ (NSDictionary *)dictionaryWithWebScriptObject:(WebScriptObject *)obj
webScriptObject:(WebScriptObject *)scriptObj
{
NSMutableDictionary *ret= [NSMutableDictionary dictionary];
id keys= [scriptObj callWebScriptMethod:@"_f0_"
withArguments:[NSArray arrayWithObjects:obj, nil]];
NSArray *keyAry= [SampleAppDelegate structueWithWebScriptObject:keys
webScriptObject:scriptObj];
unsigned i;
for(i= 0; i<[keyAry count]; i++) {
NSString *key= [keyAry objectAtIndex:i];
id val= [obj valueForKey:key];
if ([val isMemberOfClass:[WebScriptObject class]]) {
val= [SampleAppDelegate structueWithWebScriptObject:val
webScriptObject:scriptObj];
}
[ret setObject:val forKey:key];
}
return [[ret retain] autorelease];
}
+ (id)structueWithWebScriptObject:(WebScriptObject *)obj
webScriptObject:(WebScriptObject *)scriptObj
{
@try{
NSMutableArray *ret = [NSMutableArray array];
NSUInteger count = [[obj valueForKey:@"length"] integerValue]; //exception occure if associative array
unsigned i;
for (i = 0; i < count; i++) {
id val= [obj webScriptValueAtIndex:i];
if ([val isMemberOfClass:[WebScriptObject class]]) {
val= [SampleAppDelegate structueWithWebScriptObject:val
webScriptObject:scriptObj];
}
[ret addObject:val];
}
return [[ret retain] autorelease];
}
@catch (NSException *e) {
return [SampleAppDelegate dictionaryWithWebScriptObject:obj
webScriptObject:scriptObj];
}
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
WebView *webView = [[WebView alloc] init];
[[webView mainFrame] loadHTMLString:@"" baseURL:NULL];
WebScriptObject *scriptObject = [webView windowScriptObject];
NSString *_f0_= @"function _f0_(hash){var ret=[];for(var key in hash){ret.push(key);}return ret;}";
NSString *returnValue= @"[{'key0':['val000', 'val001'], 'key1':'val01'}, {'key0':'val10', 'key1':['val110', 'val111']}]";
NSString *code= [NSString stringWithFormat:@"function main(){return %@;}", returnValue];
NSString *script = [NSString stringWithFormat:@"try { %@ %@ } catch (e) { e.toString() }", code, _f0_];
id ret0= [scriptObject evaluateWebScript:script];
if (![ret0 isMemberOfClass:[WebUndefined class]]) {
NSLog(@"ret(main): %@", ret0);
}
id ret= [scriptObject callWebScriptMethod:@"main" withArguments:nil];
if (ret && [ret isMemberOfClass:[WebScriptObject class]]) {
WebScriptObject *obj= (WebScriptObject *)ret;
NSArray *nsRet= [SampleAppDelegate structueWithWebScriptObject:obj
webScriptObject:scriptObject];
NSLog(@"%@", nsRet);
}
}
@end
ResultJavascript
[{'key0':['val000', 'val001'], 'key1':'val01'}, {'key0':'val10', 'key1':['val110', 'val111']}]Cocoa
(
{
key0 = (
val000,
val001
);
key1 = val01;
},
{
key0 = val10;
key1 = (
val110,
val111
);
}
)
Sample: WebScriptObject ( Javascript associative array ) to NSDictionary ( WebScriptObject ( Javascript array ) to NSArray )
Addtion(20111029T2300): Nest Version
SampleAppDelegate.h
#import <Cocoa/Cocoa.h>
#import <WebKit/WebKit.h>
@interface SampleAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
}
@property (assign) IBOutlet NSWindow *window;
@end
SampleAppDelegate.m
#import "SampleAppDelegate.h"
@implementation SampleAppDelegate
@synthesize window;
+ (NSArray *)arrayWithWebScriptObject:(WebScriptObject *)obj
{
NSMutableArray *ret = [NSMutableArray array];
NSUInteger count = [[obj valueForKey:@"length"] integerValue]; //exception occurs if it is associative array.
unsigned i;
for (i = 0; i < count; i++) {
[ret addObject:[obj webScriptValueAtIndex:i]];
}
return [[ret retain] autorelease];
}
+ (NSDictionary *)dictionaryWithWebScriptObject:(WebScriptObject *)obj
webScriptObject:(WebScriptObject *)scriptObj
{
NSMutableDictionary *ret= [NSMutableDictionary dictionary];
id keys= [scriptObj callWebScriptMethod:@"_f0_"
withArguments:[NSArray arrayWithObjects:obj, nil]];
NSArray *keyAry= [SampleAppDelegate arrayWithWebScriptObject:keys];
unsigned i;
for(i= 0; i<[keyAry count]; i++) {
NSString *key= [keyAry objectAtIndex:i];
[ret setObject:[obj valueForKey:key] forKey:key];
}
return [[ret retain] autorelease];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
WebView *webView = [[WebView alloc] init];
[[webView mainFrame] loadHTMLString:@"" baseURL:NULL];
WebScriptObject *scriptObject = [webView windowScriptObject];
NSString *_f0_= @"function _f0_(hash){var ret=[];for(var key in hash){ret.push(key);}return ret;}";
NSString *code= @"function main(){return {'key0':'val0', 'key1':'val1'};}";
NSString *script = [NSString stringWithFormat:@"try { %@ %@ } catch (e) { e.toString() }", code, _f0_];
id ret0= [scriptObject evaluateWebScript:script];
if (![ret0 isMemberOfClass:[WebUndefined class]]) {
NSLog(@"ret(main): %@", ret0);
}
id ret= [scriptObject callWebScriptMethod:@"main" withArguments:nil];
if (ret && [ret isMemberOfClass:[WebScriptObject class]]) {
WebScriptObject *obj= (WebScriptObject *)ret;
NSDictionary *dict= [SampleAppDelegate dictionaryWithWebScriptObject:obj
webScriptObject:scriptObject];
NSLog(@"%@", dict);
}
}
@end
reference: "Notes on Cocoa - Convert a Javascript array to an NSArray"
2011年10月6日木曜日
NSTableViewのカラムのValueに対してプログラム中でBindingをする
NSTableView *tableView;
NSArrayController *arrayController;
NSString *key;
NSTableColumn *tc= [[[NSTableColumn alloc] init] autorelease];
[[tc headerCell] setStringValue:key];
NSString *modelKey= [NSString stringWithFormat:@"arrangedObjects.%@", key];
[tc bind:@"value" toObject:arrayController withKeyPath:modelKey options:nil];
[tableView addTableColumn:tc];
tableViewからtableColumnを取得してもよいはず.
円弧のNSBezierPath
- (void) appendBezierPathWithArcWithCenter:radius:startAngle:endAngle:でいいじゃんとか言わない.
開始点を変更したい場合は最後の平行移動前(書く時は後ろ)にて回転させればよい.(コメント部)
描画ならCGContextAddArcか.
double CX= __CENTER_X_;
double CY= __CENTER_X_;
double r= __RADIUS__
double b= __RATIO__0_TO_1_;
NSBezierPath *path= [NSBezierPath bezierPath];
double a= 4.0/3.0 * (sqrt(2)-1) * r;
double c= 0.0;
[path moveToPoint:NSMakePoint(+r, 0)];
if (b>0.25) {
[path curveToPoint:NSMakePoint(0, +r)
controlPoint1:NSMakePoint(+r, +a)
controlPoint2:NSMakePoint(+a, +r)];
b-= 0.25;
c+= 90.0;
}
if (b>0.25) {
[path curveToPoint:NSMakePoint(-r, 0)
controlPoint1:NSMakePoint(-a, +r)
controlPoint2:NSMakePoint(-r, +a)];
b-= 0.25;
c+= 90.0;
}
if (b>0.25) {
[path curveToPoint:NSMakePoint(0, -r)
controlPoint1:NSMakePoint(-r, -a)
controlPoint2:NSMakePoint(-a, -r)];
b-= 0.25;
c+= 90.0;
}
if(b==0.25) {
[path curveToPoint:NSMakePoint(+r, 0)
controlPoint1:NSMakePoint(+a, -r)
controlPoint2:NSMakePoint(+r, -a)];
//b-= 0.25;
//c+= 90.0;
}
elseif (b<0.25){
NSAffineTransform *affine= [NSAffineTransform transform];
[affine rotateByDegrees:c];
double t= b/0.25;
double it= (1.-t);
[path curveToPoint:[affine transformPoint:NSMakePoint(+cos(t*M_PI_2)*r, +sin(t*M_PI_2)*r)]
controlPoint1:[affine transformPoint:NSMakePoint(+r, +a*t)]
controlPoint2:[affine transformPoint:NSMakePoint(+(it*it*r+2*it*t*r+t*t*a), +(it*it*0+2*it*t*a+t*t*r))]
];
}
NSAffineTransform *affine= [NSAffineTransform transform];
[affine translateXBy:CX yBy:CY];
//[affine rotateByDegrees:45];
[path transformUsingAffineTransform:affine];
開始点を変更したい場合は最後の平行移動前(書く時は後ろ)にて回転させればよい.(コメント部)
描画ならCGContextAddArcか.
参考: s.h's page - [graphic] ベジエ曲線
2011年9月14日水曜日
メモ的: Twitterのhome_timelineの情報を無理矢理4storeに入れてみる(いろんな意味でいろいろ間違ってるとは思う)
#import "TwTurtleAppDelegate.h"
#import <OAuthConsumer/OAuthConsumer.h>
#import "FourStore.h"
@implementation TwTurtleAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
OAConsumer *consumer = [[OAConsumer alloc] initWithKey:@"XXXXXXXXXXXXXXXXXXXXXX"
secret:@"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"];
OAToken *accessToken= [[OAToken alloc] initWithKey:@"XXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
secret:@"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"];
NSURL *url= [NSURL URLWithString:@"http://api.twitter.com/1/statuses/home_timeline.xml"];
OAMutableURLRequest *requestWithBodyParams = [[[OAMutableURLRequest alloc] initWithURL:url
consumer:consumer
token:accessToken
realm:nil
signatureProvider:nil] autorelease];
OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:requestWithBodyParams
delegate:self
didFinishSelector:@selector(apiTicket:didFinishWithData:)
didFailSelector:@selector(apiTicket:didFailWithError:)];
}
- (void)fourstoreWithTurtle:(NSString *)turtle
{
FourStore *store= [[FourStore alloc] initWithEndpoint:@"http://localhost:8000/sparql/"];
[store addPrefix:@"tsp" uri:@"http://example.org/twitter/status/predicate/"];
[store addPrefix:@"tu" uri:@"http://example.org/twitter/users/"];
NSString *message0= [store deleteWithGraph:@"http://example.org/twitter/status/"];
NSLog(@"message0 %@", message0);
NSString *message1= [store addTurtle:turtle graph:@"http://example.org/twitter/status/"];
NSLog(@"message1 %@", message1);
NSString *message2= [store queryWithString:
@"SELECT ?s ?p ?o \nWHERE {\nGRAPH <http://example.org/twitter/status/> {\n?s ?p ?o .\n}\n}\n"];
NSLog(@"message2 \n%@", message2);
}
- (NSString *)createTurtleWithXMLData:(NSData *)data
{
NSMutableString *turtle= [NSMutableString string];
NSXMLDocument *document = [[[NSXMLDocument alloc] initWithData:data
options:NSXMLDocumentTidyHTML
error:NULL] autorelease];
NSError *error= nil;
NSArray *nodes = [document nodesForXPath:@"//status" error:&error];
NSEnumerator *nodesEnum= [nodes objectEnumerator];
NSXMLNode *node= nil;
while(node= [nodesEnum nextObject]) {
NSArray *idnodes= [node nodesForXPath:@"id" error:&error];
if ([idnodes count]==0) continue;
NSString *idString= [[idnodes objectAtIndex:0] stringValue];
NSEnumerator *childrenEnum= [[node children] objectEnumerator];
NSXMLNode *child=nil;
while(child= [childrenEnum nextObject]) {
NSString *name= [child name];
if ([name isEqualToString:@"id"])
continue;
NSString *value= nil;
if ([name isEqualToString:@"retweeted_status"]){
NSArray *cidnodes= [child nodesForXPath:@"id" error:&error];
if ([cidnodes count]==0) continue;
NSString *cidString= [[cidnodes objectAtIndex:0] stringValue];
value= [NSString stringWithFormat:@"<%@>", cidString];
} else if ([name isEqualToString:@"user"]){
NSArray *cidnodes= [child nodesForXPath:@"id" error:&error];
if ([cidnodes count]==0) continue;
NSString *cidString= [[cidnodes objectAtIndex:0] stringValue];
value= [NSString stringWithFormat:@"<tu:%@>", cidString];
} else {
if ([[child stringValue] length]==0) continue;
value= [child stringValue];
value= [value stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""];
value= [value stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"];
value= [NSString stringWithFormat:@"\"%@\"", value];
}
[turtle appendFormat:@"<%@> tsp:%@ %@ .\n", idString, name, value];
}
}
return turtle;
}
- (void)apiTicket:(OAServiceTicket *)ticket
didFinishWithData:(NSData *)data
{
if (0)
NSLog(@"didFinish %@", [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease]);
NSString *turtle= [self createTurtleWithXMLData:data];
if (0)
NSLog(@"\n%@", turtle);
[self fourstoreWithTurtle:turtle];
}
- (void)apiTicket:(OAServiceTicket *)ticket
didFailWithError:(NSError *)error
{
NSLog(@"%@", error);
}
@end
やってみてアレコレ悩んだ足跡.
2011年9月12日月曜日
Cocoa ( Objective-C )での 4store の Client Library (?)
動機
4storeを入れてみた.rubyのclient用ライブラリをみて,似たものをcocoaでやってみようと思った(たぶん既にどこかにあるだろうけど).入れる際(環境: MacOSX10.7)にハマった点MacPortsでraptorとrasqalを入れたのだがraptorに1.x(www/raptor)と2.x(www/raptor2)があり, rasqal0.9.26がraptor2.xを利用して入っているのにraptor 1.xが入ったままだと4storeのmake時にエラーがでたこと. "git clone https://github.com/garlik/4store.git"でとってきたらconfigureがなかったので(そういうものなのかな?), "sh autogen.sh"から始めたこと.
やってみた(rubyにあるload作ってないしsetもマネの途中)FourStore.h
@interface FourStore : NSObject
{
NSURL *_urlSPARQL;
NSURL *_urlDATA;
NSMutableArray *_prefixs;
}
- (id)initWithEndpoint:(NSString *)endpoint;
- (void)addPrefix:(NSString *)prefix uri:(NSString *)uri;
- (NSString *)addTurtle:(NSString *)turtle graph:(NSString *)graph;
//- (NSString *)setTurtle:(NSString *)turtle graph:(NSString *)graph;
- (NSString *)queryWithString:(NSString *)query;
- (NSString *)deleteWithGraph:(NSString *)graph;
@endFourStore.m
#import "FourStore.h"
@implementation FourStore
- (id)init
{
self = [super init];
if (self) {
}
return self;
}
- (id)initWithEndpoint:(NSString *)endpoint
{
if (![endpoint hasSuffix:@"/sparql/"]) {
return nil;
}
self = [self init];
if (self) {
_urlSPARQL= [[NSURL URLWithString:endpoint] retain];
NSArray *ary= [endpoint componentsSeparatedByString:@"/sparql/"];
_urlDATA= [[NSURL URLWithString:[NSString stringWithFormat:@"%@/data/", [ary objectAtIndex:0]]] retain];
_prefixs= [[NSMutableArray array] retain];
}
return self;
}
- (void)dealloc
{
[_urlSPARQL release];
[_urlDATA release];
[super dealloc];
}
+ (NSString *)sendRequest:(NSURLRequest *)request
{
NSURLResponse *response=nil;
NSError *error= nil;
NSData *data= [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
if (error) {
NSLog(@"statusCode %ld", [response statusCode]);
NSLog(@"error code %ld", [error code]);
}
NSString *message= [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [message autorelease];
}
+ (NSString *)send:(NSString *)request url:(NSURL *)url method:(NSString *)method
{
NSMutableURLRequest *requestWithBodyParams = [[NSMutableURLRequest alloc] initWithURL:url];
NSData *requestData = [request dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
[requestWithBodyParams setHTTPBody:requestData];
[requestWithBodyParams setValue:[NSString stringWithFormat:@"%d", [requestData length]]
forHTTPHeaderField:@"Content-Length"];
[requestWithBodyParams setValue:@"application/x-www-form-urlencoded"
forHTTPHeaderField:@"Content-Type"];
[requestWithBodyParams setHTTPMethod:method];
NSString *msg= [FourStore sendRequest:requestWithBodyParams];
[requestWithBodyParams release];
return msg;
}
- (void)addPrefix:(NSString *)prefix uri:(NSString *)uri
{
[_prefixs addObject:[NSDictionary dictionaryWithObjectsAndKeys:
prefix, @"p", uri, @"u", nil]];
}
- (NSString *)prefixsOfQuery
{
NSMutableString *ret= [NSMutableString string];
NSEnumerator *prefixsEnum= [_prefixs objectEnumerator];
NSDictionary *dic;
while(dic= [prefixsEnum nextObject]) {
[ret appendFormat:@"PREFIX %@: <%@>\n", [dic objectForKey:@"p"], [dic objectForKey:@"u"]];
}
return [[ret retain] autorelease];
}
- (NSString *)prefixsOfTurtle
{
NSMutableString *ret= [NSMutableString string];
NSEnumerator *prefixsEnum= [_prefixs objectEnumerator];
NSDictionary *dic;
while(dic= [prefixsEnum nextObject]) {
[ret appendFormat:@"@prefix %@: <%@> .\n", [dic objectForKey:@"p"], [dic objectForKey:@"u"]];
}
return [[ret retain] autorelease];
}
- (NSString *)queryWithString:(NSString *)query
{
NSString *fullquery= [NSString stringWithFormat:@"%@%@", [self prefixsOfQuery], query];
NSString *request= [NSString stringWithFormat:@"query=%@&soft-limit=%@",
[fullquery stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding], @""];
return [FourStore send:request url:_urlSPARQL method:@"POST"];
}
- (NSString *)addTurtle:(NSString *)turtle graph:(NSString *)graph
{
NSString *fullturtle= [NSString stringWithFormat:@"%@%@", [self prefixsOfTurtle], turtle];
NSString *request= [NSString stringWithFormat:@"mime-type=%@&data=%@&graph=%@",
[@"application/x-turtle" stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[fullturtle stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
[graph stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
return [FourStore send:request url:_urlDATA method:@"POST"];
}
//- (NSString *)setTurtle:(NSString *)turtle graph:(NSString *)graph
//{
// NSString *fullturtle= [NSString stringWithFormat:@"%@%@", [self prefixsOfTurtle], turtle];
//
// NSString *request= [fullturtle stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//
// NSURL *url= [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", [_urlDATA absoluteString], graph]];
//
// return [FourStore send:request url:url method:@"PUT"];
//}
- (NSString *)deleteWithGraph:(NSString *)graph
{
NSURL *url= [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", [_urlDATA absoluteString], graph]];
return [FourStore send:@"" url:url method:@"DELETE"];
}
@end
使い方(?)
FourStore *store= [[FourStore alloc] initWithEndpoint:@"http://localhost:8000/sparql/"];
[store addPrefix:@"dc" uri:@"http://purl.org/dc/elements/1.1/"];
if (1) {
NSString *msg= [store addTurtle:@"<http://example.org/book/book1> dc:title \"SPARQL Tutorial\" ."
graph:@"http://example.org/book"];
NSLog(@"%@", msg);
}
if (1) {
NSString *msg= [store queryWithString:
@"SELECT ?title \nWHERE {\nGRAPH <http://example.org/book> {\n<http://example.org/book/book1> <http://purl.org/dc/elements/1.1/title> ?title .\n}\n}\n"];
NSLog(@"%@", msg);
}
if (1) {
NSString *msg= [store queryWithString:
@"SELECT ?title \nWHERE {\nGRAPH <http://example.org/book> {\n<http://example.org/book/book1> dc:title ?title .\n}\n}\n"];
NSLog(@"%@", msg);
}
if (1) {
NSString *msg= [store deleteWithGraph:@"http://example.org/book"];
NSLog(@"%@", msg);
}
[store release];
結果
(> 4s-backend-setup [KB])
> 4s-backend [KB]
> 4s-httpd -p 8000 -U [KB]
> 200 added successfully
This is a 4store SPARQL server v1.1.3-54-gd8008fc
> <?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="title"/>
</head>
<results>
<result>
<binding name="title"><literal>SPARQL Tutorial</literal></binding>
</result>
</results>
</sparql>
> <?xml version="1.0"?>
<sparql xmlns="http://www.w3.org/2005/sparql-results#">
<head>
<variable name="title"/>
</head>
<results>
<result>
<binding name="title"><literal>SPARQL Tutorial</literal></binding>
</result>
</results>
</sparql>
> 200 deleted successfully
This is a 4store SPARQL server v1.1.3-54-gd8008fc
2011年8月20日土曜日
Cocoa / nsAlert setAccessoryView:でJOptionPane.showInputDialog(Java)っぽいこと
NSTextField *textField= [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 100, 20)];
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:@"Message text"];
[alert setInformativeText:@"Informative text"];
[alert setAccessoryView:textField];
[alert runModal];
NSLog(@"DONE: %@", [textField stringValue]);
[textField release];
[alert release];
IBにてCustomViewにNSFormくっつけてaccessoryViewを用意する方がカッコイイかも.
(NSFormの入力フィールドにBindingするときはForm CellのValueになるように.)
Quartz Composer / Automator / AutomatorのパッチでQCRender関連のナンカを実装してみた
動機
これをやったのでこれ的なQCRenderネタをやってみようかと安易に思った('Quartz コンポジションフィルタをイメージに適用'ってパッチが既にありますが).
やってみた0.プロジェクトの作成
プロジェクトの修正等はこちらを参照下さい.
xibのFile's Ownerのクラスも上記と同じクラス名で修正する(こちらの3.xibを編集を参照のこと).
OpenGLとQuartzのframeworkを追加した.
1.コード
#import <Automator/AMBundleAction.h>
#import <Quartz/Quartz.h>
@interface QuartzComposer : AMBundleAction
- (id)runWithInput:(id)input fromAction:(AMAction *)anAction error:(NSDictionary **)errorInfo;
- (IBAction)openQTZ:(id)sender;
@end
#import "QuartzComposer.h"
@implementation QuartzComposer
- (IBAction)openQTZ:(id)sender
{
NSString *compositionPath= [[NSBundle bundleForClass:[self class]] pathForResource:@"composition" ofType:@"qtz"];
[[NSWorkspace sharedWorkspace] openFile:compositionPath withApplication:@"Quartz Composer"];
}
- (id)runWithInput:(id)input fromAction:(AMAction *)anAction error:(NSDictionary **)errorInfo
{
NSUInteger width= 16;
NSUInteger height= 16;
NSString *compositionPath= [[NSBundle bundleForClass:[self class]] pathForResource:@"composition" ofType:@"qtz"];
QCRenderer *renderer= nil;
{
NSOpenGLPixelFormatAttribute attributes[]= {
NSOpenGLPFAPixelBuffer,
NSOpenGLPFANoRecovery,
NSOpenGLPFAAccelerated,
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)24,
NSOpenGLPFASampleBuffers, (NSOpenGLPixelFormatAttribute)1,
NSOpenGLPFASamples, (NSOpenGLPixelFormatAttribute)16,
(NSOpenGLPixelFormatAttribute)0
};
NSOpenGLPixelFormat *format= [[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes] autorelease];
NSOpenGLPixelBuffer *pixelBuffer= [[NSOpenGLPixelBuffer alloc] initWithTextureTarget:GL_TEXTURE_RECTANGLE_EXT
textureInternalFormat:GL_RGBA
textureMaxMipMapLevel:0
pixelsWide:width
pixelsHigh:height];
NSOpenGLContext *openGLContext= [[NSOpenGLContext alloc] initWithFormat:format shareContext:nil];
if(pixelBuffer == nil || openGLContext == nil) {
NSLog(@"no buffer or no context");
return nil;
}
[openGLContext setPixelBuffer:pixelBuffer
cubeMapFace:0
mipMapLevel:0
currentVirtualScreen:[openGLContext currentVirtualScreen]];
renderer= [[QCRenderer alloc] initWithOpenGLContext:openGLContext pixelFormat:format file:compositionPath];
}
NSMutableArray *outputPaths= [NSMutableArray array];
if(renderer) {
NSMutableArray *inputPaths= [NSMutableArray array];
if ([input isKindOfClass:[NSArray class]]) {
[inputPaths addObjectsFromArray:input];
}
else if ([input isKindOfClass:[NSString class]]) {
[inputPaths addObject:input];
}
int i;
for(i=0;i<[inputPaths count];i++) {
NSString *inputPath= [inputPaths objectAtIndex:i];
NSImage *inputImage= [[[NSImage alloc] initWithContentsOfFile:inputPath] autorelease];
[renderer setValue:inputImage forInputKey:@"InputImage"];
if(![renderer renderAtTime:0.0 arguments:nil]) {
NSLog(@"no rendering");
return nil;
}
[renderer createSnapshotImageOfType:@"NSBitmapImageRep"];
NSImage *image= (NSImage *)[renderer valueForOutputKey:@"OutputImage"];
NSBitmapImageRep *bitmapImage= [NSBitmapImageRep imageRepWithData:[image TIFFRepresentation]];
if(bitmapImage) {
char *tempNameBytes = tempnam([NSTemporaryDirectory() fileSystemRepresentation], "QCComposition_Result_");
NSString *tempName = [[[NSString alloc] initWithBytesNoCopy:tempNameBytes
length:strlen(tempNameBytes)
encoding:NSUTF8StringEncoding
freeWhenDone:YES] autorelease];
NSString *outputPath= [tempName stringByAppendingPathExtension:@"png"];
NSDictionary *properties= [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithFloat:1.0], NSImageCompressionFactor,
nil];
NSData *pngImageData= [bitmapImage representationUsingType:NSPNGFileType
properties:properties];
[pngImageData writeToFile:outputPath
atomically:YES];
[outputPaths addObject:outputPath];
}
}
}
else {
NSLog(@"no render");
}
return outputPaths;
}
@end2.composition.qtzを作成する
Quartz Composerで作成する.この際にInputImageというPublished InputとOutputImageというPublished Outputを用意する.
3.Supporting Files(リソース)にコンポジション(composition.qtz)を加える
Build PhasesのCopy Bundle Resourcesに含まれていること.
4.Viewまわり
xlbにボタンを配置して(IBAction)openQTZ:に繋ぐ.
あとはBuildして配置(~/Library/Automator/下).
結果![]()
![]()
Motion Blurなのでこんな感じ.
2011年8月13日土曜日
Xcode4.1のAutomator Plugin ProjectをCocoaでつくる際のテンプレートの修正点
Automator Plugin Projectを作成![]()
Cocoa の指定を確認
プロジェクトの設定(Infoタブ)を確認![]()
Principal classがAMShellScriptActionになぜかなってる.
このまま作成し配置. AMで利用すると実行時に"launch path not accessible"って言われて終了しちゃう.
修正![]()
プロジェクト作成でできるObjective-C class("- (id)runWithInput:(id)input fromAction:(AMAction *)anAction error:(NSDictionary **)errorInfo"の実装を書くオブジェクト.AMBundleActionの派生)名(テンプレートではファイル名と同じ)に修正.
2011年8月9日火曜日
OAuthConsumer.frameworkを使う(TwitterへPOST)
動機
前回の物を使ってみるため,あちらこちらのサンプルを継ぎ接ぎして(例えば)以下の様にしたら動いた..
やってみた.
フレームワークの追加
~/Library/Frameworks/のOAuthConsumer.frameworkを追加/System/Library/Framewokrs/のSecurity.frameworkを追加
フレームワークの利用のためのHeader
#import <OAuthConsumer/OAuthConsumer.h>
インスタンス変数
OAConsumer *consumer;
OAToken *accessToken;
インスタンス変数の初期化
consumer = [[OAConsumer alloc] initWithKey:@"[Consumer Key]"
secret:@"[Consumer Secret Key]"];
accessToken= nil;
Consumer Key/Consumer Secret KeyはTwitterの開発者サイトで登録し取得する.
ConsumerKey/ConsumerSecretKeyからRequestTokenを取得へ
- (void)requestRequestToken
{
NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/oauth/request_token"];
OAMutableURLRequest *request = [[OAMutableURLRequest alloc] initWithURL:url
consumer:consumer
token:nil
realm:nil
signatureProvider:nil];
[request setHTTPMethod:@"POST"];
OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request
delegate:self
didFinishSelector:@selector(requestTokenTicket:didFinishWithData:)
didFailSelector:@selector(requestTokenTicket:didFailWithError:)];
}
- (void)requestTokenTicket:(OAServiceTicket *)ticket
didFinishWithData:(NSData *)data
{
if (ticket.didSucceed) {
…
}
}
- (void)requestTokenTicket:(OAServiceTicket *)ticket
didFailWithError:(NSError *)error
{
NSLog(@"%@", error);
}
RequestTokenから認証のWebページ(PIN)の取得へ
- (void)requestTokenTicket:(OAServiceTicket *)ticket
didFinishWithData:(NSData *)data
{
if (ticket.didSucceed) {
OAMutableURLRequest *request;
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
if (accessToken != nil) {
[accessToken release];
accessToken = nil;
}
accessToken = [[OAToken alloc] initWithHTTPResponseBody:responseBody];
[responseBody release];
NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/oauth/authorize"];
request = [[[OAMutableURLRequest alloc] initWithURL:url
consumer:consumer
token:accessToken
realm:nil
signatureProvider:nil] autorelease];
OARequestParameter *p0 = [[OARequestParameter alloc] initWithName:@"oauth_token"
value:accessToken.key];
NSArray *params = [NSArray arrayWithObject:p0];
[request setParameters:params];
[[NSWorkspace sharedWorkspace] openURL:[request URL]];
[p0 release];
}
else {
}
}
(デフォルトブラウザでURLが開かれる.ここではTwitterサイトでの認証であり数字キー(PIN)が手に入る
PINからAccessTokenの取得へ
- (void)authorizationWithPin:(NSString *)pin
{
OAMutableURLRequest *request;
OADataFetcher *fetcher;
NSURL *url = [NSURL URLWithString:@"https://api.twitter.com/oauth/access_token"];
request = [[[OAMutableURLRequest alloc] initWithURL:url
consumer:consumer
token:accessToken
realm:nil
signatureProvider:nil] autorelease];
OARequestParameter *p0 = [[OARequestParameter alloc] initWithName:@"oauth_token"
value:accessToken.key];
OARequestParameter *p1 = [[OARequestParameter alloc] initWithName:@"oauth_verifier"
value:pin];
NSArray *params = [NSArray arrayWithObjects:p0, p1, nil];
[request setParameters:params];
fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:request
delegate:self
didFinishSelector:@selector(accessTokenTicket:didFinishWithData:)
didFailSelector:@selector(accessTokenTicket:didFailWithError:)];
[p0 release];
[p1 release];
}
- (void)accessTokenTicket:(OAServiceTicket *)ticket
didFinishWithData:(NSData *)data
{
if (ticket.didSucceed) {
…
}
}
- (void)accessTokenTicket:(OAServiceTicket *)ticket
didFailWithError:(NSError *)error
{
NSLog(@"%@", error);
}
accessTokenを生成してDefaultUserInfoへ保存
- (void)accessTokenTicket:(OAServiceTicket *)ticket
didFinishWithData:(NSData *)data
{
if (ticket.didSucceed) {
NSString *responseBody = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
if (accessToken != nil) {
[accessToken release];
accessToken = nil;
}
accessToken = [[OAToken alloc] initWithHTTPResponseBody:responseBody];
[responseBody release];
[accessToken storeInUserDefaultsWithServiceProviderName:@"NAME"
prefix:@"KEY"];
}
}
(ちなみにDeaultUserInfoから取り出すときは)
accessToken= [[OAToken alloc] initWithUserDefaultsUsingServiceProviderName:@"NAME"
prefix:@"KEY"];
accessTokenを使ってPOSTしてみる
NSString *message= @"Hello World!";
NSURL *url= [NSURL URLWithString:@"http://api.twitter.com/1/statuses/update.xml"];
OAMutableURLRequest *requestWithBodyParams = [[[OAMutableURLRequest alloc] initWithURL:url
consumer:consumer
token:accessToken
realm:nil
signatureProvider:nil] autorelease];
NSString *encodedParameterPairs= [NSString stringWithFormat:@"status=%@", [message URLEncodedString]];
NSData *requestData = [encodedParameterPairs dataUsingEncoding:NSASCIIStringEncoding
allowLossyConversion:YES];
[requestWithBodyParams setHTTPBody:requestData];
[requestWithBodyParams setValue:[NSString stringWithFormat:@"%d", [requestData length]]
forHTTPHeaderField:@"Content-Length"];
[requestWithBodyParams setValue:@"application/x-www-form-urlencoded"
forHTTPHeaderField:@"Content-Type"];
[requestWithBodyParams setHTTPMethod:@"POST"];
OADataFetcher *fetcher = [[[OADataFetcher alloc] init] autorelease];
[fetcher fetchDataWithRequest:requestWithBodyParams
delegate:self
didFinishSelector:@selector(apiTicket:didFinishWithData:)
didFailSelector:@selector(apiTicket:didFailWithError:)];
- (void)apiTicket:(OAServiceTicket *)ticket
didFinishWithData:(NSData *)data
{
…
}
- (void)apiTicket:(OAServiceTicket *)ticket
didFailWithError:(NSError *)error
{
NSLog(@"%@", error);
}
結果
http://twitter.com/#!/p_g_/status/100810688833912833![]()
OAuthConsumer.frameworkを設置(インストール)してみる
動機
OAuth周りのCocoaの実装であるOAuthConsumer.frameworkというのを知ったのでインストールしてみる.
やってみたコンソールで以下を実行.obj-cフォルダが出来上がる.> svn checkout http://oauth.googlecode.com/svn/code/obj-c
checkoutしたフォルダ内の以下を開く(Xcode).obj-c/OAuthConsumer/OAuthConsumer.xcodeproj
コンパイル
Build for Running
OAuthConsumer.frameworkを確認![]()
Finderでの表示.![]()
インストール先をターミナルで開く> mkdir -p ~/Library/Frameworks
> open ~/Library/Frameworks/
OAuthConsumer.framework をドラッグして ~/Library/Frameworks/ へドロップ
できた.
2011年5月26日木曜日
Quartz Composer / QCViewからのスナップショット
メモ
[nsBitmapImageRep initWithFocusedViewRect:]や[nsView cacheDisplayInRect:toBitmapImageRep:]では背景色の四角形(QCViewサイズの)が出てくるだけだったので?と思ったら専用のメソッドがQCViewにあったのでメモ.NSBitmapImageRep *imgRep= [qcView createSnapshotImageOfType:@"NSBitmapImageRep"];
引数の文字列はNSBitmapImageRep, NSImage, CIImage, CGImage, CVOpenGLBuffer, CVPixelBufferのどれかで返り値もそのインスタンスとなる.そうだ.
参考
QCView Class Reference / createSnapshotImageOfType:
2011年3月21日月曜日
正規表現のメタ文字をエスケープした文字列を返す
参考:
NSArray と NSPredicate を使った正規表現検索 / Cocoaの日々 - 2005年10月
Regular Expression Metacharacters / Regular Expressions - ICU User Guide
感謝
コード:- (NSString *)escapedStringWithString:(NSString *)string
{
NSString *value= [NSString stringWithString:string];
NSString *targets= @"\*?+[(){}^$|./";
NSInteger i;
for(i= 0; i<[targets length]; i++) {
NSString *findC= [targets substringWithRange:NSMakeRange(i, 1)];
NSString *replaceS= [NSString stringWithFormat:@"\\\\%@", findC];
value= [value stringByReplacingOccurrencesOfString:findC
withString:replaceS];
}
return value;
}
バックスラッシュについては一番最初に行うことで,エスケープ用のバックスラッシュが置換されないようにしている.
きっともっと賢いやり方や一撃メソッドがあるんだとは思う.
2010年12月4日土曜日
ノートパソコンを縦てに置いて見るPDF Viewer
動機
MacBook Proの画面でA4 PDFを全画面表示すると両端が余るのをみて,もっとでっかく表示できるはずだよな.と思ったので.
1ページPDFならプレビューの回転でよいが2ページ以上で一度に全部を回転できなかった(やり方の問題だったりして).
探せば既に便利ツールがありそうな気もしたがPDFViewを試すつもりで自作
やってみた
できた.
便利に使えるかどうかはわからないけどできたので“PDFViewの試しの産物”として置いてみた.http://sites.google.com/site/pgtwitter/cocoa
2010年11月14日日曜日
読みを取り出す
追記: portで入れた辞書の利用にはdylibを/opt/local/lib/libmecab.dylibにして, 'mecab_new2("-d /opt/local/lib/mecab/dic/ipadic-utf8/");'と引数を与える.
動機
Mecabに関する前回の結果から読みを取り出せないか?ということで挑戦.
やってみた
0.どうもappleの辞書では読みが取り出せない(おいらのやり方がわるいためだろうか).
1.portでmecabのutf-8の辞書を入れてみる.('sudo port install mecab-ipadic-utf8')
2.mecabの分析を以下のように変更- (NSArray *)mecabResultWithString:(NSString *)input
{
NSMutableArray *ret= [NSMutableArray array];
if (input==nil || [input length]==0)
return ret;
const char *buf= [input cStringUsingEncoding:NSUTF8StringEncoding];
NSUInteger l= [input lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
const mecab_node_t *node = mecab_sparse_tonode2(mecab, buf, l);
if (node == NULL) {
return ret;
}
node = node->next;
for (; node->next != NULL; node = node->next) {
NSString *f = [NSString stringWithCString:node->feature encoding:NSUTF8StringEncoding];
NSString *yomi= [[f componentsSeparatedByString:@","] objectAtIndex:7];
[ret addObject:yomi];
}
return ret;
}
3.読みをローマ字にしてみた.int i, ic= [mecabResult count];
NSMutableString *str= [NSMutableString string];
for(i= 0;i<ic;i++) {
[str appendFormat:@"%@ ", [mecabResult objectAtIndex:i]];
}
CFStringTransform(str, NULL, kCFStringTransformHiraganaKatakana, YES); //カタカナ→ひらがな
CFStringTransform(str, NULL, kCFStringTransformLatinHiragana, YES); //ひらがな→ローマ字(?)
NSLog(@"%@", str);
4.発声してみるならこういうコードらしいNSSpeechSynthesizer *synth = [[NSSpeechSynthesizer alloc] init];
[synth startSpeakingString:str];
[synth autorelease];
結果
入力: 微かなオレンジの香りが残っていた
出力: kasuka na orenji no kaori ga noko~tsu te i ta
2010年11月13日土曜日
NSXMLElementの下にあるテキスト部を抜き出す
動機
これで取り出したものに対してこれをやってみたいなぁっていうあたりからタグを外さないとと思い立って始めた(コード1).(タイトルはここまで.これを記録するためのエントリー)
ところが,MeCabにHTMLタグ付きで入れてもそれらを対象とせずに問題なく処理するらしいことを後で知った.のでこれだけなら単純にNXSMLNodeのstringValueメソッドでもよかた.
ただ,この方法ではエンコードされた文字('>'→'>')などはそのままになってしまう.そこでNSAttributedStringを利用してこれを解決してみた(コード2).参考
やってみた
コード1(戦略: HTMLのパース結果であるNSXMLNodeの種類を利用してNSXMLTextKindを収集することでタグのない部分を集める)- (NSString *)textStringWithNode:(NSXMLNode *)elem
{
NSMutableString *ret= [NSMutableString string];
int j, jc= [elem childCount];
for(j= 0; j<jc; j++) {
NSXMLNode *elmeChild= [elem childAtIndex:j];
if ([elmeChild kind] == NSXMLTextKind) {
[ret appendString:[elmeChild stringValue]];
}
else {
[ret appendString:[self textStringWithNode:elmeChild]];
}
}
return ret;
}
コード2(戦略: HTMLソース文字列からNSAttributedStringを生成し,stringメソッドでNSString化することでタグ類を外す.タグ類は属性となっているのでstringには出てこない)- (NSString *)textStringWithHTMLNode:(NSXMLNode *)elem
{
NSString *input= [elem stringValue];
NSDictionary *option= [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:NSUTF8StringEncoding],
NSCharacterEncodingDocumentOption,
nil];
NSAttributedString *as= [[NSAttributedString alloc] initWithHTML:
[input dataUsingEncoding:NSUTF8StringEncoding]
options:option
documentAttributes:nil];
[as autorelease];
return[as string];
}
このメソッドの引数は都合でNXSMLNodeにしているが,一行目の処理どおり,HTMLソースを文字列(NSString)として持っている場合でも,利用することができそうだ.
2010年11月11日木曜日
MacOS X 10.6にデフォルトで入っているlibmecab.dylib ( MeCab )を使ってみた
追記(2011/2/4): FYI 'Google groups / cocoa-dev-japan / 日本語文字列を文節に分解するには?'
追記2(2010/11/12): lengthOfBytesUsingEncodingで文字列の長さを出してmecab_sparse_tonode2を用いることで解決.参考サイトの通りに作ればちゃんと動く.
追記(2010/11/12): 半角が入ると止まる.mecabさんの設定になにかする必要があるのかしら…。CFStringTransformで「全角から半角」の逆変換をかけてUTF16LEへ変換して,mecabへ入れてみたが,あまりうまくいってない.
動機
なんとなく.
やってみた.
0.Cocoaプロジェクトを作る('Untitled').
1./usr/libをFinderで開き(コンソールで'open /usr/lib'とかする),libmecab.dylibをDnDにてプロジェクトに追加.(コピーはしない)
2.コードを書く
UntitledAppDelegate.h#import <Cocoa/Cocoa.h>
#include "mecab.h"
@interface UntitledAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
mecab_t *mecab;
NSString *_inputString;
NSArray *_mecabResult;
}
@property (assign) IBOutlet NSWindow *window;
@end
UntitledAppDelegate.m#import "UntitledAppDelegate.h"
@implementation UntitledAppDelegate
@synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
mecab = mecab_new2("-d /usr/lib/mecab/dic/apple/ja/LE");
if (mecab == NULL) {
fprintf(stderr, "error in mecab_new2: %s\n", mecab_strerror(NULL));
}
}
- (void)dealloc
{
mecab_destroy(mecab);
[super dealloc];
}
- (NSString *)inputString
{
return [[_inputString retain] autorelease];
}
- (void)setInputString:(NSString *)inputString
{
[_inputString release];
_inputString= [inputString retain];
[self setMecabResult:[self mecabResultWithString:_inputString]];
}
- (NSArray *)mecabResult
{
return [[_mecabResult retain] autorelease];
}
- (void)setMecabResult:(NSArray *)mecabResult
{
[_mecabResult release];
_mecabResult= [mecabResult retain];
}
- (NSArray *)mecabResultWithString:(NSString *)input
{
NSMutableArray *ret= [NSMutableArray array];
if (input==nil || [input length]==0)
return ret;
const char *buf= [input cStringUsingEncoding:NSUTF16LittleEndianStringEncoding];
const mecab_node_t *node = mecab_sparse_tonode(mecab, buf);
NSUInteger l= [input lengthOfBytesUsingEncoding:NSUTF16LittleEndianStringEncoding];
const mecab_node_t *node = mecab_sparse_tonode2(mecab, buf, l);
if (node == NULL) {
return ret;
}
node = node->next;
for (; node->next != NULL; node = node->next) {
NSString *w = [[NSString alloc] initWithBytes:node->surface
length:node->length
encoding:NSUTF16LittleEndianStringEncoding];
[ret addObject:w];
[w release];
}
return ret;
}
@end
3.IBにてNSTextFiledとNSTokenFieldを配置.
4.IBにて上記それぞれのインスペクタ/Bindingsタブにてvalue属性についてUntitledAppDelegateに対してModel Key PathをinputString, mecabResultと設定する.
5.実行
実行
参考サイト
感謝!
きまぐれ日記: Mac OS X Leopard に「標準で」インストールされている MeCabを使ってみる
2010年11月5日金曜日
Webページ内をXPathで指定して抜き出して保存するなどしてみた.
追記(2010/11/07): NSThread sleepForTimeInterval:でリクエスト間隔をあけるようにしてみた.
動機
TumblrみたいなバックアップとれればSpotlightで文字列検索できるのになぁ…。
やってみた条件
・URLでは引数,page=%dでページが送れる
・ページ内のバックアップ単位はdiv要素とclass属性の値で指定できる.
・同div要素にはidがありバックアップが取りたい単位に対して一意である.
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int i, ic, j= 1;
do {
if (j>1)
[NSThread sleepForTimeInterval:30];
NSString *urlString= [NSString stringWithFormat:@"http://hoge.net/user/hoge?page=%d", j++];
NSURL *url = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:url];
NSXMLDocument *document = [[[NSXMLDocument alloc] initWithData:data
options:NSXMLDocumentTidyHTML
error:NULL] autorelease];
NSError *error= nil;
NSArray *nodes = [document nodesForXPath:@"//div[@class='hoge']"
error:&error];
if (error!=nil) {
NSLog(@"%@", error);
break;
}
ic= [nodes count];
for(i= 0;i<ic;i++){
NSError *err= nil;
NSXMLElement *elem= [nodes objectAtIndex:i];
NSString *idString= [[elem attributeForName:@"id"] stringValue];
NSString *content= [elem XMLStringWithOptions:(NSXMLNodePrettyPrint|NSXMLNodeCompactEmptyElement)];
NSMutableString *outputString= [NSMutableString stringWithString:@"<html>"];
[outputString appendString:@"<head>"];
[outputString appendString:@"<meta http-equiv='Content-Type' content='text/html; charset=utf-8'/>"];
[outputString appendString:@"<base href='http://hoge.net/'>"];
[outputString appendString:@"</head>"];
[outputString appendFormat:@"<body>\n%@\n</body>", content];
[outputString appendString:@"</html>"];
[outputString writeToFile:[NSString stringWithFormat:@"/path/to/backup/%@.html", idString]
atomically:YES
encoding:NSUTF8StringEncoding
error:&err];
if (err!=nil) {
NSLog(@"%@", err);
break;
}
}
} while (ic>0);
[pool drain];
return 0;
}
気がついたこと
divのclassの値の末尾に空白が並んでいるサイトであったがこの空白はXPathで指定する際は削ってあげないと一致として扱われなかった.
2010年7月6日火曜日
(色々決め打ちだけど,まずは)ARTK_MMDのMMD再生ライブラリ部をQCパッチでやってみた.
追記(2010/12/20): 公開しました.こちら
追記(2010/12/13): ARTK_MMDのサイトが引っ越されていました.こちら
NyMMDはJavaだがオリジナルのARTK_MMDはC++なのでARTK_MMDのMMD再生ライブラリ部をQuartz Composer Custom Patchでできないか?と思いあれこれやってみて,現在こんな感じ.
(ARTK_MMD, NyMMDの作者様に感謝)
(pmd: '初音ミク'(MMD添付モデル),vmd: '【MMD】みくみくにしてあげる♪【してやんよ】【Project DIVA】' 感謝)
パッチっぽく(決め打ちでなく,portやパネルでパラメタ指定)できたら公開してみたい.
ラベル:
ARTK_MMD,
Cocoa,
MMD,
Quartz Composer
登録:
投稿 (Atom)














