Retreive tweet information (text&image) from timeline in TWTRTimelineViewController - Objective c - ios

Good afternoon,
I have an app that asks the user to log in thanks to twitter's doc found there: Log in with twitter. Then, I can successfully load the user's timeline. This timeline loads in a NavigationController which has the interface TWTRTimelineViewController. Now, I would like that when one user holds his finger on a tweet, or just click on one tweet, rather than opening Safari to display it, it pops up a button where I'll be able to work on the tweet after clicking. I will need to get access to the text and the image of the tweet.
From my understanding, I will need to delegate all the tweets to some kind of TWTRTweetView controller to work on them but I'm not so sure how, since I'm completely new to this. I did try to read the doc but couldn't really get it, and most of the example are written in Swift. I'm also not sure how I'm supposed to access the tweet's properties. I have tried STTwitter where I played with some JSON formatted texts and where I was able to get the text and the image URL but I can't figure out how to do so directly with TwitterKit. Here's my actual code of the controller that display the timeline:
#import "TwitterTimelineViewController.h"
#import <TwitterKit/TwitterKit.h>
#import "AppDelegate.h"
#interface TwitterTimelineViewController ()
#property (strong, nonatomic) IBOutlet UITableView *TwitterTableView;
#end
#implementation TwitterTimelineViewController
TWTRUserTimelineDataSource *userTimelineDataSource;
- (void)viewDidLoad {
[super viewDidLoad];
AppDelegate *delegate=(AppDelegate *)[[UIApplication sharedApplication] delegate];
[[Twitter sharedInstance] startWithConsumerKey:#"myConsumerKey" consumerSecret:#"myConsumerSecretKey"];
TWTRAPIClient *APIClient = [[TWTRAPIClient alloc] init];
userTimelineDataSource = [[TWTRUserTimelineDataSource alloc] initWithScreenName:delegate.twitterUsername APIClient:APIClient];
self.dataSource = userTimelineDataSource;
}
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
return [[Twitter sharedInstance] application:app openURL:url options:options];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Any help would be awesome!
Cheers,
Theo.

Found the answer myself. For anyone struggling with the same issue, here the code I wrote. A bit messy but it works.
-(IBAction)ShowTweets: (id) sender{
UIButton *clicked = (UIButton *) sender;
NSString *tweetToDecryptIndex = [NSString stringWithFormat: #"%ld", (long)clicked.tag];
//gets all tweets from current timeline
NSArray *allTweets = self.snapshotTweets;
//look the tweets, get the URL and removes it to get the text only
NSDataDetector *detect = [[NSDataDetector alloc] initWithTypes:NSTextCheckingTypeLink error:nil];
//gets the single tweet from clicked button
TWTRTweet *tweet = [allTweets objectAtIndex:(long)clicked.tag];
NSString *content = tweet.text; //gets the text
NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil];
NSArray *matches = [linkDetector matchesInString:content options:0 range:NSMakeRange(0, [content length])]; //find the URL
NSURL *url; //contains the url from the text of the tweet
NSString *ciph; //text from tweet without the url
for (NSTextCheckingResult *match in matches) {
if ([match resultType] == NSTextCheckingTypeLink) {
url = [match URL];
ciph = [content substringToIndex:content.length-url.absoluteString.length];
}
}
//Now, ask a JSON answer from twitter of the specific tweet using its ID
TWTRAPIClient *client = [[TWTRAPIClient alloc] init];
NSString *statusesShowEndpoint = #"https://api.twitter.com/1.1/statuses/show.json";
NSDictionary *params = #{#"id" : tweet.tweetID};
NSError *clientError;
NSURLRequest *request = [client URLRequestWithMethod:#"GET" URL:statusesShowEndpoint parameters:params error:&clientError];
if (request) {
[client sendTwitterRequest:request completion:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data) {
NSError *jsonError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:&jsonError];
//NSLog(#"%#", json);
//looking for the media_url
NSString *media = [json valueForKeyPath:#"entities.media"];
NSArray *urlArray = [media valueForKey:#"media_url_https"];
//finally getting the url as a string
NSMutableString * urlOfImageString = [[NSMutableString alloc] init];
for (NSObject * obj in urlArray)
{
[urlOfImageString appendString:[obj description]];
}
//NSLog(#"%#",urlOfImageString);
//constructing name for image to write in path
NSString *tweetID = tweet.tweetID;
NSString *imgName = [tweetID stringByAppendingString:#".jpg"];
NSString *tmp = [#"/your/path" stringByAppendingString:imgName];
//NSLog(#"%#", tmp);
//Now writting the image
NSURL *urlOfImageUrl = [NSURL URLWithString:urlOfImageString];
NSData *imageData = [NSData dataWithContentsOfURL:urlOfImageUrl];
}
else {
NSLog(#"Error: %#", connectionError);
}
}];
}
else {
NSLog(#"Error: %#", clientError);
}

Related

How can I make a request to aws cloudsearch using the AWS iOS SDK?

I have a client that runs their search functionality on their website through cloudsearch. I have been going through the documentation for days, and haven't been able to make a successful search request. I created an NSMutableRequest object, and am running that request through the AWSSignature method [signature interceptRequest:request]; but my task.result is coming back (null).
Here is my code:
AWSTask *task = [signature interceptRequest:request];
[task continueWithBlock:^id _Nullable(AWSTask * _Nonnull task) {
NSLog(#"task.result fromSearch:%#", task.result);
NSData *responseData = task.result;
NSString* newStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"newStr:%#", newStr);
NSLog(#"task.error:%#", task.error);
return nil;
}];
Am I on the right track, or is there a better way to do this through the aws iOS sdk?
To put a little more flesh on the bones of Robert's comment, I did it with some help from AFNetworking like so:
#import <AWSCore/AWSSignature.h>
#import <AWSCore/AWSService.h>
#import <AWSCore/AWSCategory.h>
#import <AWSCore/AWSCredentialsProvider.h>
#import <AWSCore/AWSTask.h>
#import "AFNetworking.h"
- (void)viewDidLoad {
[super viewDidLoad];
self.queue = [[NSOperationQueue alloc] init];
}
- (void)performSearch {
AWSAnonymousCredentialsProvider* credentialsProvider = [[AWSAnonymousCredentialsProvider alloc] init];
NSString* searchHost = #"<CloudSearchEndPoint>.eu-west-1.cloudsearch.amazonaws.com";
NSString* query = [self.searchTerms aws_stringWithURLEncoding];
NSURL* searchURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://%#/2013-01-01/search?q=%#", searchHost, query]];
AWSEndpoint* endpoint = [[AWSEndpoint alloc] initWithURL:searchURL];
AWSSignatureV4Signer* signer = [[AWSSignatureV4Signer alloc] initWithCredentialsProvider:credentialsProvider endpoint:endpoint];
NSMutableURLRequest* mutableRequest = [[NSMutableURLRequest alloc] initWithURL:searchURL];
AWSTask* task = [signer interceptRequest:mutableRequest];
[task continueWithBlock:^id(AWSTask* _Nonnull t) {
if (t.error) {
NSLog(#"Error: %#", t.error);
} else if (t.completed) {
NSLog(#"Result is %#", t.result);
}
AFJSONRequestOperation* operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:mutableRequest success:^(NSURLRequest* request, NSHTTPURLResponse* response, id JSON) {
NSLog(#"Success fetching results!");
if (JSON) {
NSDictionary* hitsContainer = [JSON objectForKey:#"hits"];
NSArray* hits = [hitsContainer objectForKey:#"hit"];
NSMutableArray* allResults = [[NSMutableArray alloc] initWithCapacity:hits.count];
for (NSDictionary* hit in hits) {
NSDictionary* fields = [hit objectForKey:#"fields"];
[allResults addObject:fields];
}
self.searchResults = allResults;
[self.tableView reloadData];
}
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) {
NSLog(#"Failure fetching search results :-( %#", error);
}
];
[self.queue addOperation:operation];
return nil;
}];

Best way to store data for an iPhone calendaring app

I am working on an iPhone app. It is a Enterprise calendaring app for my agency. We have a RESTful API backend connected to a web application where the appointments are entered. The appointments for an individual are to show up on that user’s iPhone. Data is sent by XML. There are only 3 or 4 appointments per day and less than 10 fields per record, so not a lot of data is transferred at a time (just the selected day’s information).
I tried to design this with an array on the iPhone for the parsed data, but the security checking on the web server makes the application time out when loading the data, and I didn’t handle the asynchronous processing well.
Now I’m wondering if I’m even approaching the problem correctly. Would it be better to use Core Data to store the appointments and then work to update the Core Data store in the background? I know I need to update the data outside of the loading the table process. I’m just at a loss for the best way to approach this.
I have looked through the site for information as to how to approach this. I have tried looking in books. Any help would be appreciated.
Security.h
typedef void (^touchIDComplete)(BOOL);
typedef void (^fileExists)(BOOL);
typedef void (^sessionVerify)(BOOL);
typedef void (^parsingData)(BOOL);
typedef void (^touchIDSuccess)(BOOL);
typedef void (^sessionRetrieved)(BOOL);
typedef void (^touchIDComplete)(BOOL);
typedef void (^sessionReading)(BOOL);
typedef void (^fillArray)(BOOL);
typedef void (^getTheData)(NSData *myData, NSError *error);
typedef void (^gettingESNBlock)(NSString *myESN, NSString *newSession, BOOL success, NSError *error);
typedef void (^checkingESNBlock)(NSString *myESN, NSString *sessionInfo, BOOL success, NSError *error);
#interface Security : NSObject
#property (strong, nonatomic) NSArray *types;
#property (strong, nonatomic) NSArray *esn;
#property (strong, nonatomic) NSString *idfv;
#property (strong, nonatomic) NSData *parseData;
#property (strong, nonatomic) NSString *sessionDetail;
#property (strong, nonatomic) NSString *loginFinished;
#property (strong, nonatomic) NSMutableURLRequest *request;
#property (atomic) NSString *passESN;
- (void)waitForData:(sessionVerify)compblock;
- (void)waitForFile:(fileExists)compblock;
- (void)waitForESN:(parsingData)compblock;
- (void)findESN:(gettingESNBlock)callback;
- (void)checkThumb:(touchIDSuccess)compblock;
- (void)readIt:(sessionRetrieved)compblock;
- (void)readNewSession:(sessionReading)compblock;
- (void)doTheWork:(NSString *)theESN withSession:(NSString *)newSession withSuccess:(BOOL)success error:(NSError *)error;
- (void)checkESN:(checkingESNBlock)callback;
- (void)checkTheSession:(NSString *)oldESN withSession:(NSString *)oldSession withSuccess:(BOOL)success error:(NSError *)error;
- (void)fillAppointmentData:(fillArray)compblock;
- (void)gettingData:(getTheData)compblock;
#end
Security.m
#implementation Security
void(^getESNForCallback)(NSString *myESN, NSString *newSession, BOOL success, NSError *error);
void(^checkESNWithCallback)(NSString *myESN, NSString *oldSession, BOOL success, NSError *error);
- (void)waitForFile:(fileExists) compblock {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSArray *directoryPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [directoryPaths objectAtIndex:0];
NSString *fullPath = [documentsDirectoryPath stringByAppendingString:#"/session.txt"];
compblock([fileManager fileExistsAtPath:fullPath]);
}
- (void) waitForData:(sessionVerify) compblock {
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:self.request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
if (statusCode == 401) {
// Insert process for thumbprint and session cookie pull
NSFileManager *fileManagerThree = [NSFileManager defaultManager];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *sessionPath = [documentsPath stringByAppendingPathComponent:#"session.txt"];
NSError *error;
BOOL success = [fileManagerThree removeItemAtPath:sessionPath error:&error];
if (success) {
} else {
}
} else {
return;
}
}
}
self.parseData = data;
compblock (YES);
}];
[task resume];
}
- (void)waitForESN:(parsingData) compblock {
ParseTypeXML *myParser = [[ParseTypeXML alloc] initWithData:self.parseData];
VariableStore *globals = [VariableStore sharedInstance];
if ([myParser.esn count] == 0) {
globals.user_esn = #"Error";
compblock(YES);
} else {
globals.user_esn = myParser.esn[0];
compblock(YES);
}
}
- (void)findESN:(gettingESNBlock)callback {
getESNForCallback = callback;
VariableStore *globals = [VariableStore sharedInstance];
[self doTheWork:globals.user_esn withSession:globals.sessionInfo withSuccess:YES error:nil];
}
- (void)doTheWork:(NSString *)theESN withSession:(NSString *)newSession withSuccess:(BOOL)success error:(NSError *)error {
[self checkThumb:^(BOOL finished) {
if(finished) {
[self readIt:^(BOOL newFile) {
if (newFile) {
[self readNewSession:^(BOOL seen) {
if (seen) {
VariableStore *globals = [VariableStore sharedInstance];
NSDictionary *cookieProperties = [NSDictionary dictionaryWithObjectsAndKeys:
#"ollie/", NSHTTPCookieDomain,
#"\\", NSHTTPCookiePath,
#"Cookie", NSHTTPCookieName,
globals.sessionInfo, NSHTTPCookieValue,
nil];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
NSArray *cookieArray = [NSArray arrayWithObject:cookie];
NSDictionary *headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArray];
NSMutableString *url = [[NSMutableString alloc] initWithString:#"https://company.com/file.php"];
NSURL *urlNew = [NSURL URLWithString:url];
self.request = [NSMutableURLRequest requestWithURL:urlNew];
[self.request setHTTPMethod:#"GET"];
[self.request setAllHTTPHeaderFields:headers];
[self waitForData:^(BOOL dataReceived) {
if (dataReceived) {
[self waitForESN:^(BOOL esnFound) {
if (esnFound) {
VariableStore *globals = [VariableStore sharedInstance];
getESNForCallback(globals.user_esn, globals.sessionInfo, success, error);
}
}];
}
}];
}
}];
}
}];
}
}];
}
- (void)checkThumb:(touchIDSuccess)compblock {
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
// Authenticate User
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:#"You need to log in."
reply:^(BOOL success, NSError * _Nullable error) {
if (success) {
NSLog(#"success");
compblock(YES);
} else {
switch (error.code) {
case LAErrorAuthenticationFailed:
break;
case LAErrorUserCancel:
break;
case LAErrorUserFallback:
break;
default:
break;
}
}
}];
}
}
- (void)readIt:(sessionRetrieved)compblock {
NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
NSString *url = #"https://company.com/specialstring.php";
NSMutableString *postText = [[NSMutableString alloc] init];
[postText appendString:idfv];
NSString *postBody = [NSString stringWithString:postText];
XMLPostSecurity *postAction = [[XMLPostSecurity alloc] init];
VariableStore *globals = [VariableStore sharedInstance];
globals.sessionInfo = [postAction sendPostRequestToUrl:url withBody:postBody];
FileSaving *saver = [[FileSaving alloc] init];
[saver saveSession:globals.sessionInfo];
compblock(YES);
}
-(void)readNewSession:(sessionReading)compblock {
NSFileManager *fileManagerTwo;
NSData *dataBuffer;
fileManagerTwo = [NSFileManager defaultManager];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *filePath = [documentsDirectory stringByAppendingString:#"/session.txt"];
dataBuffer = [fileManagerTwo contentsAtPath:filePath];
VariableStore *globals = [VariableStore sharedInstance];
globals.sessionInfo = [[NSString alloc] initWithData:dataBuffer encoding:(NSASCIIStringEncoding)];
compblock(YES);
}
- (void)checkESN:(checkingESNBlock)callback {
checkESNWithCallback = callback;
VariableStore *globals = [VariableStore sharedInstance];
[self checkTheSession:globals.user_esn withSession:globals.sessionInfo withSuccess:YES error:nil];
}
- (void)checkTheSession:(NSString *)theESN withSession:(NSString *)oldSession withSuccess:(BOOL)success error:(NSError *)error {
[self readNewSession:^(BOOL seen) {
if (seen) {
VariableStore *globals = [VariableStore sharedInstance];
NSDictionary *cookieProperties = [NSDictionary dictionaryWithObjectsAndKeys:
#"ollie/", NSHTTPCookieDomain,
#"\\", NSHTTPCookiePath,
#"Cookie", NSHTTPCookieName,
globals.sessionInfo, NSHTTPCookieValue,
nil];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
NSArray *cookieArray = [NSArray arrayWithObject:cookie];
NSDictionary *headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArray];
NSMutableString *url = [[NSMutableString alloc] initWithString:#"https://company.com/file.php"];
NSURL *urlNew = [NSURL URLWithString:url];
self.request = [NSMutableURLRequest requestWithURL:urlNew];
[self.request setHTTPMethod:#"GET"];
[self.request setAllHTTPHeaderFields:headers];
[self waitForData:^(BOOL dataReceived) {
if (dataReceived) {
[self waitForESN:^(BOOL esnFound) {
if (esnFound) {
VariableStore *globals = [VariableStore sharedInstance];
checkESNWithCallback(globals.user_esn, globals.sessionInfo, success, error);
}
}];
}
}];
}
}];
}
- (void)fillAppointmentData:(fillArray)compblock {
VariableStore *globals = [VariableStore sharedInstance];
NSDictionary *cookieProperties = [NSDictionary dictionaryWithObjectsAndKeys:
#"ollie/", NSHTTPCookieDomain,
#"\\", NSHTTPCookiePath,
#"Cookie", NSHTTPCookieName,
globals.sessionInfo, NSHTTPCookieValue,
nil];
NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:cookieProperties];
NSArray *cookieArray = [NSArray arrayWithObject:cookie];
NSDictionary *headers = [NSHTTPCookie requestHeaderFieldsWithCookies:cookieArray];
NSMutableString *url = [[NSMutableString alloc] initWithString:#"https://company.com/file2.php?adb="];
[url appendString:globals.chosenDate];
[url appendString:#"&esn="];
[url appendString:globals.user_esn];
NSURL *urlNew = [NSURL URLWithString:url];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:urlNew];
[request setHTTPMethod:#"GET"];
[request setAllHTTPHeaderFields:headers];
[self gettingData:^(NSData *myData, NSError *error) {
if (myData != nil) {
ParseXML *myParser = [[ParseXML alloc] initWithData:myData];
[globals.appointmentData removeAllObjects];
[globals.appointmentData addObjectsFromArray:myParser.items];
}
}];
}
- (void) gettingData:(getTheData) compblock {
VariableStore *globals = [VariableStore sharedInstance];
globals.got401 = nil;
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:self.request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
return;
}
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSInteger statusCode = [(NSHTTPURLResponse *)response statusCode];
if (statusCode != 200) {
if (statusCode == 401) {
// Insert process for thumbprint and session cookie pull
NSFileManager *fileManagerThree = [NSFileManager defaultManager];
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *sessionPath = [documentsPath stringByAppendingPathComponent:#"session.txt"];
NSError *error;
BOOL success = [fileManagerThree removeItemAtPath:sessionPath error:&error];
if (success) {
} else {
}
globals.got401 = #"Error";
} else {
return;
}
}
}
self.parseData = data;
}];
[task resume];
}
#end
If you only have 3 or 4 appointments worth of data stored locally then the answer is "whatever is easiest for you." It really doesn't matter. You could convert the data to morse code and save dots and dashes and then read that and it would still be small and fast enough.
You can save the data to a plist, serialize it using NSCoding, save it as a SQLite database, or even write the XML and convert it back to an array on reading it (although the XML option is probably the slowest/least efficient.)
Core Data is very powerful (and very cool) but it also has a very steep learning curve. I would not recommend it until you are comfortable working with iOS.
If your application is timing out then there is probably something else wrong. Edit your question to show the code for the problem area and perhaps we can help.

Why does authentication not work with my ASP.NET REST API?

I setup an ASP.NET REST API, and am trying to connect through iOS. The same error continues to appear, and I am not sure where the connection is "broken". In NSLog the link appears with both slashes rather than a forward slash as is in the NSString. Can anyone show me why this is not connecting?
Completion block log:
2015-02-08 23:19:00.795 b2bGatewayWebview[7266:548905] Loading... ["method","interface","parameters","UserAuthentication","http:\/\/website.com\/folder\/Handler1.ashx",{"userName":"DummyAcct","passsword":"DummyPwd"}]
2015-02-08 23:19:00.796 b2bGatewayWebview[7266:548905] Loading... {"method":"Getmembers","interface":"http:\/\/website.com\/folder\/Handler1.ashx","parameters":{"username":"DummyAcct"}}
2015-02-08 23:19:00.795 b2bGatewayWebview[7266:548861] View did load called.
2015-02-08 23:19:01.525 b2bGatewayWebview[7266:548937] done
2015-02-08 23:19:01.537 b2bGatewayWebview[7266:548937] RAW response = {
"Successful": false,
"ErrorMessage": "Internal server error"
}
RestAPI.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#interface RestAPI: UIViewController
#property (nonatomic, strong) NSURL *url;
#property (nonatomic, strong) NSString *interface;
-(void) CreateNewAccount:(NSString*)ausername password:(NSString*)apassword completionHandler:(void(^)(NSDictionary *dictionary, NSError *error))handler;
-(void) Getmembers:(NSString*)ausername completionHandler:(void(^)(NSDictionary *dictionary, NSError *error))handler;
-(void) UserAuthentication:(NSString*)auserName passsword:(NSString*)apasssword completionHandler:(void(^)(NSDictionary *dictionary, NSError *error))handler;
#end
RestAPI.m
#import "RestAPI.h"
#implementation RestAPI
#synthesize url;
#synthesize interface;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *initialLink = #"http://website.com/Handler1.ashx";
[self setInterface:initialLink];
NSString *username = #"DummyAcct";
NSString *password = #"DummyPswd";
//asynchronously call login method
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self UserAuthentication:username passsword:password completionHandler:^(NSDictionary *dictionary, NSError *error) {
NSLog(#"Login method called.");
}];
[self Getmembers:username completionHandler:^(NSDictionary *dictionary, NSError *error) {
nil;
}];
});
NSLog(#"View did load called.");
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (id) init
{
self = [super init];
if (self) {
[self setUrl: [NSURL URLWithString: #"http://website.com/Handler1.ashx"]];
[self setInterface:#"http://website.com/Handler1.ashx"];
}
return self;
}
- (void)load:(NSData*)data completionHandler:(void(^)(NSURLResponse *response, NSData *data, NSError *error))handler
{
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Loading... %#", s);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:data];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue
completionHandler:handler];
}
- (void) Getmembers:(NSString*)ausername completionHandler:(void(^)(NSDictionary *dictionary, NSError *error))handler
{
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
[d setValue:interface forKey:#"interface"];
[d setValue:#"Getmembers" forKey:#"method"];
NSMutableDictionary *p = [[NSMutableDictionary alloc] init];
[p setValue:ausername forKey:#"username"];
[d setValue:p forKey:#"parameters"];
NSData *data = [NSJSONSerialization dataWithJSONObject:d options:0 error:nil];
[self load:data completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"done");
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"RAW response = %#", s);
NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
handler(d, error);
}];
}
//login method
-(void) UserAuthentication:(NSString*)auserName passsword:(NSString*)apasssword completionHandler:(void(^)(NSDictionary *dictionary, NSError *error))handler
{
//NSMutableArray *a = [[NSMutableArray alloc] init];
NSMutableDictionary *d = [[NSMutableDictionary alloc] init];
[d setValue:interface forKey:#"interface"];
//[a setValue:interface forKey:#"interface"];
[d setValue:#"UserAuthentication" forKey:#"method"];
//[a setValue:#"UserAuthentication" forKey:#"method"];
NSMutableDictionary *p = [[NSMutableDictionary alloc] init];
[p setValue:auserName forKey:#"userName"];
[p setValue:apasssword forKey:#"passsword"];
[d setValue:p forKey:#"parameters"];
//[a setValue:p forKey:#"parameters"];
NSMutableArray *dictAllKeys=[NSMutableArray arrayWithArray:[d allKeys]];
NSMutableArray *dictAllValues=[NSMutableArray arrayWithArray:[d allValues]];
NSMutableArray *keysAndValues=[NSMutableArray arrayWithArray:[dictAllKeys arrayByAddingObjectsFromArray:dictAllValues]];
//NSJSONWritingOptions *writingOptions;
NSError *error;
NSData *data = [NSJSONSerialization dataWithJSONObject:keysAndValues options:0 error:&error];
[self load:data completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"done");
NSString *s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"RAW response = %#", s);
//NSJSONReadingOptions *options;
NSError *error2;
NSDictionary *d = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error2];
handler(d, error);
}];
}
#end
The Rest API SQL settings were incorrect (Integrated Security was true). Also on the iOS side, I should not have been passing an array for user authentication, but a dictionary.

iOS JSON parsing from web to a UITableView

I'm experiencing a problem with my code but I'm not sure why it's doing this. It's just giving me an error saying JSON Error. The UITableView never gets filled with anything. I'm not very experienced with iOS, so any help is appreciated.
//
// ViewController.m
// Westmount Procrastinator
//
// Created by Saleem on 10/25/13.
// Copyright (c) 2013 Saleem Al-Zanoon. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#property (strong, nonatomic) IBOutlet UIWebView *webView;
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *fullURL = #"********";
NSURL *url2 = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url2];
[_webView loadRequest:requestObj];
self.title = #"News";
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"****************"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self]; // NSString * urlString = [NSString stringWithFormat:#"http://salespharma.net/westmount/get_all_products.php"];
// NSURL * url = [NSURL URLWithString:urlString];
// NSData * data = [NSData dataWithContentsOfURL:url];
// NSError * error;
// NSMutableDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
// NSLog(#"%#",json);
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
data = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
{
[data appendData:theData];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSArray *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
//news = [responseDict objectAtIndex:0];
// [mainTableView reloadData];
if ([responseDict isKindOfClass:[NSArray class]]) {
news = responseDict;
[mainTableView reloadData];
} else {
// Looks like here is some part of the problem but I don't know why.
NSLog(#"JSON Error.");
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Could not contact server!" delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
}
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The download could not complete - please make sure you're connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [news count];
}
NSString *_getString(id obj)
{
return [obj isKindOfClass:[NSString class]] ? obj : nil;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
cell.textLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:#"Issue"]);
cell.detailTextLabel.text = _getString([[news objectAtIndex:indexPath.row] objectForKey:#"Name"]);
return cell;
}
#end
How the JSON looks on the internet:
{
"Issues":[
{
"Issue":"2",
"Link":"google.com",
"Name":"Ios Test"
},
{
"Issue":"3",
"Link":"Yahoo",
"Name":"iOS test 2"
}
],
"success":1
}
Edit: sorry for not being clear in my question, The app does not crash but fails to load the data into the database in the log it puts this up:
2013-10-26 10:26:41.670 Westmount Procrastinator[2490:70b] JSON Error.
2013-10-26 10:26:41.671 Westmount Procrastinator[2490:70b] Server Data:
{"Issues":[{"Issue":"2","Link":"google.com","Name":"Ios Test"}],"success":1}
The goal of the application to contact a database download a list of Issues of a newspaper then list them in the list view.. Then allowing the user to click on the issues and download them.
Edit I added more to the JSON to help explain.
From your sample JSON structure it does not appear to be a NSArray. It is NSDictionary instead. So, while you are parsing JSON data save it in NSDictionary and not in NSArray. Also, change your IF condition afterwards.
Importantly, if your tableview is reading data from an NSArray of NSDictionaries then I would say put this NSDictionary into an NSArray and pass it to table view. Also, check from server side what is the output in case they are multiple dictionaries in which you need to handle accordingly. So essentially there are couple of more lines you need to induce here or else ask data provider (server side) to send NSArray in all cases.
NSDictionary *responseDict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:NULL];
if ([responseDict isKindOfClass:[NSDictionary class]]) {
NSArray *tableArray = [NSArray arrayWithArray:responseDict[#"Issues"]];
}
Now use tableArray to populate your table.
Issues is an array of dictionaries, so you should ask for the dictionary at the indexpath.row, then use objectForKey to pull the appropriate value from that dictionary.
NSDictionary *myDict = #{#"Issues": #[#{#"Issue": #"2",
#"Link": #"google.com",
#"Name": #"Ios Test"},
#{#"Issue": #"3",
#"Link": #"Yahoo",
#"Name": #"iOS test 2"}],
#"success": #"1"};
NSArray *issues = [myDict objectForKey:#"Issues"];
[issues enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Issue: %# Link: %# Name: %#", [obj objectForKey:#"Issue"], [obj objectForKey:#"Link"], [obj objectForKey:#"Name"]);
}];
Will return:
2013-10-26 16:42:43.572 Jsontest[43803:303] Issue: 2 Link: google.com Name: Ios Test
2013-10-26 16:42:43.573 Jsontest[43803:303] Issue: 3 Link: Yahoo Name: iOS test 2

Getting key value from NSDictionary with GooglePlus class

I have a NSDictionary called itemDict and when printing
NSLog(#"itemDictValues:%#",itemDict);
The output is in this format:
itemDictValues:
GTLPlusPerson 0xab821e0:
{etag:""LTv_6IJISeUQGTVXLjMeOtebkoM/eup2crXcelmpMFKesXWlGkJjCiE"" kind:"plus#person" id:"1145282979128841" objectType:"person" displayName:"FirstName LastName" image:{url} url:"https://plus.google.com/1145282979128841"}
From this I need to extract the values corresponding to id, displayName and url to my NSString variables, in this format
profileId=1145282979128841;
Name=FirstName LastName;
Profilepic=https://plus.google.com/1145282979128841;
How do I go about this?
try this ...
_profileId=(NSString*)((GTLPlusPerson*)itemDict).identifier;
_profileName= (NSString*)((GTLPlusPerson*)itemDict).displayName;
_profileImageURLPath=(NSString*)((GTLPlusPerson*)itemDict).image.url;
You just parse the Dictionary to get your desired information.
NSString *profileId = [itemDict objectForKey:#"id"];
NSString *displayName = [itemDict objectForKey:#"displayName"];
Now that image, I think that's in a dictionary itself. And since you haven't specified what's inside that dictionary, so here's what I think you should do:
NSDictionary *imageDict = [itemDict objectForKey:#"image"];
NSURL *imageURL = [imageDict objectForKey:#"url"];
Then getting the UIImage becomes pretty straightforward :
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:imageURL];
NSData *imageData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
UIImage *image = [[UIImage alloc] initWithData:imageData];
You should choose the sendAsynchronousRequest method as it happens in the background and doesn't hold up the functionality of your app.
For an NSDictionary
NSString *profileId = itemDict[#"id"]
NSString *name = itemDict[#"displayName"]
NSString *profilePic = itemDict[#"image"][#"url"]
If it is GTLPlusPerson object then access the properties with objective-c dot syntax
NSString *profileId = itemDict.id;
NSString *name = itemDict.displayName;
NSString *profilePic = itemDict.url;
Judging by your log, it appears it is a GTLPlusPerson object and not an NSDictionary
NSArray* peopleList = peopleFeed.items;
NSLog(#"peopleList %# ",peopleList.description);
for (NSArray *dict in peopleFeed.items) {
NSString *peopleStrID=(NSString*)((GTLPlusPerson*)dict).identifier;
NSLog(#"peopleStrID %#",peopleStrID);
NSString *peopleName = (NSString*)((GTLPlusPerson*)dict).displayName;
NSString *peoplePic = (NSString*)((GTLPlusPerson*)dict).image.url;
}
The easiest way is to use the code Google provides:
if ([[GPPSignIn sharedInstance] authentication]) {
// The user is signed in.
GTLQueryPlus *query = [GTLQueryPlus queryForPeopleGetWithUserId:#"me"];
GTLServicePlus* plusService = [[GTLServicePlus alloc] init];
plusService.retryEnabled = YES;
//auth = GTMOAuth2Authentication object from login
[plusService setAuthorizer:auth];
[plusService executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,
GTLPlusPerson *person,
NSError *error) {
if (error) {
GTMLoggerError(#"Error: %#", error);
} else {
// Retrieve the display name and "about me" text
NSString *description = [NSString stringWithFormat:#"%#\n%#", person.displayName, person.aboutMe];
NSString *imageURL = person.image.url;
}
}];
} else {
//user is logged out
}
}

Resources