Amazon.com Widgets
 

Google Authorship Has Been Removed From Search Results

I read about profile pictures being dropped from search results back in June. However, as reported by The Next Web, authorship is now being completely removed.

"Now that authorship has been dropped completely, webmasters can remove all rel=author markup they have on their site. All the effort adding and maintaining the functionality has now gone out the window, but that’s what happens when so many Web properties rely on a single source for driving massive traffic."

It's hard to tell what the usage statistics are for Google+ due to Google forcably integrating accounts across products (e.g. YouTube to Google+). Thus, we'll never how many accounts would have been setup by choice.

But it leads me to ask what's left for Google+? What niche does it fill? The only reason I set it up was for authorship and therefore it's now of no use to me. Twitter and Facebook continue to fill every other need I have from a social network perspective.

Goodbye Google+.

I'm off to remove my authorship tags and profile.

Digital Ocean Referral

I've been using Digital Ocean for a few months now and their service is fantastic.

From testing Wordpress sites to trying Ghost to hosting the fonts for this website, I've been very impressed with both the simplicity and cost of running servers with them.

If you sign up using this link you'll receive $10.00 in credits. The lowest price tier is just $5.00/month, so that's at best a two-month free trial.

Swift - Private Selectors

Using notification center with Swift is simple:

self.notification.addObserver(self, selector: "notificationReceived:", name: GKPlayerAuthenticationDidChangeNotificationName, object: nil)

However, if you declare your selector's function as private, you'll get a crash when the selector is called (unknown selector sent to instance):

private func notificationReceived(notification: NSNotification)
    {
        // Do stuff.
    }

The key to solving is this snippet from the Using Swift with Cocoa and Objective-C Guide:

"The compiler does not automatically insert the @objc attribute for declarations marked with the private access-level modifier."

The fix is simple:

@objc private func notificationReceived(notification: NSNotification)
    {
        // Do stuff.
    }

No crash and the private access level is maintained.

Free Trials Available for In-App Subscriptions

A new announcement on iTunes Connect:

"You can now offer a free trial for all new In-App Purchase subscriptions. If you offer a free trial, it will begin when a customer subscribes. They will be automatically charged when the free trial is over, unless they have turned off automatic renewal."

I need to understand how this differs from the free trial offered by basically every publication in Newsstand.

Domain Transfer Hell - Resolved

Transfer 1

A few weeks ago I wrote about how I was going through hell trying to transfer a domain from one provider to another.

I had one old domain (www.stuarticus.com) that was with QOXY.com, which I had just renewed and wanted to transfer so I could manage the DNS.1 However, I ran into issues: QOXY had just switched registrars and that meant I couldn’t transfer domains for a period of 60 days. No matter how hard I tried, I couldn’t convince QOXY that this was an issue they needed to help resolve, despite days of back-and-forth emails.

I decided to take it up with the compliance team at the registrar (Public Domain Registry) themselves. Within 24 hours of emailing them and explaining the situation, they’d resolved it for me.

It took approximately nine days to move from QOXY to Hover.

Transfer 2

I wanted to manage all my domains in one place, so I decided to move my main domain (www.stuarticus.net) from IWantMyName2 to Hover (after the previous ordeal). I started the process at 13:42, and by 14:17 on the same day, it was transferred.

This is how it should be done.

The difference in the quality of customer service was simply astounding. I’ve heard many people say that registrar providers can be awful, but I’d never experienced it until now.

In short, I’d recommend IWantMyName and Hover. I’d avoid QOXY.


  1. QOXY don’t provide DNS management unless you have a hosting package. While they can package their products as they see fit, restricting DNS management to hosting packages is hugely inconvenient.

  2. I have nothing against IWantMyName. In fact, I’ve registered many domains with them and they’ve always been very helpful and efficient.

Microsoft's New IE Support Policy

From the MSDN blog:

"After January 12, 2016, only the most recent version of Internet Explorer available for a supported operating system will receive technical support and security updates. For example, customers using Internet Explorer 8, Internet Explorer 9, or Internet Explorer 10 on Windows 7 SP1 should migrate to Internet Explorer 11 to continue receiving security updates and technical support."

For enterprises supporting legacy applications, this will be huge.

Examining the new UISearchController API

I've been examing the new UISearchController API which replaces the UISearchDisplayController API that has been around since iOS 3. My immediate impression is that it drastically simplifies the task of managing a search bar and displaying search results.

You can have a UISearchController up and running with very little code. In the sample project I've put on GitHub which lists and searches through an array of countries, I've configured a UISearchController with the following code in my viewController viewDidLoad method:

