how to access object property in this case - html

project type: masterview application components first view: Tableview second view :webview what i want is to navigate in such a technique that : when user taps a cell, it should get the href property and to open in next webview, the page it links to.. instead of only href property
suggestion thanks
#import "MasterViewController.h"
#import "TFHpple.h"
#import "TFHppleElement.h"
#import "Preface.h"
#import "Chapters.h"
#import "Index.h"
#import "DetailViewController.h"
#interface MasterViewController ()
{
NSMutableArray * preface;
NSMutableArray * chapters;
NSMutableArray * index;
}
#end
#implementation MasterViewController
- (void) loadChapters
{
///// capturing the link /////
/*
NSURL pointer to store the file url
*/
NSURL * chapter_url = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"test/mainpage" ofType:#"html"] isDirectory:NO];
NSData * chapter_data = [NSData dataWithContentsOfURL:chapter_url];
///// passing to TFHpple /////
TFHpple * chapter_parser = [TFHpple hppleWithHTMLData:chapter_data];
///// String for XPath Query /////
NSString * chapter_query_string = #"//div[#class='cD']/ul[2]/li/a";
NSArray * chapter_nodes = [chapter_parser searchWithXPathQuery:chapter_query_string];
///// Array for initializing elements of preface/////
NSMutableArray * chapter_contents = [[NSMutableArray alloc]initWithCapacity:0];
///// Now looping to fetch contents /////
for (TFHppleElement * element in chapter_nodes) {
Chapters * chapter_ptr =[[Chapters alloc]init];
[chapter_contents addObject:chapter_ptr];
chapter_ptr.chapter_title = [[element firstChild]content];
chapter_ptr.chapter_url = [element objectForKey:#"href"];
}
chapters= chapter_contents;
[self.tableView reloadData];
}
viewdidload
- (void)viewDidLoad
{
[super viewDidLoad];
[self loadPreface];
[self loadChapters];
[self loadIndex];
// Do any additional setup after loading the view, typically from a nib.
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
switch (section) {
case 0:
return #"Table of Contents";
break;
case 1:
return #"Chapters";
break;
case 3:
return #"Index";
break;
}
return nil;
}
Method returning no of rows in a section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0:
return preface.count;
break;
case 1:
return chapters.count;
break;
case 2:
return index.count;
break;
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
switch (indexPath.section) {
case 0:
{
Preface *preface_access = [preface objectAtIndex:indexPath.row];
cell.textLabel.text = preface_access.preface_title;
return cell;
}
case 1:
{
Chapters * chapter_access = [chapters objectAtIndex:indexPath.row];
cell.textLabel.text = chapter_access.chapter_title;
return cell;
}
case 2:
{
Index * index_access = [index objectAtIndex:indexPath.row];
cell.textLabel.text = index_access.index_title;
return cell;
}
default:
break;
}
return cell;
i want to do something like this
in detailviewcontroller.m
it is the 2nd view controller
this is pseudo code I am weak in OOP concepts so appologies
- (void)viewDidLoad
{
NSMutableArray * contentsfromprevious = [[NSMutableArray alloc]initWithCapacity:0];
Preface * data = [[Preface alloc]init];
data.preface_url = contentsfromprevious;
data = preface_contents;
[self.loadwebview.request];
}

First of all your question is still not clear enough. What I've come to understand that, you want something like this:
In the MasterViewController you wish show a list of your links (html pages stored locally).
If any of the table view cells are tapped, you want to display the locally stored html page in a web view on the DetailViewController.
Assuming this, you should implement this UITableViewDelegate method on your MasterViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailVC = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailVC.htmlFileName = [htmlFiles objectAtIndex:indexPath.row]; // you might need to change this according to your need, as I said your requirement is unclear
[self.navigationController pushViewController: detailVC animated:YES];
}
Also you'll need to add this into your DetailViewController.h file
#property (nonatomic, strong) NSString *htmlFileName;
And after you've done this, you should change your DetailViewControllers viewDidLoad method into something like this:
- (void)viewDidLoad
{
// your code
// ....
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource: htmlFileName ofType:#"html"] isDirectory:NO]]];
webView.scalesPageToFit = YES;
// your code
// ...
}
I am not sure if this is what you really want though. On the other note, you don't have to put break statements after any return statements. It never gets executed.

