Nick Harris

NetNewsWire – Time to Breakup

with one comment

When I started at NewsGator there was one client side RSS feed reader in house called NewsGator “Outlook Edition”. My job was to take over development of it as the company moved to a backend sync system that kept everything you read in sync. It was 2005 and I was just learning about blogs and this new medium of RSS. Reading blog posts in NewsGator “Outlook Edition” or on the NewsGator “Web Edition” and having their read states sync was cutting edge to me. Writing the very first app to sync with the new backend platform was an incredible challenge.

My second week at NewsGator I went to lunch with Greg Reinacker, Lane Mohler and Nick Bradbury. Nick, of course, had written FeedDemon which I had never heard of at the time. I had spent a year at my old job using TopStyle so I did know his name. It was the first time I met someone who single handily wrote software I used. It was cool, though I didn’t make much of it. We all just wrote software.

Further down my timeline at NewsGator, we had a guest in the office. My co-worker Gordon Weakliem recognized him as Brent Simmons, the creator of NetNewsWire. I knew that NewsGator was actively pushing the new sync platform to current RSS reader developers. I’m not sure if it was before or after that day when Gordon and I were in Redmond, WA with Gordon trying to pitch Dare Obasanjo (RSS Bandit creator) on it, but I was there and knew the pitch.

I believe it was about 1 month for NickB to join, then 5-6 months after I had started that Brent actually came onboard. I was part of the new team of RSS client devs – Nick, Nick and Brent. Affectionately called “The Nicks” for sometime since no one at NewsGator had a Mac nor really cared about Mac development.

I was completely concentrated on RSS for Outlook, but NickB, Brent and myself often tossed ideas off of each other for improving user experience. It was around this time that I wrote a series of blog posts about user experience and how I had improved NewsGator Inbox (its new name by then) based on all the wonderful discussions NickB, Brent and I had and code I had actually shipped. Unfortunately that was on a company blog that has since been retired.

As NewsGator pivoted to a more Enterprise focus it was decided to shutdown the RSS sync system. The backend of polling RSS feeds and delivering data was still going well, but the market for RSS client apps was coming to a close. With the release of native support for RSS in Outlook it was decided to shutter NewsGator Inbox while transitioning NetNewsWire and FeedDemon to a Google Reader backend. In addition, I was moved to the NewsGator platform team. It made sense. I was already informally in charge of the the API at that point so formally making the switch was a natural transition.

Around this time I had also taken it apon myself to learn how to write apps for iOS. I believe Pocket Euchre (my first iOS app) had been out for a bit and was doing rather well. With the release of the iPad coming up fast, I was invited by Brent to help with NetNewsWire iPad. It was an amazing experience. I worked on all the cool animations and UX that Brad Ellis designed while Brent worked on stability. It launched on day one. A very proud achievement of mine that I never talk about.

This also marked the time when I moved from Windows to Mac fulltime. NewsGator recognized my iOS skills and put me to work building the first mobile apps for Social Sites. Later on I was invited to be part of Sepia Labs using both my platform skills and iOS skills to build Glassboard.

All that time I continued to use NetNewsWire. Even with the demise of Google Reader, and its purchase by Black Pixel, I’m still using NetNewsWire as my desktop reader. But that time has unfortunately come to an end.

I need read state sync and a multiple device experience. I want to be able to click links to blog posts I see on twitter and have them marked read in my RSS app. Really I want to spend less time dealing with read state – something I was spoiled with at NewsGator.

Its not easy. Its an incredibly difficult problem to solve. But it is solvable. The problem is if the solution is profitable. I love Black Pixel and have many dear friends that work there, but its not their bread and butter. A problem like this needs focus and daily attention.

As Brent stated recently, blogs are incredibly important and will outlive any social network. I completely agree.

So I’m looking for suggestions.

Where can I spend some time/money either literally helping someone write code or just supporting efforts that do this well? I wish I had the solution, but after 7+ years working on the problem I came up short.

