MacRuby와 함께 OS X 서비스를 작성하고 있습니다. 선택한 텍스트를 돋보이게합니다. 그것은 대부분 아니라, 여기의 전부 ... 작동하지만 :기초 도구 OS X 서비스, 가비지 콜렉션, MacRuby : 왜 NSRunLoop은 acceptInputForMode에서 루프되지 않습니다 : beforeDate :?
#!/usr/local/bin/macruby
# encoding: UTF-8
framework 'Foundation'
framework 'AppKit'
class KCUpcase
def upcase(pasteboard, userData: s_userdata, error: s_error)
incoming_string = pasteboard.stringForType "public.utf8-plain-text"
outgoing_string = incoming_string.upcase
pasteboard.clearContents
pasteboard.setString(outgoing_string, forType: "public.utf8-plain-text")
end
end
NSLog "Starting…"
NSRegisterServicesProvider(KCUpcase.new, "Upcase")
NSLog "Registered…"
NSRunLoop.currentRunLoop\
.acceptInputForMode(NSDefaultRunLoopMode,
beforeDate:NSDate.dateWithTimeIntervalSinceNow(10.0))
NSLog "Done."
그것은 단지 재단 툴, 응용 프로그램의 일부입니다.
이제 NSRunLoop…
라인을 참조하십시오. 그것은 실제로 작동하지 않습니다. 프로그램은 즉시 종료됩니다. 루프가 한 번 실행 된 다음 종료됩니다. 사실, 입력을 위해 10 초를 기다리지 않아도된다는 사실입니다.
NSRunLoop.currentRunLoop.runUntilDate NSDate.dateWithTimeIntervalSinceNow(60.0)
을 그리고 그것은 작동하지만, 자연스럽게 프로그램이 60 주변에 스틱, 그리고 그것은 kludge입니다 : 그래서, 여기에 내가 대신 무슨 짓을했는지. 그래서 Objective C (KCUpcase 포함, 표시되지 않음)에서 모든 것을 구현했습니다. 그리고 ... 작동합니다. 수동 메모리 관리. GC (-fobjc-gc-only
)로 전환하면 MacRuby 버전과 똑같이 종료됩니다.
#import <Foundation/Foundation.h>
#import "KCUpcase.h"
int main (int argc, const char * argv[]) {
NSLog(@"Starting…");
NSRegisterServicesProvider([[KCUpcase alloc] init], @"KCUpcase");
NSLog(@"Registered…");
[[NSRunLoop currentRunLoop]
acceptInputForMode:NSDefaultRunLoopMode
beforeDate:[NSDate dateWithTimeIntervalSinceNow:10.0]];
NSLog(@"Done.");
return 0;
}
는하지만, 슬프게도, 수정은 간단합니다 :이 재단 도구 (아닌 NSApplication)이 있기 때문에, 내가 objc_startCollectorThread
를 호출하여 수동으로 GC를 시작해야 할 것 같다. 여기 :
#import <objc/objc-auto.h>
// ...
NSLog(@"Starting…");
objc_startCollectorThread();
NSRegisterServicesProvider([[KCUpcase alloc] init], @"KCUpcase");
// ...
좋아,하지만 MacRuby과 무슨 일이야? 다시는 루프에서 대기 아니에요,
#import <MacRuby/MacRuby.h>
// ...
NSLog(@"Starting…");
objc_startCollectorThread(); // This magic stops working once we add MacRuby
[[MacRuby sharedRuntime] evaluateString: @"$stderr.puts 'hi from macruby'"];
NSRegisterServicesProvider([[KCUpcase alloc] init], @"KCUpcase");
// ...
을 그리고 :의 믹스에 던져 보자. 그리고, 다시, acceptInputForMode:beforeDate:
작품 대신 runUntilDate:
kludge을 ussing :
NSLog(@"Starting…");
[[MacRuby sharedRuntime] evaluateString: @"$stderr.puts 'hi from macruby'"];
NSRegisterServicesProvider([[KCUpcase alloc] init], @"KCUpcase");
NSLog(@"Registered…");
// Hmmm…
[[NSRunLoop currentRunLoop]
runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]];
NSLog(@"Done.");
return 0;
그래서, 내가 정말 뭔가를 분명 누락 가정합니다. 제발 저를 계몽하십시오.
그리고 그런데은 프로젝트의 전체 MacRuby 버전을 구축하고 ~/Library/Services
에 설치거야 레이크 작업과 here (download) 사용할 수 있습니다. 그런 다음 키보드 환경 설정 창에서 서비스에서 해당 확인란을 선택해야합니다 (한 번).
(또는 git clone git://gist.github.com/537075.git
)을 제외하고
는 : 흥미롭게도, 나는 MacRuby 문자열 내부 NSLog
를 호출했는데, 그것은 NoMethodError
을 올렸다. 뭐라 구요?
main에서 서비스 개체에 대한 참조를 유지 관리하는 경우 Objective-C 버전이 가비지 수집에서 작동합니까? 즉 지역 변수를 사용합니까? – JeremyP
위와 같은 결과를 얻었습니다 : acceptInputForMode ...를 사용할 때 종료되고 runUntilDate에 대해 정상적으로 실행됩니다. – kch
어떤 이유로 든 실행 루프에 입력 소스가 없다고 생각합니다. – JeremyP