Skip to main content


Showing posts from 2013

Drawing NSAttributedStrings with Superscripts and Subscripts (iOS/Xcode)

This is the briefest of brief posts dealing with Core Text and NSAttributedStrings in Xcode for iOS. First, let's create an attributed string and add a superscript attribute along with a font. NSMutableAttributedString *stringOfText = [[NSMutableAttributedString alloc] initWithString:@"Hello World"]; [stringOfText addAttributes:@{(id < NSCopying >)kCTSuperscriptAttributeName:[NSNumber numberWithInt:1], NSFontAttributeName:[UIFont fontWithName:@"Georgia" size:20]} range:NSMakeRange(2,5)]; We now have a range of options. We could: draw the string directly inside the drawRect method of a UIView use a CATextLayer  use a UILabel (iOS 6 onwards) use a UITextView (iOS 7 onwards) Explaining how to draw the string in the drawRect of a UIView is a post in its own right, so here I'll move swiftly on to look first at the CATextLayer option. You'd add an attributed string to a CATextLayer like this: CATextLayer *layerForText = [[CATextLay

NSMutableArray, indexOfObject:, NSNull and NSNotFound (Xcode for iOS)

Creating an array with empty objects NSMutableArray is a useful class for ordering objects and keeping them in order. So let's suppose we have a set number of items, for example pages in a book. We might want to place each view, or view controller, that represents a page in the book at the correct place in the array, but not necessarily want all of the pages to be held in the array at one time. So first of all we need an array of empty objects. And let's say we'd like it to be 20 objects long. NSMutableArray *pagesArray = [[NSMutableArray alloc] init]; int i = 0; for (i < 20)  { [pagesArray addObject:[NSNull null]] i++; } Replacing empty objects with real ones Now we have an array into which we can insert our page objects at their correct places. [pagesArray replaceObjectAtIndex:10 withObject:page11] Of course in real use we would've instantiated whatever it is our page11 object is, but for now it's the array we're interested in. Knowin

How to stop every app you purchase downloading to your iPad, iPhone or iPod

If you've more than one iOS device or you purchase apps through the desktop version of iTunes and find that your other device keeps downloading the same apps when you don't want it to, then on your iOS device: (1) open the Settings app (2) scroll down and tap iTunes & App Store (3) slide all "Automatic Downloads" (Music, Apps, Books, Updates) to the left to turn off Follow @sketchytech

UIWebView pagination in iOS 7 (Xcode)

