Comments:"bennyguitar/News-YC---iPhone · GitHub"
URL:https://github.com/bennyguitar/News-YC---iPhone
News/YC for iPhone
The iPhone version of News/YC, a Hacker News reader and interactive iOS application.
About
News/YC is a front-page reader for Hacker News (http://news.ycombinator.com), a portal for interestingness regarding technology and building things. This app is free, and will forever remain free - and now, starting with version 1.2, is entirely open-sourced (please don't laugh at my code). The app can be found on the iOS App Store here: https://itunes.apple.com/us/app/news-yc/id592893508?ls=1&mt=8
The Code
The root ViewController, App Delegate, and HNSingleton are in the top-level directory, while every other class should be self-documented through the folders they are in (Webservice, Data Objects, Utilities, etc.). There are a number of features that are in this code-base that aren't in the public release version (1.2) that is on the iOS App Store right now. I've tried to document these features in sub-sections labeled Version 2, and are currently in-progress (things like logging in and voting). Feel free to help out on these features and launch the best HN reader for iOS!
Webservice.{h,m}
This class contains all web requests to the API, using a delegated system so ViewController can receive callbacks about the success or failure of each call - as well as the objects (posts/comments) returned.
Fairly self-explanatory, this method hits the API and pulls the homepage back as Post objects, then calls the delegate method -(void)didFetchPosts:(NSArray *)posts
to return objects back to ViewController. If no posts are retrieved, or there is a database/server error, nil
is returned through the delegate method. ViewController checks off of this for exceptions and displays the posts accordingly.
-(void)getCommentsForPost:(Post*)postlaunchComments:(BOOL)launch;
This method returns an NSArray of Comment objects using the delegate method -(void)didFetchComments:(NSArray *)comments forPostID:(NSString *)postID launchComments:(BOOL)launch
to call back to ViewController. The launchComments part of this method is for showing the commentsView in ViewController. If YES, this will animate commentsView coming up from the bottom, if NO, this is a pull-to-refresh case where the data was updated and only the table needs to be refreshed. This method will also return nil
if there is a database/server retrieval problem so we can handle the exception accordingly.
For Version 2
-(void)loginWithUsername:(NSString*)userpassword:(NSString*)pass;
This method handles logging in and returns a User object using the delegate method -(void)didLoginWithUser:(User *)user
to call back to whatever ViewController implements and makes the call. I'm thinking about putting this method in the HNSingleton class to keep an app-wide scope on the login status (since everything is handled asynchronously) and using NSNotificationCenter when a login/logout occurs.
-(void)voteUp:(BOOL)upforObject:(id)HNObject;
This method handles voting for objects. I'm currently working on adding in the UI to handle voting/commenting on stories, and this method will take control of voting on any object (HNObject is just a Post or Comment). The callback to this delegate will be a BOOL, indicating a successful vote or not. However, I don't plan on doing anything UI-wise specifically that will alert the user that it failed (may just be too much information), though I do plan on alerting them if the cookie is bad so they can re-login and attempt again.
Data Objects - Post.{h,m} and Comment.{h,m}
These classes make up the data model used by News/YC. Both Post and Comment contain special constructor methods based on the JSON objects that return from Webservice.{h,m}
calls - going from NSDictionary to objects. Comment has an NSMutableAttributedString property, attrText
that isn't used right now, but there are plans in the future to use this to style up comments (more on that in the Things to Come section).
@interfacePost : NSObject// Properties@property(nonatomic,retain)NSString*Username;@property(nonatomic,retain)NSString*URLString;@property(nonatomic,retain)NSString*Title;@property(nonatomic,assign)intPoints;@property(nonatomic,assign)intCommentCount;@property(nonatomic,retain)NSString*PostID;@property(nonatomic,assign)BOOLHasRead;@property(nonatomic,retain)NSDate*TimeCreated;
@interfaceComment : NSObject// Properties@property(nonatomic,retain)NSString*Text;@property(nonatomic,retain)NSMutableAttributedString*attrText;@property(nonatomic,retain)NSString*Username;@property(nonatomic,retain)NSString*CommentID;@property(nonatomic,retain)NSString*ParentID;@property(nonatomic,assign)intLevel;@property(nonatomic,retain)NSDate*TimeCreated;@property(nonatomic,retain)NSMutableArray*Children;@property(nonatomic,retain)NSMutableArray*Links;@property(nonatomic,assign)CommentTypeCellType;
For Version 2.0
I have included a User.{h,m} object with the intention of adding user-management functionality as well as submitting/commenting/voting.
@interfaceUser : NSObject// Properties@property(nonatomic,retain)NSString*Username;@property(nonatomic,assign)intKarma;@property(nonatomic,assign)intAge;@property(nonatomic,retain)NSString*AboutInfo;
HNSingleton.{h,m}
This class contains a few properties that manage things on an app-wide scope. Included is an NSDictionary for keeping track of which articles have been read (though I'm thinking about adding this to the NSUserDefaults so it will always stay with the app), and the remnants of version 1.1.1 when I was using a different API to filter the homepage by Top/New/Ask (which I'd love to reincorporate again). HNSingleton incorporates a couple methods to change the theme colors and set the SessionKey (more under the break).
@interfaceHNSingleton : NSObject// Properties@property(nonatomic,retain)NSMutableDictionary*hasReadThisArticleDict;@property(nonatomic,retain)NSMutableDictionary*themeDict;@property(nonatomic,assign)enumfTypefilter;@property(nonatomic,retain)NSHTTPCookie*SessionCookie;@property(nonatomic,retain)User*User;// Methods-(void)changeTheme;-(void)setSession;-(void)loginWithUser:(NSString*)userpassword:(NSString*)pass;-(void)logout;
For Version 2.0
This class also includes a NSHTTPCookie object, SessionKey
for keeping track of user-authenticated actions such as submitting or voting. A successful login adds the cookie to the persistent cache of cookies that iOS implements device-wide. A check for the cookie inside AppDelegate's launching method adds it to the Singleton. Every authentication-important Webservice call will attach this cookie to the HTTPHeaders before the request is sent.
Loggin In/Out is another new feature set for a v2.0 release. This HNSingleton class also keeps track of the current User object associated with a login and all of the login functionality. From anywhere in the app, if a login is necessary - a call to [[HNSingleton sharedHNSingleton] loginWithUser:(NSString *)user password:(NSString *)pass
is made.
API
News/YC uses the only officially sanctioned API that Hacker News approves of: http://hnsearch.com/api. The API calls made by this app are slightly tricky. For the front-page posts, a call is made to http://hnsearch.com/bigrss and then the resulting xml is parsed to grab the unique IDs from each post. Those are then sent as a request to the actual API to get the posts. The comments, unfortunately, return as basically a totally unordered set. I create a linked list out of those, and then I turn it into a flat array based on the nested nature of the comments - so UITableView will render correctly. All of the Comment trickery is done in Comment.m
.
3rd Party Libraries
News/YC uses the following third party libraries:
Things to Come
For subsequent versions, I'd like to see a couple things happen to make this app awesome.
Features
- Logging In
- Voting
- Submitting
- Commenting
- Viewing Ask HN / Newest Posts
Having a beautiful and easy-to-use user management system is what this app needs. I've included a spot for this already with the right ViewDeck, but have not designed anything. Ideally, a user would login by swiping open the right side and entering their credentials. Then that side would show their karma, about me info (changeable perhaps), date created, and other useful user information. The only problem is that there is zero API support of this functionality and there probably never will be, especially since it seems like PG doesn't really approve of external APIs and brings the hammer down with rate-limiters. That said, I believe that this functionality could be implemented via client-side scraping rather than doing it on a server and serving up JSON for anyone to grab. Of course submitting, commenting and voting would follow from the ability to login.
I'm hoping to basically include only one more class User.{h,m}
and all calls/scraping be done in Webservice. I may implement the HNKit (https://github.com/Xuzz/HNKit) code to do this, but there isn't much documentation on it, it doesn't look like it's in ARC, and it seems fairly convoluted.
In Code
- Comment labels using NSAttributedString (for < html > tags)
- Cleaned up a little bit / better documentation
The API returns comment text with different HTML tags inside it including < p >,< i >, and < code >
that would be very cool to format in via NSAttributedString. I'm already turning the < p >
tags into new lines, but italics are used for emphasis quite a bit in HN comments, and I'd like to have that in here as well.
License
This repository is licensed under the standard MIT license. Any third party code that appears in this repository is licensed under the terms the original author laid out and does not transfer to my licensure. Feel free to use whatever you'd like from this.