Written by Nick Harris

September 2, 2014 at 3:54 am

Posted in Uncategorized

OCD

with one comment

I remember walking into the Kaiser Permanente clinic that my doctor had moved to. It wasn’t the closest clinic to my house, but when he moved I decided the drive was worth it. I trusted my doctor.

I had notes on a piece of paper. I knew what I needed to admit. I knew the thoughts I was having were wrong, irrational, horrendous and more importantly not me.

Admitting those thoughts out loud? If someone were to tell me they were having those thoughts, I would have looked at them in utter shock and would never talk to them again. Ever. Those kinds of thoughts are despicable and unforgivable.

But there they were. Replaying themselves over and over in my mind. Each time my mind telling me how horrible they were and that I was a horrible person for having them.

These thoughts became completely debilitating. Simple things like a trip to the grocery store became torturous outings I avoided whenever I could. The true low came when I had to close all my blinds to try and keep the thoughts at bay.

Self-diagnosing through websites is not something I would recommend. One tends to stumble upon all the other things that might be wrong instead of applying Occam’s razor.

I got lucky. I stumbled upon The Imp of the Mind.

Discovering that what I was going through was a documented psychiatric condition with successful therapy options was incredible. The book even uses the thoughts I was having as a case study.

I wasn’t fucking crazy. I wasn’t fucking alone.

Figuring that out, I soon realized, was the easy part. Getting the treatment I needed was the hard part.

And so I found myself on that awkward doctors table/bed thing holding my notes and shaking, waiting for the doc.

When he came in I did it. I said it all. And I broke down like a blubbering fool.
After I was done, what he said will always stick with me:

“That had to be one of the hardest things you’ve ever done.”

It was. And one of my proudest as well.

I went on to do both one-on-one and group therapy sessions based on Cognitive Behavioral Therapy. More specifically – Mindfulness.

I love Mindfulness. Its changed my life.

I hasn’t “cured” me. I’ll compete with depression, OCD and anxiety for the rest of my time.

I just have better weapons to fight them with.

Written by Nick Harris

August 13, 2014 at 4:42 am

Posted in Uncategorized

UICollectionViewCell Flip and Move

with one comment

In my previous post I asked how to both flip and move a UIView. My co-worker Jason Hanson found that adding a “container” view and moving that while flipping the child view worked great. So the example code now looks like this:

[UIViewtransitionWithView:self.flipView

                 duration:5.0

                  options:UIViewAnimationOptionTransitionFlipFromLeft

               animations:^{

                   self.containerView.frame = CGRectOffset(self.containerView.frame, 0, -250);

                   self.flipView.backgroundColor = [UIColor redColor];

               } completion:^(BOOL finished) {

                   self.isFlipViewUp = NO;

}];

 

With that solved, I could move on to implementing the bigger picture effect I was working on – flipping a UICollectionViewCell, centering it in the window with a modal type background, then flipping it back.

I love this effect, and I’m proud of my code. But I’m wondering if there is a better way to do it.

To demonstrate I created a little sample project that flips a playing card:

 

The initial flip needs to:

1. Flip the card from its back to its face
2. Add a gray overlay to the rest of the visible screen
3. Center the card on the screen

Here’s the code:

- (void)flipCard

