load a static URL on app startup and display the text

This commit is contained in:
Sami Samhuri 2012-11-14 23:00:41 -08:00
parent c5772ca2b1
commit 911c59fe62
14 changed files with 1034 additions and 34 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
xcuserdata

View file

@ -19,6 +19,9 @@
7B00EC841654BBEB00531FBD /* VSViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B00EC831654BBEB00531FBD /* VSViewController.m */; };
7B00EC871654BBEB00531FBD /* VSViewController_iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B00EC851654BBEB00531FBD /* VSViewController_iPhone.xib */; };
7B00EC8A1654BBEB00531FBD /* VSViewController_iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7B00EC881654BBEB00531FBD /* VSViewController_iPad.xib */; };
7B00EC9A1654BCBC00531FBD /* MMHTTPClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B00EC971654BCBC00531FBD /* MMHTTPClient.m */; };
7B00EC9B1654BCBC00531FBD /* MMHTTPRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B00EC991654BCBC00531FBD /* MMHTTPRequest.m */; };
7B00EC9E1654C0A900531FBD /* VSSource.m in Sources */ = {isa = PBXBuildFile; fileRef = 7B00EC9D1654C0A900531FBD /* VSSource.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@ -39,6 +42,12 @@
7B00EC831654BBEB00531FBD /* VSViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = VSViewController.m; sourceTree = "<group>"; };
7B00EC861654BBEB00531FBD /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/VSViewController_iPhone.xib; sourceTree = "<group>"; };
7B00EC891654BBEB00531FBD /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/VSViewController_iPad.xib; sourceTree = "<group>"; };
7B00EC961654BCBC00531FBD /* MMHTTPClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMHTTPClient.h; sourceTree = "<group>"; };
7B00EC971654BCBC00531FBD /* MMHTTPClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMHTTPClient.m; sourceTree = "<group>"; };
7B00EC981654BCBC00531FBD /* MMHTTPRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MMHTTPRequest.h; sourceTree = "<group>"; };
7B00EC991654BCBC00531FBD /* MMHTTPRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MMHTTPRequest.m; sourceTree = "<group>"; };
7B00EC9C1654C0A900531FBD /* VSSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VSSource.h; sourceTree = "<group>"; };
7B00EC9D1654C0A900531FBD /* VSSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = VSSource.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -58,6 +67,7 @@
7B00EC5B1654BBEB00531FBD = {
isa = PBXGroup;
children = (
7B00ECA11654C1AA00531FBD /* 3rd Party */,
7B00EC701654BBEB00531FBD /* ViewSource */,
7B00EC691654BBEB00531FBD /* Frameworks */,
7B00EC671654BBEB00531FBD /* Products */,
@ -87,6 +97,8 @@
children = (
7B00EC791654BBEB00531FBD /* VSAppDelegate.h */,
7B00EC7A1654BBEB00531FBD /* VSAppDelegate.m */,
7B00EC9C1654C0A900531FBD /* VSSource.h */,
7B00EC9D1654C0A900531FBD /* VSSource.m */,
7B00EC821654BBEB00531FBD /* VSViewController.h */,
7B00EC831654BBEB00531FBD /* VSViewController.m */,
7B00EC851654BBEB00531FBD /* VSViewController_iPhone.xib */,
@ -110,6 +122,18 @@
name = "Supporting Files";
sourceTree = "<group>";
};
7B00ECA11654C1AA00531FBD /* 3rd Party */ = {
isa = PBXGroup;
children = (
7B00EC961654BCBC00531FBD /* MMHTTPClient.h */,
7B00EC971654BCBC00531FBD /* MMHTTPClient.m */,
7B00EC981654BCBC00531FBD /* MMHTTPRequest.h */,
7B00EC991654BCBC00531FBD /* MMHTTPRequest.m */,
);
name = "3rd Party";
path = ViewSource;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -181,6 +205,9 @@
7B00EC771654BBEB00531FBD /* main.m in Sources */,
7B00EC7B1654BBEB00531FBD /* VSAppDelegate.m in Sources */,
7B00EC841654BBEB00531FBD /* VSViewController.m in Sources */,
7B00EC9A1654BCBC00531FBD /* MMHTTPClient.m in Sources */,
7B00EC9B1654BCBC00531FBD /* MMHTTPRequest.m in Sources */,
7B00EC9E1654C0A900531FBD /* VSSource.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:ViewSource.xcodeproj">
</FileRef>
</Workspace>

50
ViewSource/MMHTTPClient.h Normal file
View file

@ -0,0 +1,50 @@
//
// MMHTTPClient.h
// Marshmallows
//
// Created by Sami Samhuri on 11-09-03.
// Copyright 2011 Guru Logic. All rights reserved.
//
#import <UIKit/UIImage.h>
#import "MMHTTPRequest.h"
@interface MMHTTPClient : NSObject
+ (MMHTTPClient *) sharedClient;
+ (id) client;
+ (id) clientWithBaseURL: (NSString *)baseURL;
+ (id) clientWithBaseURL: (NSString *)baseURL timeout: (NSUInteger)timeout;
+ (NSString *) pathFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION;
+ (NSString *) urlFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION;
+ (NSString *) urlWithPath: (NSString *)path;
+ (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback;
+ (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback;
+ (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback;
+ (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback;
+ (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback;
+ (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback;
+ (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback;
+ (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback;
+ (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback;
@property (strong, nonatomic) NSString *baseURL;
@property NSUInteger timeout;
- (id) initWithBaseURL: (NSString *)baseURl;
- (id) initWithBaseURL: (NSString *)baseURl timeout: (NSUInteger)timeout;
- (NSString *) pathFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION;
- (NSString *) urlFor: (NSString *)first, ... NS_REQUIRES_NIL_TERMINATION;
- (NSString *) urlWithPath: (NSString *)path;
- (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback;
- (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback;
- (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback;
- (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback;
- (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback;
- (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback;
- (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback;
- (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback;
- (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback;
@end

288
ViewSource/MMHTTPClient.m Normal file
View file

@ -0,0 +1,288 @@
//
// MMHTTPClient.m
// Marshmallows
//
// Created by Sami Samhuri on 11-09-03.
// Copyright 2011 Guru Logic. All rights reserved.
//
#import "MMHTTPClient.h"
// Encode a string to embed in an URL.
NSString* MMHTTPURLEncode(NSString *string) {
CFStringRef urlStringRef = CFURLCreateStringByAddingPercentEscapes(NULL,
(CFStringRef) string,
NULL,
(CFStringRef) @"!*'();:@&=+$,/?%#[]",
kCFStringEncodingUTF8);
return (__bridge NSString *)urlStringRef;
}
MMHTTPClient *_sharedMMHTTPClient;
NSString *JoinURLComponents(NSString *first, va_list args)
{
NSMutableString *url = [NSMutableString string];
NSString *slash = @"";
for (NSString *arg = first; arg != nil; arg = va_arg(args, NSString *)) {
[url appendFormat: @"%@%@", slash, MMHTTPURLEncode(arg)];
slash = @"/";
}
return [NSString stringWithString: url];
}
@implementation MMHTTPClient
@synthesize baseURL = _baseURL;
@synthesize timeout = _timeout;
+ (MMHTTPClient *) sharedClient
{
if (!_sharedMMHTTPClient) {
_sharedMMHTTPClient = [[self alloc] init];
}
return _sharedMMHTTPClient;
}
+ (id) client
{
return [[self alloc] init];
}
+ (id) clientWithBaseURL: (NSString *)baseURL
{
return [[self alloc] initWithBaseURL: baseURL];
}
+ (id) clientWithBaseURL: (NSString *)baseURL timeout: (NSUInteger)timeout
{
return [[self alloc] initWithBaseURL: baseURL timeout: timeout];
}
+ (NSString *) pathFor: (NSString *)first, ...
{
va_list args;
va_start(args, first);
NSString *url = JoinURLComponents(first, args);
va_end(args);
return url;
}
+ (NSString *) urlFor: (NSString *)first, ...
{
va_list args;
va_start(args, first);
NSString *url = [[[self sharedClient] baseURL] stringByAppendingString: JoinURLComponents(first, args)];
va_end(args);
return url;
}
+ (NSString *) urlWithPath: (NSString *)path
{
return [[[self sharedClient] baseURL] stringByAppendingPathComponent: path];
}
+ (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback
{
return [[self sharedClient] request: options then: callback];
}
+ (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback
{
return [[self sharedClient] get: url then: callback];
}
+ (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback
{
return [[self sharedClient] getImage: url then: callback];
}
+ (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback
{
return [[self sharedClient] getText: url then: callback];
}
+ (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback
{
return [[self sharedClient] post: url then: callback];
}
+ (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback
{
return [[self sharedClient] post: url fields: fields then: callback];
}
+ (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback
{
return [[self sharedClient] post: url data: data then: callback];
}
+ (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback
{
return [[self sharedClient] put: url data: data then: callback];
}
+ (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback
{
return [[self sharedClient] delete: url then: callback];
}
- (id) init
{
return [self initWithBaseURL: nil timeout: MMHTTPRequestDefaultTimeout];
}
- (id) initWithBaseURL: (NSString *)baseURL
{
return [self initWithBaseURL: baseURL timeout: MMHTTPRequestDefaultTimeout];
}
- (id) initWithBaseURL: (NSString *)baseURL timeout: (NSUInteger)timeout
{
self = [super init];
if (self) {
_baseURL = [baseURL copy];
_timeout = timeout;
}
return self;
}
- (NSString *) pathFor: (NSString *)first, ...
{
va_list args;
va_start(args, first);
NSString *url = JoinURLComponents(first, args);
va_end(args);
return url;
}
- (NSString *) urlFor: (NSString *)first, ...
{
va_list args;
va_start(args, first);
NSString *url = [_baseURL stringByAppendingString: JoinURLComponents(first, args)];
va_end(args);
return url;
}
- (NSString *) urlWithPath: (NSString *)path
{
return [_baseURL stringByAppendingPathComponent: path];
}
- (MMHTTPRequest *) getImage: (NSString *)url then: (MMHTTPImageCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
url, @"url",
@"image", @"type",
nil];
return [self request: options then: (MMHTTPCallback)callback];
}
- (MMHTTPRequest *) getText: (NSString *)url then: (MMHTTPTextCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
url, @"url",
@"text", @"type",
nil];
return [self request: options then: (MMHTTPCallback)callback];
}
- (MMHTTPRequest *) get: (NSString *)url then: (MMHTTPCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
url, @"url",
@"image", @"type",
nil];
return [self request: options then: (MMHTTPCallback)callback];
}
- (MMHTTPRequest *) post: (NSString *)url then: (MMHTTPCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"POST", @"method",
url, @"url",
nil];
return [self request: options then: callback];
}
- (NSString *) encodeFields: (NSDictionary *)fields withPrefix: (NSString *)prefix
{
NSString *suffix = @"";
if (prefix) {
prefix = [NSString stringWithFormat: @"%@[", prefix];
suffix = @"]";
}
else {
prefix = @"";
}
NSMutableArray *parts = [NSMutableArray array];
NSString *value;
for (NSString *key in [fields keyEnumerator]) {
value = [fields objectForKey: key];
if ([value isKindOfClass: [NSDictionary class]]) {
[parts addObject: [self encodeFields: (NSDictionary *)value withPrefix: [NSString stringWithFormat: @"%@%@", prefix, key]]];
}
else {
[parts addObject: [NSString stringWithFormat: @"%@%@%@=%@", prefix, MMHTTPURLEncode(key), suffix, MMHTTPURLEncode(value)]];
}
}
return [parts componentsJoinedByString: @"&"];
}
- (NSString *) encodeFields: (NSDictionary *)fields
{
return [self encodeFields: fields withPrefix: nil];
}
- (MMHTTPRequest *) post: (NSString *)url fields: (NSDictionary *)fields then: (MMHTTPCallback)callback
{
NSString *body = [self encodeFields: fields];
return [self post: url data: [body dataUsingEncoding: NSUTF8StringEncoding] then: callback];
}
- (MMHTTPRequest *) post: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"POST", @"method",
url, @"url",
data, @"data",
nil];
return [self request: options then: callback];
}
- (MMHTTPRequest *) put: (NSString *)url data: (NSData *)data then: (MMHTTPCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"PUT", @"method",
url, @"url",
data, @"data",
nil];
return [self request: options then: callback];
}
- (MMHTTPRequest *) delete: (NSString *)url then: (MMHTTPCallback)callback
{
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
@"DELETE", @"method",
url, @"url",
nil];
return [self request: options then: callback];
}
- (MMHTTPRequest *) request: (NSDictionary *)options then: (MMHTTPCallback)callback
{
NSString *url = [options objectForKey: @"url"];
NSMutableDictionary *mutableOptions = [options mutableCopy];
if (_baseURL && !([url hasPrefix: @"http:"] || [url hasPrefix: @"https:"])) {
[mutableOptions setObject: [self urlWithPath: url] forKey: @"url"];
}
NSUInteger timeout = [[options objectForKey: @"timeout"] unsignedIntValue];
if (timeout == 0) {
[mutableOptions setValue: [NSNumber numberWithUnsignedInt: self.timeout] forKey: @"timeout"];
}
options = [NSDictionary dictionaryWithDictionary: mutableOptions];
return [MMHTTPRequest requestWithOptions: options callback: callback];
}
@end

View file

@ -0,0 +1,43 @@
//
// MMHTTPRequest.h
// Marshmallows
//
// Created by Sami Samhuri on 11-09-03.
// Copyright 2011 Guru Logic. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIImage.h>
#define MMHTTPRequestStatusError -1
#define MMHTTPRequestDefaultTimeout 120
typedef void (^MMHTTPCallback)(NSInteger status, id data);
typedef void (^MMHTTPTextCallback)(NSInteger status, NSString *text);
typedef void (^MMHTTPImageCallback)(NSInteger status, UIImage *image);
@interface MMHTTPRequest : NSObject
{
NSMutableData *_responseData;
}
@property (nonatomic, retain) NSURLConnection *connection;
@property (nonatomic, retain) NSMutableURLRequest *request;
@property (nonatomic, retain) NSString *method;
@property (nonatomic, retain) NSString *url;
@property (nonatomic, retain) NSMutableDictionary *headers;
@property (nonatomic, retain) NSData *data;
@property (nonatomic, retain) NSString *type;
@property (nonatomic, copy) MMHTTPCallback callback;
@property NSUInteger timeout;
@property (readonly) NSInteger statusCode;
@property (strong, readonly) NSDictionary *responseHeaders;
@property (readonly) NSData *responseData;
@property (readonly) NSString *responseText;
@property (readonly) UIImage *responseImage;
+ (id) requestWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback;
- (id) initWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback;
- (void) cancel;
@end

147
ViewSource/MMHTTPRequest.m Normal file
View file

@ -0,0 +1,147 @@
//
// MMHTTPRequest.m
// Marshmallows
//
// Created by Sami Samhuri on 11-09-03.
// Copyright 2011 Guru Logic. All rights reserved.
//
#import "MMHTTPRequest.h"
@interface MMHTTPRequest ()
- (void) _start;
@end
@implementation MMHTTPRequest
@synthesize connection = _connection;
@synthesize request = _request;
@synthesize method = _method;
@synthesize url = _url;
@synthesize headers = _headers;
@synthesize data = _data;
@synthesize type = _type;
@synthesize callback = _callback;
@synthesize timeout = _timeout;
@synthesize statusCode = _statusCode;
@synthesize responseHeaders = _responseHeaders;
+ (id) requestWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback
{
return [[self alloc] initWithOptions: options callback: callback];
}
- (id) initWithOptions: (NSDictionary *)options callback: (MMHTTPCallback)callback
{
self = [super init];
if (self) {
self.callback = callback;
self.timeout = MMHTTPRequestDefaultTimeout;
self.method = [options objectForKey: @"method"];
self.url = [options objectForKey: @"url"];
self.headers = [options objectForKey: @"headers"];
self.data = [options objectForKey: @"data"];
self.type = [options objectForKey: @"type"];
if (!self.method) self.method = @"GET";
[self _start];
}
return self;
}
- (void) cancel
{
self.callback = nil;
[_connection cancel];
}
- (NSData *) responseData
{
return [NSData dataWithData: _responseData];
}
- (NSString *) responseText
{
return [[NSString alloc] initWithBytes: _responseData.bytes
length: _responseData.length
encoding: NSUTF8StringEncoding];
}
- (UIImage *) responseImage
{
return [UIImage imageWithData: _responseData];
}
- (void) _start
{
self.request = [NSMutableURLRequest requestWithURL: [NSURL URLWithString: self.url]
cachePolicy: NSURLRequestUseProtocolCachePolicy
timeoutInterval: self.timeout];
[self.request setHTTPMethod: self.method];
if (self.data && ([self.method isEqualToString: @"POST"] || [self.method isEqualToString: @"PUT"])) {
[self.request setHTTPBody: self.data];
}
if (self.headers) {
for (NSString *key in self.headers) {
[self.request setValue: [self.headers objectForKey: key] forHTTPHeaderField: key];
}
}
self.connection = [NSURLConnection connectionWithRequest: self.request delegate: self];
[self.connection start];
}
#pragma mark - NSURLConnection delegate methods
- (void) connection: (NSURLConnection *)connection didReceiveResponse: (NSURLResponse *)response
{
if ([response respondsToSelector: @selector(statusCode)])
{
_statusCode = [(NSHTTPURLResponse *)response statusCode];
_responseHeaders = [(NSHTTPURLResponse *)response allHeaderFields];
}
else {
_statusCode = 500;
_responseHeaders = [[NSDictionary alloc] init];
}
_responseData = [[NSMutableData alloc] init];
}
- (void) connection: (NSURLConnection *)connection didReceiveData: (NSData *)data
{
[_responseData appendData: data];
}
- (void) connection: (NSURLConnection *)connection didFailWithError: (NSError *)error
{
_responseData = nil;
_statusCode = MMHTTPRequestStatusError;
if (self.callback) {
self.callback(self.statusCode, error);
}
}
- (void) connectionDidFinishLoading: (NSURLConnection *)connection
{
id data = nil;
if (self.callback && self.statusCode == 200) {
if ([self.type isEqualToString: @"text"]) {
data = self.responseText;
}
else if ([self.type isEqualToString: @"image"]) {
data = self.responseImage;
}
else {
data = self.responseData;
}
}
if (self.callback) {
self.callback(self.statusCode, data);
}
}
@end

View file

@ -7,8 +7,8 @@
//
#import "VSAppDelegate.h"
#import "VSViewController.h"
#import "VSSource.h"
@implementation VSAppDelegate
@ -21,6 +21,12 @@
} else {
self.viewController = [[VSViewController alloc] initWithNibName:@"VSViewController_iPad" bundle:nil];
}
NSString *url = @"http://samhuri.net";
NSRange scrollRange = NSMakeRange(0, 0);
VSSource *source = [VSSource sourceWithURL: url scrollRange: scrollRange];
[self.viewController loadSource: source];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;

27
ViewSource/VSSource.h Normal file
View file

@ -0,0 +1,27 @@
//
// VSSource.h
// ViewSource
//
// Created by Sami Samhuri on 2012-11-14.
// Copyright (c) 2012 Sami Samhuri. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^VSSourceCallback)(BOOL ok, NSString *text);
@interface VSSource : NSObject
@property (strong, nonatomic) NSString *url;
@property (assign, nonatomic) NSRange scrollRange;
@property (strong, nonatomic) NSString *text;
+ (id) sourceWithURL: (NSString *)url scrollRange: (NSRange)scrollRange;
+ (id) sourceWithURL: (NSString *)url;
- (id) initWithURL: (NSString *)url scrollRange: (NSRange)scrollRange;
- (id) initWithURL: (NSString *)url;
- (void) fetch: (VSSourceCallback)callback;
- (void) cancel;
@end

73
ViewSource/VSSource.m Normal file
View file

@ -0,0 +1,73 @@
//
// VSSource.m
// ViewSource
//
// Created by Sami Samhuri on 2012-11-14.
// Copyright (c) 2012 Sami Samhuri. All rights reserved.
//
#import "VSSource.h"
#import "MMHTTPClient.h"
@interface VSSource ()
@property (strong, nonatomic) MMHTTPRequest *request;
@property (copy, nonatomic) VSSourceCallback callback;
@end
@implementation VSSource
@synthesize scrollRange = _scrollRange;
@synthesize text = _text;
@synthesize url = _url;
+ (id) sourceWithURL: (NSString *)url scrollRange: (NSRange)scrollRange
{
return [[self alloc] initWithURL: url scrollRange: scrollRange];
}
+ (id) sourceWithURL: (NSString *)url
{
return [self sourceWithURL: url scrollRange: NSMakeRange(0, 0)];
}
- (id) initWithURL: (NSString *)url scrollRange: (NSRange)scrollRange
{
self = [super init];
if (self) {
self.url = url;
self.scrollRange = scrollRange;
}
return self;
}
- (id) initWithURL: (NSString *)url
{
return [self initWithURL: url scrollRange: NSMakeRange(0, 0)];
}
- (void) fetch: (VSSourceCallback)callback;
{
if (self.text) {
callback(YES, self.text);
}
else {
self.callback = callback;
self.request = [MMHTTPClient getText: self.url then: ^(NSInteger status, NSString *text) {
self.text = text;
if (self.callback) {
self.callback(status == 200, self.text);
}
}];
}
}
- (void) cancel
{
[self.request cancel];
self.request = nil;
self.callback = nil;
self.text = nil;
}
@end

View file

@ -7,7 +7,13 @@
//
#import <UIKit/UIKit.h>
#import "VSSource.h"
@interface VSViewController : UIViewController
@property (strong, nonatomic) VSSource *source;
@property (strong, nonatomic) IBOutlet UITextView *sourceView;
- (void) loadSource: (VSSource *)source;
@end

View file

@ -9,21 +9,50 @@
#import "VSViewController.h"
@interface VSViewController ()
- (void) update;
@end
@implementation VSViewController
- (void)viewDidLoad
@synthesize source = _source;
- (void) viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
if (self.source) {
[self update];
}
}
- (void)didReceiveMemoryWarning
- (void) loadSource: (VSSource *)source
{
self.source = source;
[self update];
}
- (void) update
{
if (self.sourceView && self.source) {
if (self.source.text) {
self.sourceView.text = self.source.text;
[self.sourceView scrollRangeToVisible: self.source.scrollRange];
}
else {
[self.source fetch: ^(BOOL ok, NSString *text) {
if (ok) {
[self update];
}
else {
NSLog(@"error fetching %@", self.source.url);
}
}];
}
}
}
- (void) didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end

View file

@ -2,16 +2,18 @@
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1536</int>
<string key="IBDocument.SystemVersion">12A206j</string>
<string key="IBDocument.InterfaceBuilderVersion">2519</string>
<string key="IBDocument.AppKitVersion">1172.1</string>
<string key="IBDocument.HIToolboxVersion">613.00</string>
<string key="IBDocument.SystemVersion">12C60</string>
<string key="IBDocument.InterfaceBuilderVersion">2840</string>
<string key="IBDocument.AppKitVersion">1187.34</string>
<string key="IBDocument.HIToolboxVersion">625.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">1856</string>
<string key="NS.object.0">1926</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>IBProxyObject</string>
<string>IBUITextView</string>
<string>IBUIView</string>
</array>
<array key="IBDocument.PluginDependencies">
@ -33,6 +35,38 @@
<object class="IBUIView" id="766721923">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUITextView" id="49274661">
<reference key="NSNextResponder" ref="766721923"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{768, 1004}</string>
<reference key="NSSuperview" ref="766721923"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MSAxIDEAA</bytes>
</object>
<bool key="IBUIClipsSubviews">YES</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<bool key="IBUIShowsHorizontalScrollIndicator">NO</bool>
<string key="IBUIText">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
<int key="IBUIAutocapitalizationType">2</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<int key="type">1</int>
<double key="pointSize">14</double>
</object>
<object class="NSFont" key="IBUIFont">
<string key="NSName">Helvetica</string>
<double key="NSSize">14</double>
<int key="NSfFlags">16</int>
</object>
</object>
</array>
<string key="NSFrame">{{0, 20}, {768, 1004}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
@ -59,6 +93,14 @@
</object>
<int key="connectionID">3</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">sourceView</string>
<reference key="source" ref="841351856"/>
<reference key="destination" ref="49274661"/>
</object>
<int key="connectionID">9</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@ -82,8 +124,100 @@
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="766721923"/>
<array class="NSMutableArray" key="children">
<reference ref="49274661"/>
<object class="IBNSLayoutConstraint" id="743327192">
<reference key="firstItem" ref="49274661"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="766721923"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="766721923"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="561193563">
<reference key="firstItem" ref="49274661"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="766721923"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="766721923"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="122218691">
<reference key="firstItem" ref="49274661"/>
<int key="firstAttribute">4</int>
<int key="relation">0</int>
<reference key="secondItem" ref="766721923"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="766721923"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="519000636">
<reference key="firstItem" ref="49274661"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="766721923"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="766721923"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="49274661"/>
<reference key="parent" ref="766721923"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="519000636"/>
<reference key="parent" ref="766721923"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="122218691"/>
<reference key="parent" ref="766721923"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">7</int>
<reference key="object" ref="561193563"/>
<reference key="parent" ref="766721923"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="743327192"/>
<reference key="parent" ref="766721923"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -92,18 +226,49 @@
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<array key="2.IBViewMetadataConstraints">
<reference ref="519000636"/>
<reference ref="122218691"/>
<reference ref="561193563"/>
<reference ref="743327192"/>
</array>
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<boolean value="NO" key="4.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="7.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">3</int>
<int key="maxID">9</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">VSViewController</string>
<string key="superclassName">UIViewController</string>
<object class="NSMutableDictionary" key="outlets">
<string key="NS.key.0">sourceView</string>
<string key="NS.object.0">UITextView</string>
</object>
<object class="NSMutableDictionary" key="toOneOutletInfosByName">
<string key="NS.key.0">sourceView</string>
<object class="IBToOneOutletInfo" key="NS.object.0">
<string key="name">sourceView</string>
<string key="candidateClassName">UITextView</string>
</object>
</object>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/VSViewController.h</string>
@ -116,6 +281,6 @@
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<bool key="IBDocument.UseAutolayout">YES</bool>
<string key="IBCocoaTouchPluginVersion">1856</string>
<string key="IBCocoaTouchPluginVersion">1926</string>
</data>
</archive>

View file

@ -2,16 +2,18 @@
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1536</int>
<string key="IBDocument.SystemVersion">12A269</string>
<string key="IBDocument.InterfaceBuilderVersion">2835</string>
<string key="IBDocument.AppKitVersion">1187</string>
<string key="IBDocument.HIToolboxVersion">624.00</string>
<string key="IBDocument.SystemVersion">12C60</string>
<string key="IBDocument.InterfaceBuilderVersion">2840</string>
<string key="IBDocument.AppKitVersion">1187.34</string>
<string key="IBDocument.HIToolboxVersion">625.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">1919</string>
<string key="NS.object.0">1926</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>IBProxyObject</string>
<string>IBUITextView</string>
<string>IBUIView</string>
</array>
<array key="IBDocument.PluginDependencies">
@ -33,10 +35,38 @@
<object class="IBUIView" id="774585933">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUITextView" id="589318973">
<reference key="NSNextResponder" ref="774585933"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{320, 548}</string>
<reference key="NSSuperview" ref="774585933"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MSAxIDEAA</bytes>
</object>
<bool key="IBUIClipsSubviews">YES</bool>
<bool key="IBUIMultipleTouchEnabled">YES</bool>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
<string key="IBUIText">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<object class="IBUITextInputTraits" key="IBUITextInputTraits">
<int key="IBUIAutocapitalizationType">2</int>
<string key="targetRuntimeIdentifier">IBCocoaTouchFramework</string>
</object>
<object class="IBUIFontDescription" key="IBUIFontDescription">
<int key="type">1</int>
<double key="pointSize">14</double>
</object>
<object class="NSFont" key="IBUIFont">
<string key="NSName">Helvetica</string>
<double key="NSSize">14</double>
<int key="NSfFlags">16</int>
</object>
</object>
</array>
<string key="NSFrame">{{0, 20}, {320, 548}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC43NQA</bytes>
@ -76,6 +106,14 @@
</object>
<int key="connectionID">7</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchOutletConnection" key="connection">
<string key="label">sourceView</string>
<reference key="source" ref="372490531"/>
<reference key="destination" ref="589318973"/>
</object>
<int key="connectionID">14</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@ -99,8 +137,100 @@
<object class="IBObjectRecord">
<int key="objectID">6</int>
<reference key="object" ref="774585933"/>
<array class="NSMutableArray" key="children">
<reference ref="589318973"/>
<object class="IBNSLayoutConstraint" id="611089412">
<reference key="firstItem" ref="589318973"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="774585933"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="774585933"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="176107381">
<reference key="firstItem" ref="589318973"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="774585933"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="774585933"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="428914871">
<reference key="firstItem" ref="589318973"/>
<int key="firstAttribute">4</int>
<int key="relation">0</int>
<reference key="secondItem" ref="774585933"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="774585933"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="201961901">
<reference key="firstItem" ref="589318973"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="774585933"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBLayoutConstant" key="constant">
<double key="value">0.0</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="774585933"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">8</int>
<reference key="object" ref="589318973"/>
<reference key="parent" ref="774585933"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">9</int>
<reference key="object" ref="201961901"/>
<reference key="parent" ref="774585933"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">10</int>
<reference key="object" ref="428914871"/>
<reference key="parent" ref="774585933"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">11</int>
<reference key="object" ref="176107381"/>
<reference key="parent" ref="774585933"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">12</int>
<reference key="object" ref="611089412"/>
<reference key="parent" ref="774585933"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -108,31 +238,32 @@
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="11.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="6.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<array key="6.IBViewMetadataConstraints">
<reference ref="201961901"/>
<reference ref="428914871"/>
<reference ref="176107381"/>
<reference ref="611089412"/>
</array>
<string key="8.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<boolean value="NO" key="8.IBViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">7</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">VSViewController</string>
<string key="superclassName">UIViewController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/VSViewController.h</string>
</object>
</object>
</array>
<int key="maxID">14</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes"/>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaTouchFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<bool key="IBDocument.UseAutolayout">YES</bool>
<string key="IBCocoaTouchPluginVersion">1919</string>
<string key="IBCocoaTouchPluginVersion">1926</string>
</data>
</archive>