self.countrySearchController = ({
            let controller = UISearchController(searchResultsController: nil)
            controller.searchResultsUpdater = self
            controller.searchBar.frame = CGRectMake(0.0, 0.0, CGRectGetWidth(self.countryTable.frame), 44.0)
            self.countryTable.tableHeaderView = controller.searchBar

            return controller
        })()

There are a few items to point out in this code:

  • nil is passed in the UISearchController initialiser so as to ensure that the results of the search are presented in the current viewController.
  • The frame of the searchBar must be set, otherwise it has a height of 0.
  • As per the above, the UISearchControllers searchBar is added to the tableHeaderView. There is no need to add a UISearchBar or UISearchDisplayController in Interface Builder.

The viewController must conform to UISearchResultsUpdating protocol, which contains a single method:

func updateSearchResultsForSearchController(searchController: UISearchController!)

When that method is called, search results are updated based on what String is held the searchController.searchBar.text variable.

It's a remarkably simple API to use.

Ultra Light View Controllers with Swift Extensions

One of the big gripes about using the Model-View-Controller paradigm was the resultant massive view controller you’d end up with. I always had large viewControllers when tableViews were involved. In Objective-C, I started using separate tableView managers that acted as the data ource and delegate. It would usually look something like:

TableViewManager *manager = [TableViewManager new];
self.tableView.delegate = manager;
self.tableView.dataSource = manager;

While this made for a lighter viewController, I still felt as though I was tying everything together with string.

Swift has, joyously, introduced Extensions1. These make me very happy. As per Apple’s Swift Language Guide, Extensions add new functionalities to an existing class, notably allowing an existing type to conform to a protocol.

The beauty is that you don’t need to declare your extensions in the same file. If you have a look at the example viewController in my sample project, ViewController.swift, it’s only 36 lines long (including comments). There is no need to declare conformance to (or implement) protocols in the viewController.

Instead, what I’m doing is creating a separate extension file when needed. In this case, ViewControllerExtensions.swift, where I can declare conformance to various protocols as required.

You can declare as many extensions as you want in a single file and the syntax is straightforward:

extension ViewController: UITableViewDelegate
{
    func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
        tableView.deselectRowAtIndexPath(indexPath, animated: true)
    }
}

The sample project with this approach to extensions is available on GitHub.

Note: all of this is possible with Objective-C Categories.


  1. Not to be confused with iOS 8 App Extensions

Premier League warns about posting goal videos online

Dan Johnson, Head of Communications at the Premier League:

"It's a breach of copyright and we would discourage fans from doing it, we're developing technologies like gif crawlers, Vine crawlers, working with Twitter to look to curtail this kind of activity."

It'll be fun to see how this is enforced and the subsequent reaction.

P.S. I really like the phrase "gif crawler".

Amazing Flag Quiz — III. Leaving It As It Is

I've decided not to focus on updating Amazing Flag Quiz for the time being. This is mostly due to the amount of time I have spare — none.

It doesn't mean I won't update the game in the future. On the contrary, the app still receives around 20 - 30 new downloads a week (and occasionally some in-app purchases) so I will come back to it when time permits.

Is this good Core Data practice in Swift?

I borrowed this idea from NSHipster's GCC Code Block Evaluation C Extension post. I've never seen it used for the purposes of an NSManagedObjectContext, but it seems to work for what I need it to do.


class MainContext: NSObject {
    let managedObjectContext:NSManagedObjectContext = ({
        // Setup the model
        var modelURL = NSBundle.mainBundle().URLForResource("TEST", withExtension: "momd")
        var model = NSManagedObjectModel(contentsOfURL: modelURL)

        // Setup the coordinator
        var bundlePath = NSBundle.mainBundle().pathForResource("TEST_DB", ofType: "sqlite")
        var fileURL = NSURL(fileURLWithPath: bundlePath)
        var coordinator = NSPersistentStoreCoordinator(managedObjectModel: model)
        var error : NSError? = nil
        coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: fileURL, options: [NSReadOnlyPersistentStoreOption : "YES"], error: &error)

        // Setup the context
        var context = NSManagedObjectContext(concurrencyType: NSManagedObjectContextConcurrencyType.MainQueueConcurrencyType)
        context.persistentStoreCoordinator = coordinator

        // Return the context
        return context
    })()


    /**
    Returns shared instance of MainContext
    */
    class var sharedInstance : MainContext {
    struct Static {
        static let instance : MainContext = MainContext()
        }
        return Static.instance
    }
}

Expectations

Jared Sinclair:

"Expect a Long Road – Becoming a household name isn’t easy. Expecting overnight sustainability – nevermind overnight success – is wishful thinking. If you want to build a business by yourself, you’ll need an indefinite source of outside income. That means you have to work your ass off every night and weekend, or else secure venture funding."

Agreed.