Related

UISearchBar in Xcode 5

I implemented the UISearchBar option in my Json data table. However, whenever I am trying to search it, the program crashes. Highly appreciate help on this.
my table view controller's header and implementation files are given below
Header file.
#import <UIKit/UIKit.h>
#interface byTitleViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray * jsonArray;
#property (nonatomic, strong) NSMutableArray * songsArray;
#property (strong, nonatomic) NSMutableArray* filteredTableData;
- (void) retriveData;
#property (weak, nonatomic) IBOutlet UISearchBar *searchBar;
#property (nonatomic, assign) bool isFiltered;
#end
Implementation file
#import "byTitleViewController.h"
#import "songs.h"
#define getDataURL #"http://fetchpin.com/byTitle.php"
#interface byTitleViewController ()
#end
#implementation byTitleViewController
#synthesize jsonArray, songsArray, filteredTableData, searchBar, isFiltered;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"By Title";
searchBar.delegate = (id)self;
[self retriveData];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSUInteger rowCount;
if(self.isFiltered)
rowCount = filteredTableData.count;
else
rowCount = songsArray.count;
return rowCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
songs* songlist;
if (isFiltered) {
songlist = [filteredTableData objectAtIndex:indexPath.row];
}else{
songlist = [songsArray objectAtIndex:indexPath.row];
}
cell.textLabel.text = songlist.songTitle;
return cell;
// Configure the cell...
/*songs * songObject;
songObject = [songsArray objectAtIndex:indexPath.row];
cell.textLabel.text = songObject.songTitle;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
*/
}
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void) retriveData{
NSURL * url = [NSURL URLWithString:#"http://fetchpin.com/byTitle.php"];
NSData * data = [NSData dataWithContentsOfURL:url];
jsonArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
songsArray = [[NSMutableArray alloc] init];
for (int i = 0; i < jsonArray.count; i++) {
NSString * sId = [[jsonArray objectAtIndex:i] objectForKey:#"id"];
NSString * sTitle = [[jsonArray objectAtIndex:i] objectForKey:#"title"];
[songsArray addObject:[[songs alloc]initWithSongTitle: sTitle andSongID: sId]];
}
//[self.tableView reloadData];
}
//search bar ...
-(void)searchBar:(UISearchBar*)searchBar textDidChange:(NSString*)text
{
if(text.length == 0)
{
isFiltered = FALSE;
}
else
{
isFiltered = true;
filteredTableData = [[NSMutableArray alloc] init];
for (songs * sTitle in songsArray)
{
NSRange titleRange = [sTitle.songTitle rangeOfString:text options:NSCaseInsensitiveSearch];
if(titleRange.location != NSNotFound)
{
[filteredTableData addObject:sTitle];
}
}
}
[self.tableView reloadData];
}
#end
It looks like the problem is that some of the objects you are loading from the JSON have a title that is not an NSString, but an NSNull. Adding a check for NSNull in the textDidChange: method should solve the problem:
if(![sTitle.name isKindOfClass:[NSNull class]])
{
NSRange titleRange = [sTitle.name rangeOfString:text options:NSCaseInsensitiveSearch];
if(titleRange.location != NSNotFound)
{
[filteredTableData addObject:sTitle];
}
}
Alternately, you could filter out songs with an NSNull title in your retrieveData method.

iOS JSON Parsing to tableview, incorrect rows

I am developing an iOS App, I have a tableview controller populated from a MySQL database. When I click on a raw a detailview appears showing data from the database, such as a master detail app. The problem is following:
1. When I run the app on the iPhone simulator, the app shows the three records from the mysql table, thats correct.
2. If I click on the first row, nothing happened.
3. If I click on the second or third row, the app opens the detailview, but the data don't correspond to the selected row(record).
4. I click on the back button of the detailview, and the app opens the masterview again.
5. Now if I click on the first row, the app opens the detailview, but as mentioned before, the detailview data don't correspond to the selected row(record) on the master view.
Here you have my viewcontroller code (master view):
//
// ViewController.m
//
#import "ViewController.h"
#import "DetailViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"Areas";
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
NSURL *url = [NSURL URLWithString:#""];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc]initWithRequest:request delegate:self];
// Do any additional setup after loading the view, typically from a nib.
}
- (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;
news = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
[mainTableView reloadData];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"The download could not complete - please make sure you're connect to either 3G or WiFi" 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];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if(cell==nil){
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
}
cell.textLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"name"];
cell.detailTextLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"nombre"];
return cell;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.title =[[news objectAtIndex:indexPath.row]objectForKey:#"nombre"];
detailViewController.newsArticle = [news objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
And here the detailview code:
//
// DetailViewController.m
//
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize newsArticle;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
titleLabel.text = [newsArticle objectForKey:#"nombre"];
timeLabel.text = [newsArticle objectForKey:#"name"];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Any idea what I have done wrong??
Thank you
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.title =[[news objectAtIndex:indexPath.row]objectForKey:#"nombre"];
detailViewController.newsArticle = [news objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detailViewController animated:YES];
}
You are using didDeselectRow which is called when a row is deselected and hence the wierd behaviour plus wrong data.. you have to use didSelectRow

How do you make a UITableView smaller programmatically?

Rather than bloat and convolute this post with what I've tried and failed at, I'll just keep it simple, as I'm sure the answer is probably simpler than I think.
I have a scrolling UITableView on the main view of my application. All I'm trying to do is move the default position--or "starting point"--of the scrolling UITableView down about 194 points to make room for my navigation bar and a couple other UI elements. How do I do this? Here are what I believe to be the pertinent method implementations from my ViewController .h and .m files, respectively:
// MGViewController.h
// UITVPractice
#import <Foundation/Foundation.h>
#interface ItemsViewController : UITableViewController
-(id) init;
-(id) initWithStyle:(UITableViewStyle)style;
#end
// MGViewController.m
// UITVPractice
#import "ItemsViewController.h"
#import "MGItem.h"
#import "MGItemStore.h"
#implementation ItemsViewController
-(void)viewDidLoad {
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
self.tableView.backgroundView = backgroundImageView;
[super viewDidLoad];
}
-(id) init {
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
/* create 5 random MGItems and place in the MGItemStore */
for (int i = 0; i < 20; i++) {
[[MGItemStore sharedStore] createItem];
}
}
return self;
}
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [[[MGItemStore sharedStore] allItems] count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
/* Create an instance of UITableViewCell */
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"UITableViewCell"];
}
UIView *backView = [[UIView alloc] initWithFrame:CGRectZero];
backView.backgroundColor = [UIColor clearColor];
cell.backgroundView = backView;
/* Display custom background image for cell(s) */
cell.backgroundView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"cellBackground.png"] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0]];
/* Display custom background image for selected cell(s) */
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:#"cellBackgroundTouched.png"] stretchableImageWithLeftCapWidth:0.0 topCapHeight:5.0]];
/* eliminate the white box that bounds the black text. */
[[cell contentView] setBackgroundColor:[UIColor clearColor]];
[[cell backgroundView] setBackgroundColor:[UIColor clearColor]];
[cell setBackgroundColor:[UIColor clearColor]];
/* Set the text of the cell to the description of the item that is at the nth index of items, where n = row this cell will appear in on the tableView */
MGItem *p = [[[MGItemStore sharedStore] allItems] objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[p description]];
[[cell textLabel] setTextColor:[UIColor whiteColor]];
// [[cell textLabel] highlightedTextColor: [UIColor purpleColor]];
return cell;
}
-(id) initWithStyle:(UITableViewStyle)style {
return [self init];
}
#end
I apologize if this post comes off as a "do this for me" post, but I've tried about a dozen different things and none of them have worked. Been stuck on this for about 3 days. Thanks for any help you can provide.
EDIT: Yes, Ismael, you're correct. It is a subclass of UITableViewController. I think I understand what you're saying. Working on it now. Thanks to both who answered.
The best way to do this is to "nest" the tableview controller inside another UIView. If you are using storyboards, just add a "container view" then set that view controller's class to that of your tableview controller. Then, changing the container view's size will automatically change the table view's size. Here's an example where I have a few table views nested in one view:
I take it your controller is a subclass of UITableViewController? If that's the case, then you will have to change that.
In order to do this, change the subclass to UIViewController, add the UITableViewDelegate and UITableViewDataSource protocols.
Then, add a UITableView *tableView property and change your viewDidLoad method to look like this:
-(void)viewDidLoad {
[super viewDidLoad]; // [super viewDidLoad]; should go first!!
CGFloat startingPoint = 194.0; // or whatever
CGRect tableRect = self.view.bounds;
tableRect.origin.y = startingPoint;
tableRect.size.height -= startingPoint;
self.tableView = [[UITableView alloc] initWithFrame:tableRect style:UITableViewStyleGrouped]; // or plain, whichever you need
self.tableView.dataSource = self;
self.tableView.delegate = self;
self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine; // do this if grouped, looks better!
self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self.view addSubview:self.tableView];
UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
self.tableView.backgroundView = backgroundImageView;
}
Edit: There's a reason for this. In a normal UIViewController, the self.view is a UIView, but in a UITableViewController, the self.view is the same as self.tableView and is a UITableView, and that's why you can't change the frame of it.

