I decided to play around with node.js, specifically with node-webkit.
Node-webkit allows programmers to write desktop-apps with Javascript, and even package them for distribution, for example via the Mac App Store. (Check out this list of apps written with it.)
To play with it, I’ve decided to write a tiny thesaurus-app.
It should lookup and display synonyms and related words using a (German) thesaurus via the JSON-API at openthesaurus.de.
To be really useful, it should be possible to bring the app to the foreground using a keyboard shortcut. In my case it’s Shift+Alt+T.
It should be possible to dismiss the app by tapping ESC
It worked quite nicely. The app doesn’t really feel like a web-app, even though it utilizes web-app technologies. And I could even create a binary for the App Store.
# this is about http://en.wikipedia.org/wiki/Monty_Hall_problem
num_rounds = 5000
num_correct_guesses_keep = 0
num_correct_guesses_switch = 0
num_rounds.times do
doors = [false, false, false]
doors[rand(3)] = true# first pick = random
player_pick = rand(3)
show_bad_door = doors.index(true)
# show a bad door that is not the price_door and not player's pickwhile (doors[show_bad_door] || show_bad_door == player_pick)
show_bad_door = rand(3)
end# second pick, player choses to switch to the other door
remaining_doors = [0, 1, 2]
remaining_doors.delete(show_bad_door)
remaining_doors.delete(player_pick)
player_switch_pick = remaining_doors.first
win = if doors[player_pick]
num_correct_guesses_keep += 1"yes"else"no"end
win_switch = if doors[player_switch_pick]
num_correct_guesses_switch += 1"yes"else"no"end
puts "doors: #{doors}, show_bad_door: #{show_bad_door}, "\
"player keeps: #{player_pick}, player wins: #{win}, "\
"player wins if he switches: #{win_switch}"end
win_ratio = ( num_correct_guesses_keep.to_f / num_rounds.to_f * 100.to_f ).round(2)
win_ratio_pick = ( num_correct_guesses_switch.to_f / num_rounds.to_f * 100.to_f ).round(2)
puts "correct: #{num_correct_guesses_keep}, correct-switch: #{num_correct_guesses_switch}, "\
"win-ratio: #{win_ratio}%, win-ratio switch: #{win_ratio_pick}%"
Switching really doubles the probability to win. Dang it. ;)
I’ve just uploaded my new app. It is called “Zones” and it’s one of those desktop helper tools for Mac OS X. You can take a look at Zones here.
It was fun to do and I learned a bunch of stuff about Mac OS X. It was probably also the last side-project ever written in Objective-C for me, since the Apple world is switching to Swift now. (Which is good.)
Sadly, I cannot distribute the app through the AppStore, because it cannot be sandboxed using the APIs it does (Accessibility). Which means I will probably never earn enough money to buy a happy meal with it.
I had a UIPageViewController in scrolling-mode that would allow to pan between view-controllers using a finger gesture. However, I wanted to restrict the panning area to a certain area of the screen, for example as shown in this screenshot:
I do it by subclassing the UIPageViewController, finding its UIScrollView, and adding a new UIPanGestureRecognizer to that scrollView.
I set my subclassed UIPageViewController to be the delegate of that new UIPanGestureRegognizer. I then implement two delegate methods:
In the last override I decide if I want to “eat the event” (reply YES) or if I want the original UIPanGestureViewRecognizer of the UIScrollView to handle it (reply NO). So, the YES-reply means the UIPageViewController will not scroll to the next ViewController.
Here are two code snippets for rotating and resizing UIImage’s without using UIGraphicsBeginImageContext(), because it is not thread-safe and can lead to weird behavior.
In my case the camera-preview when taking a picture in an app I was writing, turned black from time to time. The problem was that I was rotating and resizing the images using UIGraphicsBeginImageContext().
Here’s some code I’ve found and tweaked to resize images:
This kept me busy for a while until I found a super simple way to do it: In this tutorial/code-snippet I’ll show you how to write an image-cropper for your iPhone-app.
What do I mean by image-cropper?
Bascially, it’s about giving your users a simple way to select part of an image using pan and pinch gestures. This can be handy when they upload a profile picture or something similar.
Here’s the end result:
How it’s done:
There is one UIScrollView with a large contentSize. Embedded in the scroll-view is a UIView (baseView). And embedded in the baseView is the UIImageView with the Ferrari-picture.
The yellow boxes in the above image represent the iPhone screen and the cropping area.
Because the contentSize is bigger than the bounds of the screen (= frame of _scrollView), the user can pan to select the desired image. Because minimumZoomScale and maximumZoomScale are set, the user can pinch to zoom. (Although I am not sure why it helps to set the initial zoomScale after all other initialization. If it’s done earlier it won’t scroll until zoomed.)
The actual cropping is done by rendering the contents of the view-controller’s view into an ImageContext and then cutting out the portion that (here: roughly) corresponds to the non-dimmed “window” in the center.
The image is then saved to the phone’s photo gallery.
Here’s the actual cropping code that is executed when you tap the “OK”-button.
- (void)pickResult:(id)sender // ehm.. not sure why I needed sender here.. ;)
{
// some visual feedback a.k.a. special effects:
_acceptButton.enabled = NO;
_specialEffectsView.alpha = 1.0f;
[UIView animateWithDuration:1.0f animations:^{
_specialEffectsView.alpha = 0;
} completion:^(BOOL finished) {
_infoLabel.alpha = 1.0f;
[UIView animateWithDuration:1.0f animations:^{
_infoLabel.alpha = 0;
_acceptButton.enabled = YES;
}];
}];
// 1. hide stencil overlay
_stencilView.hidden = YES;
// 2. take a screenshot of the whole screen
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// 3. pick interesting area and crop
CGImageRef imageRef = CGImageCreateWithImageInRect([screenshot CGImage],
CGRectMake(35.0f, 159.0f, 248.0f, 248.0f));
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
// 4. just for fun, resize image by factor 2
UIImage *resizedImage = [croppedImage resizedImageToSize:
CGSizeMake(croppedImage.size.width * 2, croppedImage.size.height * 2)];
// 5. save result to photo gallery
UIImageWriteToSavedPhotosAlbum(resizedImage, NULL, NULL, NULL);
// 6. show stencil view again
_stencilView.hidden = NO;
}
Very straightforward stuff.
But as I said, it took me a while. For some reason I never thought of taking a screenshot first.. ;)
Also this solution has the limitation of pixel size. If you want to crop an image of for example 10000 times 10000 pixels and get half of it, you would expect a 5000x5000 pixel result. However, because of the screenshot technique, the cropped area will never be bigger than the pixels on the iPhone screen.
I’ve scrapped the website where I offer setting up your email-server. While it was fun to learn and experiment with, and while some have expressed interest in the offer, it’s neither pracitcal nor profitable for me to continue offering it.
Please refer to this post for information how to start with the email topic yourself. It describes a simple way of setting up an emailserver with Ubuntu.
I just ditched Google Analytics. It’s like a reflex to add it into website projects, but I don’t really need it. Nor do I want it. I think Google has enough information about us already. And they freely share with the American government it seems. So yeah, goodbye.
Now I’m using one of these tools. I can execute a shell script on my computer now and seconds later I have all the analytics I need. Good looking, useful and best of all, not shared with Google.