ApplescriptObjC
dj bazzie wazzie op 24 december 2010 #
Ik zie dat hier op OMT veel over Objective-C bridges is gepraat maar niet over applescriptObjC ook wel ASOC genoemd.
Zelf ben ik hier sinds een paar dagen mee aan de slag gegaan en moet zeggen dat het boven verwachting functioneerd. Je hebt nu de mogelijkheid om alle functies in cocoa te gebruiken maar ook alle andere en third party framworks te gebruiken. Objective-C classes kan je aanroepen en dat nu allemaal zonder call method functies dat een beetje onhandig was. ASOC word mogelijk gemaakt door het ApplescriptObjC.framework dat er voor zorgt dat je volledige cocoa applicaties kan schrijven met applescript. Het jammere is dat veel gebruikers hiermee tot op vandaag moeite mee hebben die vanuit applescript komen. Objective-C programmeurs (kennen het cocoa framework beter) gaan veel makkelijker van start met deze nieuwe manier van Applescript applicaties te maken. Apple geeft heel weinig documentatie en verwijst naar het cocoa framework om daarin te kijken hoe je je applicatie schrijft.
Meestal bij alle voordelen komt er meestal ook wel minimaal 1 nadeel en dat klopt. Het idee van prototyping dat je had in Applescript-Studio is nu wel weg. AS-Studio was altijd een geweldig iets voor simpele applicaties en het maken van prototypes. Wanneer de klant het programma goed vond programmeer je het opnieuw in Objective-C. In ASOC neemt de tijd toe dus het maken van prototypes zit er niet echt meer bij. Persoonlijk denk ik zelfs dat de ontwikkelingstijd van een applicaties in ASOC zoveel heeft toegenomen t.o.v. AS-Studio dat de ontwikkelingstijd dichter bij Objective-C zit dan AS-Studio.
De code en de constructie is wel compleet anders. In AS-Studio moet je objecten in je interace een applescript naam geven (indien je deze wil aanroepen vanuit je code). Nu maak, je net als in Objective-C, een class aan en die gebruik je in je interface en maak je connections met de outlets en actions.
Misschien dat dit niet helemaal een bridge is moet ik wel zeggen dat het beter werkt dan andere bridges die ik gezien heb. Omdat alles gewoon is aan te roepen en mee te werken
Misschien dat iemand anders hier nog wat aan toe te voegen heeft
dj bazzie wazzie op 24 december 2010 #
Even een verschil qua laden van een nib file bij starten van een applicatie. De nib file heeft een window die niet visible is bij het launch
AS-Studio
on lauched theObject
load nib "aNib"
set visible of window "windowname" to true
end launched
ASOC
on applicationWillFinishLaunching_(aNotification)
set aWindowManager to current application's class "NSWindowController"'s alloc()'s initWithWindowNibName_("aNib")
aWindowManager's showWindow_(me)
end applicationWillFinishLaunching_
dj bazzie wazzie op 30 november 2011 #
Een jaartje later:
Hoeveel ik geschreven heb in AppleScriptObjC valt op zich nog wel tegen (misschien een keer 30 classes). Maar in tegenstelling tot Studio helemaal bug vrij. Daarbij krijg ik als feedback van de gebruikers de de nieuwe applicaties veel responser aanvoelen door de hogere snelheid terwijl studio applicaties een beetje aanvoelden als slecht geschreven Java applicaties.
Ik heb inmiddels ook een tweede nadeel gevonden, je kan een AppleScriptObjC class alloceren vanuit een appleScriptObjC class alleen dit gaat maar 2 levels diep. Moet het per se zal je hiertussen een Objective-C object moeten zetten als brug wat erg lelijk is.
Ook ben ik heel af en toe wel eens een ongebruikelijke vertaling van missing value tegen gekomen. Het AppleScriptObjC framework zal nil altijd goed omzetten naar missing value object maar NSNull zal niet altijd goed gaan.
Een groot voordeel is dat eindelijk threading nu ook mogelijk is wat in Studio een ramp was. Studio was gebouwd dat alles via de main thread liep en grote buggy workarounds moesten gedaan worden. multi processing om precies te zijn om meerdere acties tegelijk uit te voeren.
Willemien op 01 december 2011 #
Objective-C heeft veel voordelen t.o.v. AppleScriptObjC. Heb je het ook weleens andersom geprobeerd, dus Objective-C met Scripting Bridge?
dj bazzie wazzie op 02 december 2011 #
Scripting bridge is ook gewoon met en zelfs naast AppleScriptObjC te gebruiken (beetje overkill, maar het kan). Probleem is echter wel dat veel programma's niet werken met scripting bridge omdat de sdef files niet helemaal deugen van veel third party software.
Het Enige echte nadeel van AppleScriptObjC is dat de veelzijdigheid er ook voor kan zorgen dat je slechte programma's schrijft door bijvoorbeeld teveel AppleScript objecten te gebruiken en onnodige coercions uitvoeren (zoals in voorbeeld onder). Maar goed dit dropt alleen heel erg je performance, niet je veelzijdigheid. Dus ik snap de vele voordelen van Objective-C t.o.v. AppleScriptObjC opmerking niet zo goed.
Bijvoorbeeld: Wanneer je de waarde van een NSTextField naar een andere wil verplaatsen kan je dit in AppleScriptObjC op meerder manieren doen.
set myString to firstfield's stringValue() as string
secondfield's setStringValue_(myString)
Het probleem is dat je een dubbele coercion uitvoerd waardoor eerst een NSString naar een AppleScript text object moet worden omgezet en vervolgens in de stack geplaatst moet worden. Dan moet bij het tweede commanda aan de stack myString worden opgevraagd en weer opnieuw gealloceerd moet worden naar een NSString (dit doet het AppleScriptObjC framework). Nu is de performance drop niet noemenswaardig maar wel als het heel vaak herhaalt wordt. Dit kan je oplossen door 'as string' te verwijderen waardoor myString de pointer wordt die gereturned wordt door stringValue() method.
Je zou zelfs kunnen zeggen:
secondfield's setStringValue_(firstfield's stringValue())
Wat de mooiste oplossing is, omdat deze code niet door AppleScript wordt geïnterpreteerd maar direct door Objective-C/Cocoa.
Willemien op 02 december 2011 #
Dat de AppleScript-woordenboeken vaak niet deugen dat heb ik ook gemerkt, dat is altijd zo geweest. Het is lastig om ze goed te maken. Ook de woordenboeken van Apple zijn niet perfect maar iTunes en Safari zijn niet zo groot en nog wel te doen. Scripting Bridge heeft ook zo z'n nukken en kuren.
"Objective-C heeft veel voordelen t.o.v. AppleScriptObjC" zeg ik bij nader inzien verkeerd. Objective-C heeft als taal voordelen boven AppleScriptObjC maar dat geldt andersom ook. Ik bedoel dat programmeren in Objective-C veel voordelen heeft omdat Objective-C veel beter door Xcode wordt ondersteund:
Er is een Debugger, dit is een heel groot voordeel.
Draait (en test) sneller.
Betere errors, tijdens build en run.
Build haalt er meer fouten uit.
Fix and Continue.
De Cocoa-documentatie en -voorbeelden van Apple zijn in Objective-C.
Handigheidjes in Xcode (3) zoals Balance {}, Command-dubbelklik, Option-Command-dubbelklik, Refactor, Build and Analyze.
Ik ben nieuwsgierig, kan het volgende in AppleScriptObjC?:
C-libraries gebruiken.
Core Data.
Een method gebruiken die een Block als parameter heeft.
In Objective-C een AppleScriptObjC-class gebruiken.
dj bazzie wazzie op 02 december 2011 #
Dan zitten we op dezelfde golflengte
... Ik dacht dat ik nog misschien dingen over het hoofd zag. Het zijn inderdaad exact de dingen die je noemde waarin AppleScriptObjC echt achter Objective-C aan loopt. Kom die problemen ook veel tegen zoals gebruikers die geen idee hebben wat ze fout doen omdat er niets wordt gemeld in de console en toch een button reageert niet.
Cocoa bindings zijn ook eenvoudig aan te maken wat voor een AppleScripter ook wel iets nieuws is. in AppleScriptObjC moet je dan ook niet proberen data sources aan te maken maar gebruik maken van late bindings.
C libraries is niet te doen, echter kan je wel bepaalde C structs doorsturen en ontvangen zoals het aanmaken van NSRect gewoon {x, y} is waarbij x en y integers zijn. Dit wordt door AppleScriptObjC framework omgezet naar een struct. Verder zijn tot nu toe alle frameworks (Zowel van Apple als third party developers) te gebruiken. Ik heb nog geen core data gebruikt maar moet wel lukken denk ik.
Blocks als parameters heb ik niet gebruikt dus zou ik ook echt niet weten of dat wel of niet lukt.
Als laatste kan je zeker Objective-C en AppleScrtiptObjC classes mengen alleen is er 1 nadeel. Je kan in AppleScriptObjC een appleScriptObjC class alloceren maar die class mag niet nog een AppleScriptObjC class alloceren. Zelf zijn mijn programma's voor meer dan 90% Objective-C en alleen wat handiger is in AppleScript doe ik in een AppleScriptObjC class. Let wel op dat de compiler, die geen AppleScriptObjC kent, een compiler warning geeft wanneer je vanuit Objective-C een AppleScriptObjC wil inladen.
Willemien op 08 december 2011 #
Blocks is een uitbreiding van Apple op C en dus Objective-C. Nieuwe methods hebben een block als callback i.p.v. een method. Zo is bij NSSavePanel
- (void)beginSheetForDirectory:(NSString *)path file:(NSString *)name modalForWindow:(NSWindow *)docWindow modalDelegate:(id)modalDelegate didEndSelector:(SEL)didEndSelector contextInfo:(void *)contextInfo
vervangen door
- (void)beginSheetModalForWindow:(NSWindow *)window completionHandler:(void (^)(NSInteger result))handler
Tenzij Apple AppleScript uitbreidt met blocks wordt dit een probleem.
Core Data kan worden gebruikt met AppleScriptObjC maar een subclass van NSManagedObject lukt niet.
Ik ben aan het experimenteren geweest en heb via Scripting Bridge en AppleScriptObjC uit iTunes gegevens opgehaald. In het kort: ik liep meteen tegen fouten in de dictionary van iTunes aan, de warnings van de compiler heb ik weggewerkt met een protocol en ik zit af en toe in de verkeerde taal te typen.
Over het aanroepen van AppleScriptObjC vanuit Objective-C heb ik een paar vragen:
Hoe roep in vanuit Objective-C een stukje AppleScriptObjC aan, of hoe kom ik aan het AppleScriptObjC-object? Ik doe nu NSAllocateObject(NSClassFromString(@"testclass"), 0, NULL); Een alternatief is het object in een nib stoppen. Is er nog een andere manier?
Als ik vanuit Objective-C een AppleScriptObjC-method aanroep dan worden de types van de parameters automatisch geconverteerd maar het resultaat niet of alleen het buitenste object. Ik krijg een (array van) NSAppleEventDescriptor terug en ik moet in AppleScriptObjC zorgen dat ik alleen Objective-C-types of iets KVC ccompliants teruggeef. Is daar een handige manier voor of moet ik zelf alles omzetten naar NSArray, NSDictionary enz.
Je zegt dat je in AppleScriptObjC een AppleScriptObjC class kan alloceren maar in die class niet nog een AppleScriptObjC class mag alloceren. Ik heb dit geprobeerd en bij mij werkt het gewoon. Ik denk ook niet dat daar een niveau wordt bijgehouden of dat wordt bijgehouden waar een object is gealloceerd. Gaat er misschien iets anders mis?
dj bazzie wazzie op 12 december 2011 #
Ik gebruik zelf ook gewoon NSClassFromString maar niet NSAllocateObject
//protocol file
@protocol appleScriptClassProtocol <NSObject>
- (NSString *) stringValue;
- (NSNumber *) numberValue;
- (id) alloc;
@end
//Objective-C
.....
id <appleScriptClassProtocol> myAppleScript;
id <appleScriptClassProtocol> instanceOfMyAppleScript;
myAppleScript = (id <appleScriptClassProtocol>) NSClassFromString(@"appleScriptClass");
instanceOfMyAppleScript = [[myAppleScript alloc] init];
NSLog(@"%@", [myAppleScript stringValue]);
NSLog(@"%@", ([[myAppleScript numberValue] boolValue] ? @"YES" : @"NO"));
NSLog(@"%@", [myAppleScript numberValue]);
.....
--AppleScript
property NSNumber : class "NSNumber"
script appleScriptClass
property parent : class "NSObject"
property __integer : 1250
on stringValue()
return __integer as string
end
on numberValue()
return NSNumber's numberWithInteger_(__integer)
end numberValue
end script
Ik snap je vraag niet echt betreft de return waarden van methods. Wanneer ik een text object return vanuit AppleScriptObjC wordt deze omgezet naar een NSCFString object. Lists worden omgezet naar NSCFArrays, records worden omgezet naar NSCFDictionary. Integers, reals en numbers moeten eerst naar een NSNumber object worden omgezet. Dit heeft te maken dat AppleScript bij integers groter dan (2 ^ 31) - 1 niet meer als integer functioneren maar het getal wordt omgezet. Het AppleScriptObjC framework vangt dit op en daarom kan je beter NSNumbers returnen.
Het is ook niet zo dat AppleScriptObjC een error erin gooit wanneer je een AppleScriptObjC class in een AppleScriptObjC class in een appleScriptObjC class aanmaakt. De problemen zit hem in de focus/target van het script. Me, my en it zijn onjuist andere objecten zijn onbereikbaar waardoor het eigenlijk een geisoleerd object wordt.
Willemien op 13 december 2011 #
Toch denk ik nog steeds dat AppleScriptObjC, de Objective-C runtime of iets anders niet bijhoudt hoe diep je in classes zit. Het klinkt een beetje alsof een object is gereleased en daardoor zichzelf kwijt is. Ik geloof wel dat er iets fout gaat maar vraag me af of de plek waar het object is aangemaakt de oorzaak is.
moet
id <appleScriptClassProtocol> myAppleScript;
niet zijn
Class myAppleScript;
- (id) alloc; hoeft dan niet in het protocol te zitten, het hoort daar ook eigenlijk niet.
ik heb nu
[[NSClassFromString(@"testclass") alloc] init];
dat vind ik mooier dan
NSAllocateObject(NSClassFromString(@"testclass"), 0, NULL);
ik was init vergeten, het werkt wel zonder init, dat doet blijkbaar niks.
Mijn method geeft een array met iTunes tracks terug als NSArray met NSAppleEventDescriptors. Daar kan ik niet veel mee. Ik moet in AppleScriptObjC de tracks converteren naar Objective-C classes of types die automatisch worden geconverteerd. Waarschijnlijk is het handiger om alles met de tracks in AppleScriptObjC te doen maar daar zie ik nogal tegenop. Ik ga nog wat meer nadenken en overwegen waar ik mee ga worstelen, AppleScriptObjC of Scripting Bridge.
dankjewel
dj bazzie wazzie op 14 december 2011 #
Protocol is eigenlijk helemaal niet nodig maar omdat het object nog niet bestaat bij het compileren maak ik een protocol aan. AppleScript classes worden vlak voordat het NSApplication object wordt aangemaakt (NSApplicationMain functie in de main.m file) uitgelezen en worden objective-C classes aangemaakt. En als tweede reden gebruik ik protocol voor de code completion. '- (id) alloc' zet ik er alleen maar in zodat ik geen compiler warning krijg, het heeft inderdaad geen betekenis.
Ik gebruik id <protocol> myClass om de redenen in de bovengenoemde alinea;
Ik ken het probleem wel met NSAppleEventDescriptors maar op zich moet het wel makkelijk te verhelpen zijn (het kan inderdaad niet altijd). Bijvoobeeld:
on getProcesses()
tell application "System Events" to return every process
end
deze functie zal een array met event descriptors terug sturen zoals je al zei maar als je zou zeggen:
on getProcesses()
tell application "System Events" to return name of every process
end
krijg je netjes een array met allemaal strings. Dus sommige dingen zijn wel makkelijk aan te passen. Je hebt ook het probleem met records dat eigenlijk vrij voor de hand ligt. Als ik bijvoorbeeld de properties van een process van system events opvraag krijgt ik wel een record class maar dit is geen 'plain' record. ten eerste zijn keys met spaties in AppleScript niet mogelijk dus een property als 'unix id' van een process kan eigenlijk niet in een record. Daarom kan een record met zo'n waarde niet gereturned worden. Deze properties/keys moeten worden omgezet. Je kan eigenlijk alleen records returnen die ook gebruikt kunnen worden in current application. Voorgedefinieerde woorden als name, id, enabled, visible, title etc... zijn geen probleem zolang de key maar uit 1 woord bestaat.
Willemien op 14 december 2011 #
Ik bedoel niet dat het protocol niet nodig is maar dat er een foutje in het voorbeeld zit, er wordt iets van type Class aan myAppleScript toegekend. Volgens mij moet het zijn://protocol file
@protocol appleScriptClassProtocol <NSObject>
- (NSString *) stringValue;
- (NSNumber *) numberValue;
@end
//Objective-C
.....
Class myAppleScript;
id <appleScriptClassProtocol> instanceOfMyAppleScript;
myAppleScript = NSClassFromString(@"appleScriptClass");
instanceOfMyAppleScript = [[myAppleScript alloc] init];
enz.
Op deze manier krijg je geen warning. -alloc hoort er ook niet in omdat +alloc wordt gebruikt.
Advertentie
Je kunt alleen reageren met een gratis OMT account.
Log in of registreer.
Inloggen
Over dit topic
Gestart op 24 december 2010 door dj bazzie wazzie
Laatste reactie door dj bazzie wazzie
Reageer op dit topic