View controller not in view hierarchy?

So I am trying to transition from one view controller to another with a segue programmatically so that I can only initialize it when a user needs to login. However, xcode keeps giving me the error that it is not in the view hierarchy and refuses to load to it.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
ViewController.m
#import "ViewController.h"
#import "API.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
if (![[API sharedInstance] isAuthorized]) {
[self performSegueWithIdentifier:#"ShowLogin" sender:nil];
}// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
LoginScreen.h (the controller not in the hierarchy)
#import <UIKit/UIKit.h>
#interface LoginScreen : UIViewController
{
//the login form fields
IBOutlet UITextField *fldUsername;
IBOutlet UITextField *fldPassword;
}
//action for when either button is pressed
-(IBAction)btnLoginRegisterTapped:(id)sender;
#end
LoginScreen.m (the controller apparently not in the hierarchy)
#import "LoginScreen.h"
#import "UIAlertView+error.h"
#import "API.h"
#include <CommonCrypto/CommonDigest.h>
#define kSalt #"(protected value)"
#implementation LoginScreen
-(void)viewDidLoad {
[super viewDidLoad];
}
#pragma mark - View lifecycle
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(IBAction)btnLoginRegisterTapped:(UIButton*)sender {
//form fields validation
if (fldUsername.text.length < 4 || fldPassword.text.length < 4) {
[UIAlertView error:#"Enter username and password over 4 chars each."];
return;
}
//salt the password
NSString* saltedPassword = [NSString stringWithFormat:#"%#%#", fldPassword.text, kSalt];
//prepare the hashed storage
NSString* hashedPassword = nil;
unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];
//hash the pass
NSData *data = [saltedPassword dataUsingEncoding: NSUTF8StringEncoding];
if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {
hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
} else {
[UIAlertView error:#"Password can't be sent"];
return;
}
//check whether it's a login or register
NSString* command = (sender.tag==1)?#"register":#"login";
NSMutableDictionary* params =[NSMutableDictionary dictionaryWithObjectsAndKeys:command, #"command", fldUsername.text, #"username", hashedPassword, #"password", nil];
//make the call to the web API
[[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json) {
//result returned
NSDictionary* res = [[json objectForKey:#"result"] objectAtIndex:0];
if ([json objectForKey:#"error"]==nil && [[res objectForKey:#"IdUser"] intValue]>0) {
[[API sharedInstance] setUser: res];
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
//show message to the user
[[[UIAlertView alloc] initWithTitle:#"Logged in" message:[NSString stringWithFormat:#"Welcome %#",[res objectForKey:#"username"]] delegate:nil cancelButtonTitle:#"Close" otherButtonTitles: nil] show];
} else {
//error
[UIAlertView error:[json objectForKey:#"error"]];
}
}];
}
#end
API.h (calling my web service)
#import "AFHTTPClient.h"
#import "AFNetworking.h"
typedef void (^JSONResponseBlock)(NSDictionary* json);
#interface API : AFHTTPClient
#property (strong, nonatomic) NSDictionary* user;
+(API*)sharedInstance;
//check whether there's an authorized user
-(BOOL)isAuthorized;
//send an API command to the server
-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock;
-(NSURL*)urlForImageWithId:(NSNumber*)IdPhoto isThumb:(BOOL)isThumb;
#end
API.m (calling my web service)
#import "API.h"
//the web location of the service
#define kAPIHost #"(protected web address)"
#define kAPIPath #""
#implementation API
#synthesize user;
#pragma mark - Singleton methods
/**
* Singleton methods
*/
+(API*)sharedInstance {
static API *sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
sharedInstance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kAPIHost]];
});
return sharedInstance;
}
#pragma mark - init
//intialize the API class with the deistination host name
-(API*)init {
//call super init
self = [super init];
if (self != nil) {
//initialize the object
user = nil;
[self registerHTTPOperationClass:[AFJSONRequestOperation class]];
// Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
[self setDefaultHeader:#"Accept" value:#"application/json"];
}
return self;
}
-(BOOL)isAuthorized {
return [[user objectForKey:#"IdUser"] intValue]>0;
}
-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock {
NSData* uploadFile = nil;
if ([params objectForKey:#"file"]) {
uploadFile = (NSData*)[params objectForKey:#"file"];
[params removeObjectForKey:#"file"];
}
NSMutableURLRequest *apiRequest = [self multipartFormRequestWithMethod:#"POST" path:kAPIPath parameters:params constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
if (uploadFile) {
[formData appendPartWithFileData:uploadFile name:#"file" fileName:#"photo.jpg" mimeType:#"image/jpeg"];
}
}];
AFJSONRequestOperation* operation = [[AFJSONRequestOperation alloc] initWithRequest: apiRequest];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//success!
completionBlock(responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//failure :(
completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:#"error"]);
}];
[operation start];
}
-(NSURL*)urlForImageWithId:(NSNumber*)IdPhoto isThumb:(BOOL)isThumb {
NSString* urlString = [NSString stringWithFormat:#"%#/%#upload/%#%#.jpg", kAPIHost, kAPIPath, IdPhoto, (isThumb)?#"-thumb":#""];
return [NSURL URLWithString:urlString];
}
#end
The issue is that the view of your initial view controller has not been added to the window by the time viewDidLoad is called.
Move that call to viewDidAppear:
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
if (![[API sharedInstance] isAuthorized]) {
[self performSegueWithIdentifier:#"ShowLogin" sender:self];
}
}

NSDictionary selected on Actionsheet, from a UITableView with Custom Cells

I am working on a big learning experience, adding a NSDictionary that uses a JSON(deserializer) to grab content from my MAMP(myphp admin) server (localhost), and put all's this information nicely in a TablewView, which has custom UITableViewCell's,
my problem is, the Table View loads the information from my server just fine, however, when I use the didSelectRowatIndexPath, with an actionsheet, I can get the actionsheet to come up, however I cannot get it to pull the information from my NSDictionary that was previously used in the UITableView.... (basically in the end, the action sheet will have a few buttons, for example loading a URL from a shared application, and all this information will be grabbed from my server using the same NSDictionary in the UITable View.
any help would greatly be appreciated...... thank you so much this community rocks!!!
//
// TouchJSONViewController.m
// TouchJSON
//
// Created by Chance Brown on 3/7/11.
// Copyright 2011 __MyCompanyName__. All rights reserved.
//
#import "TouchJSONViewController.h"
#import "CJSONDeserializer.h"
#import "StaffPicksCustomCell.h"
#import "UIImageView+WebCache.h"
#implementation TouchJSONViewController
#synthesize tableview, rows, cellOne;
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"http://localhost/json.php"]; // Modify this to match your url.
// HOME 192.168.2.23
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL:url]; // Pulls the URL
// NSLog(jsonreturn); // Look at the console and you can see what the restults are
NSData *jsonData = [jsonreturn dataUsingEncoding:NSUTF32BigEndianStringEncoding];
NSError *error = nil;
// In "real" code you should surround this with try and catch
NSDictionary * dict = [[CJSONDeserializer deserializer] deserializeAsDictionary:jsonData error:&error];
if (dict)
{
rows = [[dict objectForKey:#"users"] retain];
}
NSLog(#"Array: %#",rows);
[jsonreturn release];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [rows count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
StaffPicksCustomCell *cell =(StaffPicksCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[StaffPicksCustomCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSSortDescriptor *ratingsSortDescriptor = [[[NSSortDescriptor alloc] initWithKey:#"ID" ascending:NO] autorelease];
rows = [rows sortedArrayUsingDescriptors:[NSArray arrayWithObject:ratingsSortDescriptor]];
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
cell.primaryLabel.text = [dict objectForKey:#"post_title"];
cell.theDate.text = [dict objectForKey:#"post_date"];
cell.mydescription.text = [dict objectForKey:#"post_content"];
[cell.myImageView setImageWithURL:[NSURL URLWithString:[dict objectForKey:#"imagelink"]]
placeholderImage:[UIImage imageNamed:#"placeholder1.png"]];
//cell.textLabel.text = [dict objectForKey:#"post_title"];
//cell.detailTextLabel.text = [dict objectForKey:#"post_content"];
//tableView.backgroundColor = [UIColor cyanColor];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 125;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
StaffPicksCustomCell *cell = (StaffPicksCustomCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"StaffPicksCustomCell" owner:self options:nil];
for (id currentObject in topLevelObjects) {
if ([currentObject isKindOfClass:[StaffPicksCustomCell class]]) {
cell= (StaffPicksCustomCell *) currentObject;
break;
}
}
}
// Configure - Did Select Row at Index Path.
UIActionSheet *popup = [[UIActionSheet alloc] initWithTitle:#"OPTIONS" delegate:self cancelButtonTitle:#"Cancel"destructiveButtonTitle:nil otherButtonTitles:#"More Info",#"Contact Seller",#"Picture", nil];
[popup setActionSheetStyle:UIActionSheetStyleBlackTranslucent];
[popup showInView:[self view]];
[popup release];
// return cell
}
-(void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)indexPath
{
switch (indexPath) {
case 0:
{
NSLog(#"Case 0 Selected");
NSDictionary *dict = [rows objectAtIndex: indexPath];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[dict objectForKey:#"guid"]]];
}
break;
case 1:
{
NSLog(#"Case 1 Selected");
}
break;
case 2:
{
NSLog(#"Case 2 Selected");
}
break;
}
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
It's the rows, they are being autoreleased. Here's the important lines.
The first line in the viewDidLoad retains the rows correctly
rows = [[dict objectForKey:#"users"] retain];
But you sort these rows in the cellForRowAtIndexPath and did not retain it.
rows = [rows sortedArrayUsingDescriptors:[NSArray arrayWithObject:ratingsSortDescriptor]];
This should be something like:
NSArray *sortedRows = [rows sortedArrayUsingDescriptors:[NSArray arrayWithObject:ratingsSortDescriptor]];
[rows release];
rows = [sortedRows retain];
Hope this helps.