Newly added to iOS 7 is the ability to paginate your UIWebView left to right and in other directions as well. See this post for a handy three lines of code to get this working (scroll down to the Native Web App Development section, beneath which you'll see 'Paginate Mode' instructions). You can also find details in Apple's UIWebView documentation and you might well wish to add hyphenation to your css to make this even more book like. (See also Mozilla's guide to hyphens .) Follow @sketchytech

JavaScriptCore Framework for iOS 7

I only stumbled across this by chance. Matt Neuburg mentions it in his latest book on Programming iOS 7 published by O'Reilly: “New in iOS 7, your Objective-C code can load a JavaScript virtual machine and communicate back and forth between JavaScript and Objective-C. See Apple’s JavaScriptCore Framework Reference (currently documented only for OS X, not iOS). I don’t think this has anything to do with UIWebView per se, but it’s so cool that I couldn’t resist mentioning it.” and this blog post  goes into more detail. See also Apple's JavaScriptCore Framework guide for OS X , there is no guide for the iOS 7 implementation yet. Update Apple's explanation of the JavaScriptCore framework is as follows: The JavaScript Core framework (JavaScriptCore.framework) provides Objective-C wrapper classes for many standard JavaScript objects. Use this framework to evaluate JavaScript code and to parse JSON data. For information about the classes of this framework, see the head

Yesterday's dream: Open File Formats

The creation of OpenOffice was instrumental in the creation of more open and interchangeable XML-based office formats. This should be a source of celebration, but now the goal of OpenOffice has largely been achieved, the goal shifts. With the advent of apps, the focus is on what can be uniquely achieved in one app vs another. And unique apps demand unique file formats, think .pages, .garageband, .idraw and so on. This use of unique files is something Apple encourages and supports in its operating systems. This doesn't mean that every app is an island, but instead that apps have unique file types in order to achieve their goals in the most efficient way possible, but then often have interchange formats for use on the desktop and so on. Depending on the app and its role these interchange formats might be: SVG, PDF, .docx, RTF, etc. For those involved in data preservation, this might sound like a bad thing, since unconverted files from apps that disappear into the ether might

Is the future of eBooks RTF?

Displaying RTF (and RTFD) text in an app With the advent of iOS 7 things are changing inside Apple's mobile operating system a good deal when it comes to the display of text. For example, you can now create an RTF file in TextEdit, style it with bold and itals, etc. on a Mac and even drop an image into that file. The display of that file is then possible with a trivial amount of code: NSURL *rtfString = [[NSBundle mainBundle]                          URLForResource: @"helloworld" withExtension:@"rtfd"]; NSAttributedString *stringWithRTFAttributes = [[NSAttributedString alloc]   initWithFileURL:rtfString options:@{NSDocumentTypeDocumentAttribute:NSRTFDTextDocumentType} documentAttributes:nil error:nil];     // Instantiate UITextView object textView = [[UITextView alloc] initWithFrame:CGRectMake(20,20,self.view.frame.size.width,self.view.frame.size.height)];     textView.attributedText=stringWithRTFAttributes;     [self.view addSubview:textView]; A

Creating an NSAttributedString from HTML (or RTF) in iOS 7 (Xcode) - Updated for Swift

Following additions to the iOS 7 NSAttributedString class it is now possible to create attributed strings using HTML. For example: NSURL *htmlString = [[NSBundle mainBundle] URLForResource: @"helloworld" withExtension:@"html"]; NSAttributedString *stringWithHTMLAttributes = [[NSAttributedString alloc]   initWithFileURL:htmlString options:@{NSDocumentTypeDocumentAttribute:NSHTMLTextDocumentType} documentAttributes:nil error:nil]; // Instantiate UITextView object UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20,20,self.view.frame.size.width,self.view.frame.size.height)]; textView.attributedText=stringWithHTMLAttributes; [self.view addSubview:textView]; Two things to note here: (1) this is a rough and ready use of UITextView - see this earlier post for a better implementation (2) you'll need to save an accompanying file called 'helloworld.html' for this to work. Here is the helloworld.html file: <html><p>

Paging and paginating the easy way with UITextView and UIScrollView in iOS 7 (Xcode)

Following yesterday's post on the right way to use UITextView, I wanted to put it together with the contents of an earlier post on UIScrollView in order to show how simple it is to let iOS 7 work out the pagination for you. I'm not going to hold your hand in this post, instead I'll ask you to refer back to the two earlier posts if there's something that isn't clear in the following code and its comments: // Create a scroll view UIScrollView *scrollingView = [[UIScrollView alloc] initWithFrame:CGRectMake(20,20,self.view.bounds.size.width-20,self.view.bounds.size.height-20)]; // Make the scroll view content size big enough for four pages scrollingView.contentSize  = CGSizeMake((self.view.bounds.size.width-20)*4,self.view.bounds.size.height-20); // Enable paging in scroll view scrollingView.pagingEnabled = YES; // Add scroll view to view [self.view addSubview:scrollingView];     // Create string - content NSAttributedString *textString =  [[NSA

Making the Most of UITextView in iOS 7: NSTextStorage, NSLayoutManager, NSTextContainer and NSAttributedString

Most likely if you're using UITextView then you'll want to take advantage of attributed (or styled) strings. So let's create a NSAttributedString first of all: NSAttributedString *textString =  [[NSAttributedString alloc] initWithString:@"Hello World" attributes:@{NSFontAttributeName: [UIFont fontWithName:@"HoeflerText-Italic" size:12]}]; Now, it might seem convenient to create a UITextView and add the attributed string like this: UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(20, 20, self.view.bounds.size.width, self.view.bounds.size.height)];   textView.attributedText=textString; [self.view addSubview:textView]; But that would be the wrong thing to do if we want to take maximum advantage of all the classes, methods and delegates available to us when using UITextView. So what should be done first is to add the attributed string into a NSTextStorage object: NSTextStorage *textStorage = [[NSTextStorage alloc] init

iCloud, Mavericks and iOS 5, 6 and 7 - How to keep Pages, Numbers and Keynote in sync

When you update to the latest version of Pages, Numbers or Keynote for iOS 7 you'll be warned upon opening apps that the file will be converted into the latest format that can only be opened in the latest version of the iWork app in question and that it will only be possible to open this on a desktop using Mavericks in combination with the updated versions of Pages, Numbers or Keynote. If you are running iOS 7 but an earlier version of OS X prior to Mavericks you'll probably have to do a dance of downloading the Word version of your docs from iCloud via Safari to work with them in Pages '09, for example, or else not update Pages for iOS. However, if you are running Mavericks but not iOS 7 then you can still take advantage of the new Pages and other iWork apps without as much fuss. This is because: When you install the updated apps in Mavericks a folder is created in your Applications folder called iWork '09 and here you'll find all the '09 versions as the

What to do if Adobe Creative Cloud tells you to quit AdobeCrashDaemon before you can install an update (OS X)?

AdobeCrashDaemon isn't a Creative Cloud app, it doesn't run and exist like all the others, so you can't just quit it. Thankfully, there is solution (or two). You can either visit this thread or try the solution that worked for me: Quit all running Adobe apps Go to Applications > Utilities and open the Activity Monitor app Type adobe_licutil in the search box Double-click on adobe_licutil  Select 'Quit' All should now run as expected. Follow @sketchytech

Import EPUBs into InDesign without ickmull (or the Terminal)

Following Nick Barreto's recent post on importing EPUB files into InDesign I was inspired to write this short post providing an alternative method that uses only InDesign itself. Import EPUB into InDesign (1) Follow Nick's post up to the point where he unzips the EPUB - you can do this not only in the way he describes but also by using StuffIt Expander  and dragging the EPUB file onto the StuffIt icon in the OS X dock, or by replacing .epub extension with .zip in Finder and double clicking (2) Drill down to the XHTML files as Nick also describes and change the extension of each to .xml (3) Next import the XML file into InDesign by going to File->Import XML... and selecting the file. (4) OK the DTD warning that appears telling you something about not having the linked file. (5) The XML will appear in the Structure panel and from here you can drag it into text boxes - see Adobe's guide for help . (6) Next open the Tags panel using Window->Utilities->Tags to

How to view four apps at once in Windows 8.1

One of the headline features of the Windows 8.1 update is the ability to run four apps at once side by side. This is how to get it working: (1) open four different apps from the start screen (2) open the desktop (3) move cursor to top left of the screen (4) click and drag the little preview screen that appears and place the first app next to the desktop (it should move aside) (5) repeat (4) twice being careful to drop apps next to and not on top of others Once you've done this you can resize using bars and push other apps off the screen by dragging bars to the right. If you want to choose exactly which app you want to open (or you have more than four open) you can repeat step (3) and take the cursor to the top of the screen then drag to the right then back to the left to see the apps that are running but not displayed in a Start bar. If you want to return from the Start screen or a single Desktop view or any other app to this multi-app view go to the top left of t

Are you looking for Windows 8.1 in the Windows 8 Store and not finding it?

Windows 8 neither automatically updates to Windows 8.1 nor does it get pushed to your updates list. Instead it appears in the Windows Store, which you access from the Start screen using the shopping bag tile. However, unless your Windows 8 system is prepped and ready it might not appear in the store at all. The first step to getting your system up to date and ready for Windows 8.1 is to go to the Settings menu. Do this by taking your cursor down to the bottom right of the screen and off the edge, and then click on the Settings cog. Step two is to select 'Change PC Settings' from the bottom of the side menu. The third step is to select Windows Update from the bottom of the PC settings menu and to install updates. If you do this and restart the system and the updates fail (as they did for me first time around) simply repeat the steps and freshly download the updates and try again until all are installed. The final step is to visit the Store using the sho

The reason I think the Microsoft Surface makes more sense than the Pro

You can now pre-order a Surface 2 from Microsoft. The Surface (formerly known as RT) starts at £359 (UK) but you don't want the 32 GB version unless you're happy with only 15 GB of storage for user content . Instead you'll probably want the 64 GB version with about 44 GB of storage for user content, which will cost £439. If you go with the Surface Pro then the 64 GB model has about 27 GB of storage for user content and you'll want to jump to the 128 GB version to benefit from a more comfortable 85 GB for user content. After all you're spending over £700 on this, so the extra £80 for the £799 model is most likely worth it for the majority of users. But wait. Why are you buying the pro-model at all? For the security blanket of the traditional Windows desktop? OK, the vision of one device is great but is it really the most productive or price conscious solution? I can pick up a Windows 8 laptop with a 1 TB drive on Amazon for £300 (or £450 for an i5 Lenovo) withou

Apps with and without iOS 7 bugs

- Updated 21 Oct 2013 - It's hard to resist upgrading to iOS 7, especially when you want to try your best to keep up with all the new apps and design trends happening in mobile, but sometimes it's good to show some reserve and not be caught out. With this in mind I've researched a short list of apps that I'd rather not live without. Apps still suffering bugs Comments on iTunes indicate that  GoodReader  would benefit from a second round of bug fixes for iOS 7 following their recent update (Sep 16, 2013). iOS 7 ready apps A new version of  Procreate  has been released to fix bugs.  Kodiak for PHP  and  Kodiak for JavaScript  have no reported bugs according to their developer and  Textastic  got in early and put their house in order well before iOS 7 was released, as did TouchDraw .  DoInk  has confirmed (via Twitter) no current bugs have been reported or found. iDesign  has received iOS 7 bug fixes to backup and save functions. Update : having now updated an

Why don't scrolling eBook UIs work?

Why don't scrolling eBook UIs work? At the moment there's a choice to be made when reading eBooks on tablet devices like the iPad - either you choose a book page type interface or a scrolling one like a web page. It comes as a mystery to many why reading a book chapter as a scrolling page is any different than a blogpost or a newspaper article, which are both often more comfortable to read in a non-paginated way than attempts to paginate them. The answer is related to length and the type of content. An article or post is often something you skim through and is short. Scrolling is ideal for this. However, as soon as we try reading a book chapter things become trickier. To read the equivalent of ten or twenty printed pages is not the same as reading what might have been less than half a printed page. To understand this, let's look at what happens when we read a printed book: (1) there is a void at the top and bottom of each page where it begins and ends (2) the po

Use cases for browser-based ebook reading

Twitter has both a browser-based mobile web app and native mobile apps. The native ones work better. Why then do the browser-based ones exist? I suggest a few reasons people might use them here: 1. because they haven't yet installed the apps and wish to use the site without doing so 2. they've arrived by a search on Google and just flick through a few tweets before deciding whether or not to launch the native app and continue for longer 3. they want to have a tab open for twitter but quickly tab to other sites to save time For similar reasons I think it is important that publishers (and others) develop browser-based ebook reading platforms alongside native ones. I outline some of these reasons here: 1. people might land on the book via a web search and want to start reading online, make a few notes (e.g. for later syncing) before making a download (and/or purchase) 2. they might be searching multiple books from multiple publishers with multiple different browser-based

The development of #jsonbook

What you are seeing in this video is a paragraph being clicked and an editable space for user comments on that chapter opening. If a citation is clicked then a list of references cited in the paragraph opens, if a note referent is clicked the notes referred to in the paragraph open. All of this is dynamic and doesn't require additional markup to the XML. Citations are auto-detected by their text format - (author, date: pages) - and notes will similarly be identified (in the final versions of the code) using a combination of regular expressions and walking through XML nodes with PHP and/or JavaScript. It is still in the early stages of development (mainly in PHP/jQuery, iOS will be second), but there is steady progress being made with the json-book project, more details of which you can find on GitHub  - be sure to also read the Wiki. The implementation isn't set in stone, it's an example of one possible way of parsing the JSON, and is an organic first-pass at fin

Installing PDFlib in MAMP OS X

In this example, I'm going to outline the instructions for installing PDFlib 8 on a MAMP system running PHP 5.2.17. You'll have to make the logical adjustments to the folder names if you've a different setup. First of all stop the MAMP servers then do the following: (1) download the correct version of PDFLib for your system and programming language: (2) double-click the downloaded .dmg file to unpack (3) create a folder called pdflib inside your MAMP htdocs folder (4) drag the entire contents of the opened .dmg file here (5) navigate in Finder to Applications/MAMP/htdocs/pdflib/bind/php/php-520 (6) keep the Finder window in point (5) open (7) open the php.ini file contained in Applications/MAMP/bin/php/php5.2.17/conf (8) find the line that begins extension_dir and reads something like this:     ; Directory in which the loadable extensions (modules) reside.     extension_dir = "/Applications/MAMP/bi

json-book - notes and references example

An early (and incomplete) example of what is made possible using JSON and a scripting language like PHP. Using a separation of style and content there's no need to repeat html mark-up (and jQuery) for each book or chapter, making it lighter and more flexible than creating each book in HTML/CSS/JavaScript and much more reusable. Not to mention easier to add all the bells and whistles you want without changing the content (data). This future approach to producing books will save time and enable editors to refocus on the content rather than hacking the content to work in each different ereader, because every book will be updated programmatically each time the parsers are improved and adapted for each format. This means that you will no longer have multiple book content files that each need to be updated separately. It will be possible, via this method, to package books in EPUB and Kindle formats, as well as to deliver and parse in Android and iOS with a single JSON file. Develo

Exporting PDFs direct from InDesign to iCloud

Here's an interesting thing I spotted using InDesign CC on Mac OS X 10.8 (Mountain Lion). When you save a PDF in the normal way using File->Adobe PDF Presets you can use the drop down "Where" menu beneath the 'Save As' box and select iCloud (Preview). At first I thought "iCloud (Preview)" meant that Adobe was testing out iCloud functionality as a preview offering, but what it actually means is that you save the PDF to Preview's iCloud store. My secondary thought was that this might be built into OS X like the ability to Save as PDF through the print dialogue box, but trying the same thing in Illustrator and OpenOffice appears to disprove this theory, and makes it appear that this is something implemented on purpose in InDesign (correct me if I'm wrong!). It's strange because Adobe Acrobat uses and there doesn't seem to be an option to save directly to this location, but you would think Adobe would prefer us

Time Machine Backup: "Unable to complete backup. An error occurred while creating the backup folder."

The first thing to try in this situation is a simple restart and remount of your external drive. If the problem persists the following might well fix this error: (1) select your backup disk in Finder (2) select the Backups.backupdb folder (3) select the folder with the name of your computer (4) look for a file that ends .inProgress (5) drag the .inProgress file to trash to delete it (6) select Time Machine icon from top menu bar and choose "Backup Now" All should now return to normal. If it doesn't then this thread has some suggestions. Send to Kindle Follow @sketchytech

Setting up Netgear Readyshare WiFi Router with Time Machine

(1) Using a Mac, format external disk (with USB connection) in Mac OS X Journaled format using Disk Utlity (Applications->Utilties->Disk Utility) (2) Click on the external drive inside Finder, press cmd + I and change sharing preferences so that everyone can read and write to the disk (3) Unmount and plug external drive into USB socket of Netgear Router (4) visit in your Mac's browser (5) select readySHARE tab (6) press Edit button (7) select your drive from the list (Folder Name T:/ with my router) (8) press Create Network Folder (9) make sure you've the correct drive selected and enter a Folder and Share name, providing Read and Write access for all (10) your router name (something like D6200) will appear as a server you can connect to in Finder sidebar (and this contains your network folder) (11) enter Time Machine and use Select Disk … to select the folder you created as your backup destination. Do not log in with a username and p

How to upgrade from Windows XP 32-bit to Windows 8 64-bit inside VMWare Fusion OS X

This approach will delete all personal and application files you use in XP.  So Backup any files you need. Also recommended is VMWare Fusion version 5. (1) Back up any files you will want to preserve (2) shut down Windows using the Virtual Machine menu (3) go to Virtual Machine menu and select Settings ... (4) select Processors & Memory (5) make sure you have at least 2GB (2000 MB) of memory allocated (6) go to the Virtual Machine menu and select Hard Disk->Hard Disk Setting ... (7) If your virtual hard disk is of the SCSI kind, delete or remove the virtual hard disk (if it is of the IDE kind you might be able to ignore this step and jump to step 11)  (8) select Virtual Machine menu again and Select Settings... (9) select Add Device and select new Hard Disk (10) select size you require (20GB is minimum) and change type to IDE if it's not selected already (11) insert Windows 8 install CD into SuperDrive (12) use the icons (on virtual machine w

Gimmick Racing on iOS: Table Top Racing Rules!

One of the first games I ever bought on iOS was Shrek Kart, because it was the closest thing to Mario Kart I could find. It was played and played, and no end of fun was had from the game. And yet all the attention at the time was going to Real Racing and its stunning graphics and AirPlay integration. But the truth is that realism is rather dull. We know this from Infinity Blade. Gameloft realised from the start that humour was important, and even realistic racers need some added unrealism, hence the success of the Asphalt series. I've played many other racers since these Gameloft successes, but grew rather bored of wading through racers in the end, and so by the time Table Top Racing was released, even though it has a developer connection to Wipeout, a game I, like many, was addicted to on the N64, I was too fatigued by it all to pay out for this app. Shame on me. This is an amazing game. Not only do you get to launch over sandwiches and drive along spoons as you explore how

Don't get your ternary operators in a twist: Objective-C and the NYTimes Style Guide

The New York Times recently released its style guide for Objective-C on GitHub. And one of the first pull requests was related to the use of ternary operators. Something that is incredibly difficult to search for in the documentation when you don't know their name, because the defining elements of the operators are a question mark (?) and a colon (:).  a==b ? NSLog(@"it's a match") : NSLog(@"boo, no match"); // Ternary operator meaning if a is equal to b then print "it's a match" in the console, else print "boo, no match" For this reason alone they are probably best accompanied by a comment with the words "ternary operator" before or after them, but this aside, they are an interesting case along with using: id a = @"string"; id b = @[@"an",@"array"]; id c = @{@"key":@"value"}; Ignoring the @ sign, the above examples are familiar to most programmers as indicatin

#baddesign or #worksjustfine: The many functions of the cmd + R shortcut (Mac OS X)

There are two types of people: (1) the shortcut whizz and (2) the methodical menu manipulator. In between we have the average Joe who probably uses a combination of the help search bar and the limited range of shortcut keys they know almost as much as the menu system. Shortcuts accelerate productivity, but shortcut keys are not consistent across apps. This makes sense, since there are only a limited number of keys, and combinations placed conveniently near each other, that are logical enough for the purpose. For example cmd + R can do the following: OpenOffice - align text right Pages/Numbers - show/hide ruler(s) Adobe Acrobat/Illustrator/InDesign/Photoshop - show/hide rulers Safari/iTunes/Mac App Store - refresh page Pixelmator - show/hide rulers Preview - rotate current page Mail - reply to message Twitter - reply to selected message (if no message selected do nothing) Kindle - sync to furthest page read iPhoto - rotate selected image Calculator  - enter RPN mode

Three Steps to Syncing a Box Folder on your Mac or Windows Desktop

Having logged into your account on the Box website follow these three steps: (1) Click on the cloud icon at the top of the browser window (2) Select 'Official Box Apps' from righthand menu (3) Choose Box Sync for Mac, Box Sync for Windows (or Box for Windows 8) This will download the app for you to install and provide you with instructions to setup the folder syncing service. Note:  To uninstall Box Sync run the installer and select uninstall. If you encounter any problems with logging into the service, uninstalling and reinstalling can provide a solution. Follow @sketchytech

Innovating in-app purchase

The system of in-app purchase is most often associated with buying your way through games. As a gamer this feels like cheating, as a parent it feels like an attempt to exploit me. The general consensus around the web appears to be that games should charge upfront rather than try and profit from children's demands on their parents to the tune of tens or even hundreds of pounds. We parents still sweat that leaving in-app purchasing on in Settings might allow one-click spending, even now the process has changed. And sweat we probably should, since children often learn passwords and pin codes for the adult's convenience - when the demands to unlock this and update that become too frequent - and this can return to bite us. Does this mean the whole system is doomed? Until recently my advice to developers would've been don't bother if you want to win the goodwill of parents and people in general. And still there is a niggle at the back of my head that a paid for app is a