{

    // grap the screen size and create a view with the same frame

    // set its background to clear so it can be animated

    UIWindow *mainWindow = [[[UIApplicationsharedApplication] delegate] window];

    self.modalView = [[UIView alloc] initWithFrame:mainWindow.frame];

    self.modalView.backgroundColor = [UIColorclearColor];

    [mainWindow addSubview:self.modalView];

    

    // remove the tapToPresentCardGesture

    // then add the tapToHideCardGesture both to the cell and the modal view

    [self.contentView removeGestureRecognizer:self.tapToPresentCardGesture];

    [self.contentView addGestureRecognizer:self.tapToHideCardGesture];

    [self.modalView addGestureRecognizer:self.tapToHideCardGesture];

    

    // translate the frame of the cell to the main window

    self.originalFrame = self.frame;

    CGPoint translatedOrigin = [self convertPoint:self.bounds.origin toView:self.modalView];

    self.translatedFrame = CGRectMake(translatedOrigin.x, translatedOrigin.y, self.frame.size.width, self.frame.size.height);

    self.frame = self.translatedFrame;

    

    // add the cell to the modalView

    [self.modalView addSubview:self];

    

    // flip the contentView while repositioning the actual cell view

    [UIViewtransitionWithView:self.contentView

                      duration:0.5

                       options:UIViewAnimationOptionTransitionFlipFromLeft

     

                    animations:^{

                        

                        // animate the backgroundColor of the modalView to a semi-transparent black

                        self.modalView.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.75];

                        

                        // move the cell to the center of the screen

                        self.center = mainWindow.center;

                        

                        // change the imageView to the card image

                        [self.cardImageView setImage:[UIImage imageNamed:@"AC"]];

                        

                    } completion:nil];

}

 

When it flips back it needs to:

1. Flip the card from its face to its back
2. Remove the gray overlay
3. Replace the card back into the UICollectionView

Here’s that code:

- (void)hideCard

{

    // flip the contentView back from right to left

    [UIViewtransitionWithView:self.contentView

                      duration:0.5

                       options:UIViewAnimationOptionTransitionFlipFromRight

     

                    animations:^{

                        

                        // animate the backgroundColor of the modalView to clear

                        self.modalView.backgroundColor = [UIColor clearColor];

                        

                        // animate the cell back to its original spot

                        self.frame = self.translatedFrame;

                        

                        // set its image back to “Back”

                        [self.cardImageView setImage:[UIImage imageNamed:@"Back"]];

                        

                    } completion:^(BOOL finished) {

                        

                        // remove the modalView along with its tapGesture and set it to nil

                        [self.modalView removeFromSuperview];

                        [self.modalView removeGestureRecognizer:self.tapToHideCardGesture];

                        self.modalView = nil;

                        

                        // reset the tap on the contentView to show the card

                        [self.contentView removeGestureRecognizer:self.tapToHideCardGesture];

                        [self.contentView addGestureRecognizer:self.tapToPresentCardGesture];

                        

                        // tell the delegate that the cell is back

                        [self.delegate cardDidHide];

                    }];

}

 

Notice that it calls a delegate. The delegate is the UICollectionView which simply calls reloadData to get the cell back:

- (void)cardDidHide

{

    // when the cell comes back it needs to be added back to this view

    // calling reloadData will do this correctly

    [self.collectionView reloadData];

};

 

Is this the simplest way of doing this? Could I do this better?

Written by Nick Harris

July 23, 2014 at 4:18 am

Posted in Uncategorized

Flip and Move a UIView – What Am I Doing Wrong?

leave a comment »

This is definitely a newbie question but I figure I’ll post it here then ask Twitter people for the answer cause its Monday and I’m feeling lazy.

I want to use UIView transitionWithView:duration:options:animations:completion: to flip a UIView and reposition it. The problem I’m having is that the first half of the animation has a clipped view. The second half works as expected.

Here’s the code:

- (void)viewDidLoad

{

    [superviewDidLoad];

    UITapGestureRecognizer *tapFlipView = [[UITapGestureRecognizeralloc] initWithTarget:selfaction:@selector(flip)];

    [self.flipView addGestureRecognizer:tapFlipView];

    

    self.flipView.backgroundColor = [UIColorredColor];

    self.isFlipViewUp = YES;

}

 

- (void)flip

