8 ms·
Shell Scripting with Objective-C
- zrail 12y agoOk, `NSImage initWithContentsOfURL` is awesome. I haven't ever done much GUI coding, is that a standard type of thing in GUI toolkits? (also, the pedant in me would like to point out that this is not "shell scripting" as you're not scripting a shell, but it's super cool regardless)
- melling 12y agoShell scripting usually means writing in your shells (e.g sb, csh, zsh) native script. The author is using it to mean small scripts that he runs in a shell, which is fine with me. I'm starting to use Go for these sorts of things because it's really fast. I'd try objc but if I want to move my programs to a Linux server, I'm out of luck.
- wtallis 12y agoYou're not out of luck when it comes to using objc on linux, you just have to forgo a lot of the newer APIs. But if you're using it on a server, chances are you won't miss the GUI APIs that GNUstep lacks.
- mrsteveman1 12y agoIndeed, I had an entire server blog engine written in objc, I had it running quite well on a Mac VPS (Lion running on vmware on Xserves), that I intended to move over to a Linode. But I wanted libdispatch, blocks, all the stuff in the newer objc runtime, etc. Back then that meant playing all sorts of games compiling a specific objc runtime (there's more than one outside of apple), in a specific order with other things from GNUstep, using clang at certain steps instead of gcc to compile it all. It was a mess, but if I had really wanted to I probably could have pulled it off, and now I'm sure things have improved. I moved the entire thing to python and forgot about it though. But I've always liked the idea of writing little things that have no GUI of any kind in objc, I wrote a few commandline utilities in objc and loved it. Background services on the system (mac or linux either one) would be fun too I think.
- 21echoes 12y agoTo be a bit pedantic: NSImage isn't part of a GUI toolkit -- don't confuse NSImage with UIImageView! The NSImage is more equivalent to a .png, not to a web <img> tag; it's completely separate from a framework for routing data to the screen.
- demallien 12y agoAre you sure about that? I'm pretty sure that it's NSImage that holds the actual pixmap, which definitely makes it part of the GUI stack.
- Moto7451 12y agoNSImage is part of AppKit and while it is definitely key to a lot of UI code that's because of well thought out delegation rather than it being part of UIKit or CocoaTouch. It would be pretty annoying to have two different and possibly incompatible NSImage classes to deal with if it lived in each platform's UI framework.
- DHowett 12y agoUnfortunately, UIKit doesn't use the well-thought-out NSImage class, opting instead to reimplement it by way of UIImage. In this case, the GP is correct: NSImage is part of the UI toolkit (AppKit); it is not a core API exposed by, say, Foundation.
- js2 12y agoAuthor could combine both worlds with pyobjc. Might be interesting to add that as a comparison.
- jicea 12y agoHmmm, I didn't know pyobjc at all, sounds very cool: power of Cocoa with expressiveness of Python!
- callesgg 12y agoPersonally I find the objective c stuff to take longer to read and understand just because there is allot more text.
- callesgg 12y agoNice.. getting down votes for saying that objective c is more verbose than Python. Most function names are longer and that is the way it is.
- fyolnish 12y agoyou miss the point
- natch 12y agoWhat is going on in the below line? c = [t v] Can you tell me what c represents, and where it got its value? Sure, from [t v], but what are those? No, you can't. You finished reading it really quickly, but you understand very little about what is going on. "A lot more text" is there for a reason: to explain what is going on. How about: cellsToUpdate = [tableView visibleCells] This code tells you exactly what each item means. I find clear naming really nice to work with. Not that I would necessarily use exactly that line as a way of doing things, but hopefully you get the idea.
- deleted 12y ago[deleted]
- shadesandcolour 12y agoI like Objective-C a whole lot, but this is a shitty example. You didn't show what "a lot more text" looks like, you showed everyone what "proper variable names" look like.
- ant_sz 12y agoThe objective-c with ARC support really enjoys some advantages script programing languages enjoy. Apple added many syntax sugar such as `@[]` to build array and `@{}` to build dictionary, which makes it easy to write. So I am not surprised someone is trying to use it as a so-called shell script. The cocoa frameworks really contains a lot of convenient API (ex. when it comes to python, you have to install PIL or something else to process images). But on the other hand the objective-c shell scripting can not be used on platform other than OSX. That is a disadvantage.
- jicea 12y agoHi author here! It was more a play experiment than a true try to replace Python/Ruby/Go scripting. I was very intrigued by "Objective-C Minimalism" http://bou.io/ObjectiveC-Minimalism.html http://bou.io/ObjectiveC-Minimalism.html and wanted to see what would be scripting in Objective-C with all new features (Objects literals, ARC etc...)
- mpweiher 12y agoQuick correction: the object literal syntax is independent of ARC.
- danra 12y agoCringed when opening the link, expecting to find AppleScript. Things turned out better than expected!
- gatehouse 12y agoDecided to give it a shot in bash. #!/bin/bash set -eu curl -s "https://raw.githubusercontent.com/manbolo/appicon/master/mask.png" >"icon_mask.png" for app_id in "$@" do metadata=$(curl -s "http://itunes.apple.com/us/lookup?id=$app_id") icon_url=$(echo $metadata | jq -r ".results[0].artworkUrl512") name=$(echo $metadata | jq -r ".results[0].trackCensoredName") icon_base="icon_$name" curl -s "$icon_url" >"$icon_base.png" convert "$icon_base.png" "icon_mask.png" -compose copy-opacity -composite "$icon_base.png" for size in 1024 512 120 114 60 57 do convert "$icon_base.png" -resize "${size}x${size}" "${icon_base}_${size}x${size}.png" done done rm icon_mask.png Run like ./appicon.bash 400274934 598581396 Notes - didn't replicate the slugify - dependencies: imagemagick, jq - here without spaces: http://pastebin.com/yBPwHwdk http://pastebin.com/yBPwHwdk - to get the same clarity as the python & Obj-C samples, I'd probably be approaching the same length.
- yesbabyyes 12y agoYou could easily make a quick slugify with `tr`: 10a11 > name=$(echo $name | tr -cd '[:blank:][:alnum:]' | tr -s '[:blank:]' '-' | tr '[:upper:]' '[:lower:]')
- jicea 12y agoAuthor here, the bash version is too beautiful: compact and clean! I will include it in the article if you're ok!
- gatehouse 12y agoSure.
- js2 12y agoYou may be able to use sips instead of imagemagick.
- bshimmin 12y agoThis bit about summed it up for me: "You can say that [NSJSONSerialization JSONObjectWithData:resultsData options:0 error:nil]; is more verbose than r.json() but verbosity is an Objective-C convention, for the better or the wors[e]" For this sort of task, like one of the other commenters, I would almost certainly write something quick and simple (and fairly unstructured) in bash; if it needed to be more maintainable, I'd write it in Ruby. Using a verbose, static typed language just seems wrong here. Of course, for any given programmer and any given task, using the language with which they are most familiar is often a very good option (obviously only in circumstances where it is possible to perform the task in that language and its specific attributes don't jeopardise the successful running of the task).
- mpweiher 12y agoThis is very cool! The amount of functionality in modern application frameworks like Cocoa is really amazing, and it is a shame that it tends to be ignored/inaccessible for scripting tasks. Here is an implementation in Objective-Smalltalk (http://objective.st http://objective.st): #!/usr/bin/env stsh #-<void>processIconForApp:appId framework:AppKit load. framework:EGOS_Cocoa load. nonChars := NSCharacterSet letterCharacterSet invertedSet. str := '_'. [ :self | ((self componentsSeparatedByCharactersInSet:nonChars) componentsJoinedByString:str) lowercaseStri ] installInClass: NSString withMethodHeaderString:'slugString'. mask := http://raw.githubusercontent.com/manbolo/appicon/master/maskInverted.png. appInfo := ref:http://itunes.apple.com/us/lookup getWithArgs id: appId iconURL := var:appInfo/results/0/artworkUrl512. name := var:appInfo/results/0/trackCensoredName. icon := context evaluateScriptString: iconURL. #(1024 512 120 114 60 57 ) do:[ :width | c := MPWCGBitmapContext rgbBitmapContext: width @ width. c scale: width / icon pixelsWide. c maskedBy:mask draw:[ :aContext | aContext drawImage:icon. ]. scaled := c image. outname := name slugString ,'_', width stringValue, '_', width stringValue , '_.png'. file:{outname} := scaled representationUsingType:4 properties:nil. ]. This processes a single icon per call. The only dependency apart from AppKit (and obviously Objective-Smalltalk) is MPWDrawingContext, which I load via EGOS_Cocoa.