{

    if( self.isFlipViewUp )

    {

        [UIViewtransitionWithView:self.flipView

                          duration:5.0

                           options:UIViewAnimationOptionTransitionFlipFromLeft

                        animations:^{

                            self.flipView.frame = CGRectOffset(self.flipView.frame, 0, 250);

                        } completion:^(BOOL finished) {

                            self.isFlipViewUp = NO;

                        }];

    }

    else

    {

        [UIViewtransitionWithView:self.flipView

                          duration:5.0

                           options:UIViewAnimationOptionTransitionFlipFromRight

                        animations:^{

                            self.flipView.frame = CGRectOffset(self.flipView.frame, 0, -250);

                        } completion:^(BOOL finished) {

                            self.isFlipViewUp = YES;

                        }];

    }

}

 

The result of this code looks like this:

What am I doing wrong?

Written by Nick Harris

July 8, 2014 at 12:55 am

Posted in Uncategorized

Fuck Cancer

with one comment

I’ve always been lucky to have amazing friends. My friend Doug was the epitome of that. Though I visited him in the hospital after his first brain surgery, I had no idea the extent of his battle with cancer after we lost touch when we were no longer working together. Wonderful article. Truly the Doug I remember. Particularly the “if there’s winners and losers, I’m in” quote 


http://www.westword.com/2014-05-29/news/jen-berman-doug-furcht/full/

Written by Nick Harris

May 31, 2014 at 3:50 am

Posted in Uncategorized

Working Support

leave a comment »

My former co-worker Nick Bradbury talking about software support:

My first week after joining Automattic as a mobile developer was among the most unusual new-hire experiences I’ve had. Instead of jumping into the code, I did customer support – and I’ll continue to do it for another two weeks.

I’ve loved this post since Nick wrote it. I should have linked to it sooner.

My first few weeks at NewsGator were spent helping the support team figure out bug reports. I hated it, but the time I spent triaging those bugs made me deep dive into the code.

If you want to really learn a new piece of software – either through joining a new team or by acquiring it from someone else – follow the bugs. They’ll lead you to the code that needs the most attention.

Written by Nick Harris

May 9, 2014 at 5:41 am

Posted in Uncategorized

iOS Client Side Sync

leave a comment »

There’s been much ado about writing sync type services for mobile from the server side, but I haven’t seen much about how to implement them on the client side. This is an overview post to see if there’s more interest in how I’ve done things in the past.

Main point: Map your sync data well with Core Data and use NSFetchedResultController’s.

Hit me up on Twitter if a deeper dive into this is something of interest.

Most of my iOS experience has been writing enterprise apps used by large companies as opposed to individual consumers. At NewsGator I wrote the first three versions of NewsGator Social Sites for iOS which connected employees to their companies Microsoft Sharepoint portal. The original was written with iOS 2.1. The amount of data that needed to be “synced” far outreaches anything else I’ve ever worked on.

Social Sites had a co-worker concept that was similar to friends or people you follow on Twitter. Those people could post to a timeline with text, pictures and videos, then have other co-workers comment on those posts (also with pictures and video) – all within the company firewall.

There was also the concept of Communities that had their own timeline of posts and comments along with a list of members.

On top of that there were also Sharepoint libraries of documents, photos, task lists, polls or any N number of object types a company decided to add to their Sharepoint portal. All of these could be associated with both individuals as well as Communities.

An incredible amount of data constantly changing.

I’ve had a lot of experience with SQL databases. I love SQL. But when I had to decide between using SQL or Core Data, I chose Core Data specifically for the use of NSFetchedResultController’s.

My approach was to map the data in Core Data as close as possible to how it was represented on the server. I could then create specific NSFetchedResultController’s for each view controller in the app. All of the “sync” would happen in the background and if something that a particular view needed to know about changed, it would be notified via the NSFetchedResultController.

What this bought me was a separation between the networking code, the local data preservation code and the view controller code.

It worked wonderfully.

It’s been over a year since I’ve work on that code, but if there’s interest, I can put something together that’s more in depth which I can share.

 

Written by Nick Harris

April 23, 2014 at 5:55 am

Posted in Uncategorized

Follow

Get every new post delivered to your Inbox.