TouchJSON How to make a table populated with json clickable? - iphone

I am a total newbie on iOS development. After numerous tries; with lots of sample codes I managed to parse a json string from my server and able to display the results in a dynamic tableview. My problem is I cannot make the cells clickable so they would pass the id and the label to another view where another json parse will be performed to display the details of the row.
Below is my code:
#import "jsonviewcontroller.h"
#import "CJSONDeserializer.h"
#import "Otel_ItemViewController.h"
#implementation jsonviewcontroller
#synthesize tableview;
#synthesize rows;
- (void)dealloc {
[rows release];
[tableview release];
[super dealloc];
}
// Customize the number of rows in the table view.
- (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";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
cell.textLabel.text = [dict objectForKey:#"C_NAME"];
cell.detailTextLabel.text = [dict objectForKey:#"CAT_ID"];
return cell;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:#"http://zskript.net/categories.php"];
NSString *jsonreturn = [[NSString alloc] initWithContentsOfURL: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] retain];
if (dict)
{
rows = [dict objectForKey:#"users"];
}
NSLog(#"Array: %#",rows);
[jsonreturn release];
}
// Do some customisation of our new view when a table item has been selected
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure we're referring to the correct segue
if ([[segue identifier] isEqualToString:#"ShowSelectedMovie"]) {
// Get reference to the destination view controller
Otel_ItemViewController *vc = [segue destinationViewController];
// get the selected index
NSInteger selectedIndex = [[self.tableview indexPathForSelectedRow] row];
// Pass the name and index of our film
[vc setSelectedItem:[NSString stringWithFormat:#"%#", [rows objectAtIndex:selectedIndex]]];
[vc setSelectedIndex:selectedIndex];
}
}
- (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;
}
#end
And below is the view that will display the detail:
#import "Otel_ItemViewController.h"
#implementation Otel_ItemViewController
#synthesize selectedIndex, selectedItem;
- (void)viewDidLoad
{
[super viewDidLoad];
[outputLabel setText:selectedItem];
[outputText setText:selectedItem];
[outputImage setImage:[UIImage imageNamed:[NSString stringWithFormat:#"%d.jpg", selectedIndex]]];
}
#end
Currently, when I click the cells in the table, Although I have set it to push to the next view, nothing happens. Would someone please advise?
Here is the updated code.
My root view controller:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
DetailViewController *controller = [[DetailViewController alloc] init];
controller.CATNAME = [dict objectForKey:#"C_NAME"];
controller.CATNUMBER = [dict objectForKey:#"CAT_ID"];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
And here is DetailViewController.h:
#interface DetailViewController : UIViewController {
NSString *CATNAME;
NSInteger CATNUMBER;
IBOutlet UILabel *labelId;
IBOutlet UILabel *LabelName;
}
#property (nonatomic) NSInteger CATNUMBER;
#property (nonatomic, retain) NSString *CATNAME;
#end
And DetailViewController.m:
#import "DetailViewController.h"
#implementation DetailViewController
#synthesize CATNAME, CATNUMBER;
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void) viewDidLoad
{
LabelName.Text = CATNAME;
labelId = CATNUMBER;
// [LabelName setText:CATNAME];
// [labelId setText:CATNUMBER];
}

You have to implement this method
EDIT: Loading a new view
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [rows objectAtIndex: indexPath.row];
MyNewViewController *controller = [[MyNewViewController alloc] init];
controller.C_NAME = [dict objectForKey:#"C_NAME"];
controller.CAT_ID = [dict objectForKey:#"CAT_ID"];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
In the code above I assume you are using a navigation controller (which is the easiest way to do what you want to be doing). Also I am assuming you have a class that inherits from UIViewController that you want to have displayed. I am also assuming that this class which I called MyNewViewController in my example has two members and properties called C_NAME and CAT_ID respectively.
- (void) viewDidLoad
{
labelName.Text = C_NAME;
labelId = CAT_ID
}
The above my be incorrect as I am doing it out of memory. But the principal stays the same, if you passed the variables correctly it should work, you can have a look at my blog it still needs some work done on it, but it has a nice beginners post and shows how to edit the text of the label. In the code above I am assuming your view contains two labels labelName and labelId respectfully.
In there you have access to what cell was selected and you can then define what needs to happen.

Related

Passing Data from Dynamic tableView to Static TableView

Hi Let me try to clarify my issue. I have two TableViews, one is static and the other is dynamic. The static= RootVC and Dynamic=FirstVC. In FirstVC i have data that I want to select,save and pass the saved data to a UILabel in RootVC. 1)When I run my App data is selected however it is not saved or passed to my rooVC. I was using delegates and was advice not to use "delegate" but use "Blocks". But still i'm facing the same issue. Here is my code:
in rootVC.h
#import <UIKit/UIKit.h>
#interface RootViewController : UITableViewController
{
NSString *getRepeatLabel;
}
#property (strong, nonatomic) IBOutlet UILabel *repeatLabel;
#property (strong, nonatomic) IBOutlet UILabel *repeatDetail;
#property (nonatomic,strong) NSString *getRepeatLabel;
#end
in my rootVC.m
#import "RootViewController.h"
#interface RootViewController ()
#end
#implementation RootViewController
- (void)viewDidLoad
{
[super viewDidLoad];
_repeatLabel.text = #"Repeat";
_repeatDetail.text = getRepeatLabel;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UIViewController *destinationController = segue.destinationViewController;
if( [destinationController isKindOfClass:[FirstViewController class]] )
{
[(FirstViewController *)destinationController setCompletionBlock:^(NSString *getRepeatLabel;)
{
// do something here with your string // maybe you must reload your table // it depends on where your returning data needs to display <--------Not sure what to do here
// NSDateFormatter*dateFormatter = [[NSDateFormatter alloc]init];
// NSArray*days = [dateFormatter shortWeekdaySymbols]; <------Here I would like when data is selected to show days in short symbol
NSLog (#"The selected day/s is %#", getRepeatLabel); <---nothing displaying on console
}];
}
}
#end
in FirstVC.h
#import <UIKit/UIKit.h>
#import "RootViewController.h"
typedef void(^WeekdayCompletionBlock)(NSString *dayName);
#interface FirstViewController : UITableViewController
{
NSString *dayName;
}
#property (nonatomic, strong) WeekdayCompletionBlock completionBlock;
#property (nonatomic,strong) NSString *dayName;
- (IBAction)save:(id)sender;
#end
in FirstVC.m
#import "FirstViewController.h"
#import "RootViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize completionBlock;
#synthesize dayName;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Initialize table data
completionBlock = [NSArray arrayWithObjects:#"Sunday", #"Monday", #"Tuesday", #"Wednesday", #"Thursday", #"Friday", #"Saturday", nil];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [completionBlock count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"RepeatCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
cell.textLabel.text = [completionBlock objectAtIndex:indexPath.row];
return cell;
}
// Called after the user changes the selection.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSLog (#"The selected day/s is %#", [completionBlock objectAtIndex:indexPath.row]);
_getRepeatLabel = completionBlock; //<-----------string from RootVC gives error "undeclared _getRepeatLabel"
}
- (IBAction)save:(id)sender
{
NSUserDefaults *myNewWeekString = [NSUserDefaults standardUserDefaults];
[myNewWeekString setObject:completionBlock forKey:#"%#"];
[myNewWeekString synchronize];
self.completionBlock(myNewDayOfWeekString) <------error myNewDayOfWeekString undeclared and if i declare it here it complains about incompatibility
}
#end
Your code is a little bit wrong. I think you don't really understand block.
You want to pass more than string so the best way to do that is via array. Change block definition to accept array instead of string:
typedef void(^WeekdayCompletionBlock)(NSArray *dayName);
Change declaration of your property in FirstVC.h to:
#property (nonatomic, copy) NSArray *completionBlock; //This is your array, you use it as data source, It's not a block
//Add your block property
// This is your block property you will use it to pass the data between view controllers
#property (copy) WeekdayCompletionBlock returnBlock;
//Add property to keep your selected days
#property (nonatomic, strong) NSMutableArray *returnArray;
Add this line to viewDidLoad method:
self.returnArray = [[NSMutableArray alloc] init];
Change your didSelectRowAtIndexPath method in FirstVC.m to:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark)
{
cell.accessoryType = UITableViewCellAccessoryNone;
//remove data from array
[self.returnArray removeObject:[completionBlock objectAtIndex:indexPath.row]];
}
else
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
//add data to array
[self.returnArray addObject:[completionBlock objectAtIndex:indexPath.row]];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
In your save: method call block and pass value to rootVC replace line:
self.completionBlock(myNewDayOfWeekString);
with:
if (self.returnBlock)
{
self.returnBlock(self.returnArray);
}
[self.navigationController popViewControllerAnimated:YES];
The last change left to do is set up ablok in your rootVC.m file. Replace line:
[(FirstViewController *)destinationController setCompletionBlock:
with (nsstring needs to be replaced with nsarray - you pass array with all of the selected data)
[(FirstViewController *)destinationController setCompletionBlock:^(NSArray *getRepeatLabel)
You set up block not NSArray.
I don't know what are you trying to do here:
[myNewWeekString setObject:completionBlock forKey:#"%#"];
You are using %# as a key. It should be text for example #"MY_KEY_FOR_ACCESING_DAYSOFWEEK". You are saving completionBlock it's all of your days if you want to save just selected days replace it with self.returnArray.
Hope this help.

How to change the style of a UITableViewController programmatically in Xcode

I'm trying to change the style of a UITableViewController to grouped. I know you can do this when creating a new table view, but I have a class that extends UITableViewController, so I don't need to make a new table view. Here's my code:
#import "DetailViewController.h"
#import "NSArray-NestedArrays.h"
#implementation DetailViewController
#synthesize steak, sectionNames, rowControllers, rowKeys, rowLabels;
- (void)viewDidLoad {
sectionNames = [[NSArray alloc] initWithObjects:[NSNull null], NSLocalizedString(#"General", #"General"), nil];
rowLabels = [[NSArray alloc] initWithObjects:
[NSArray arrayWithObjects:NSLocalizedString(#"Steak Name", #"Steak Name"), nil],
[NSArray arrayWithObjects:NSLocalizedString(#"Steak Wellness", #"Steak Wellness"), NSLocalizedString(#"Steak Type", #"Steak Type"), NSLocalizedString(#"Other", #"Other"), nil]
, nil];
rowKeys = [[NSArray alloc] initWithObjects:
[NSArray arrayWithObjects:#"steakName", nil],
[NSArray arrayWithObjects:#"steakWellness", #"steakType", #"other", nil]
, nil];
// TODO: Populate row controllers array
[super viewDidLoad];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sectionNames count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
id theTitle = [sectionNames objectAtIndex:section];
if ([theTitle isKindOfClass:[NSNull class]]) {
return nil;
}
return theTitle;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [rowLabels countOfNestedArray:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"SteakCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier];
}
NSString *rowKey = [rowKeys nestedObjectAtIndexPath:indexPath];
NSString *rowLabel = [rowLabels nestedObjectAtIndexPath:indexPath];
cell.detailTextLabel.text = rowKey;
cell.textLabel.text = rowLabel;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// TODO: Push editing controller onto the stack
}
#end
- (instancetype)init
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self) {
}
return self;
}
Not following? What do you mean by you don't have to "make a new table view"?? You still have to instantiate one.
Either you created one already and it has the style you want, or you have to instantiate a new one and set the property on it.
tableView.style is READONLY. So you can't change the style of an existing one. You are going to have to do something like:
[MyTableViewSubClass initWithFrame:aFrame style:UITableViewStyleGrouped];
You can not just change the style of an UITableView. So you only have 2 options:
Make another UITableView which is grouped
Use custom cells
Hope it helps
You would take care of this when you instantiated your view controller.
For example, to instantiate a normal UITableViewController you would do the following.
UITableViewController *tblCtr = [[UITableViewController alloc]initWithStyle:UITableViewStyleGrouped];
Therefore, if you have extended UITableViewController then your init code should take care of this.
MyCustomTableViewController *mctvc = [[MyCustomTableViewController alloc]initWithStyle:UITableViewStyleGrouped];
To achieve this you will need to implement this method in your .m file. Below is an example of what your header and implementation file should contain for instantiation.
Header
#interface MyCustomTableViewController : UITableViewController
{
-(id)initWithStyle:(UITableViewStyle)style;
}
Implementation
#implementation MyCustomTableViewController
-(id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if(self)
{
...
return self;
}
return nil;
}
#end
When you call [super initWithStyle:style] the code provided by apple will take care of building the tableview for you with the requested view style.
You can create a new tableview to overwrite UITableviewController's tableview like this:
UITableView *tableView = [[UITableView alloc] initWithFrame:self.tableView.frame style:UITableViewStyleGrouped];
self.tableView = tableView;
simply buddy to allocate set the frame and style of table ..example code write down.
[tableObject initWithFrame:CGRectMake(x,y,width,height) style:UITableViewStyleGrouped];

Pass data from a table to a webview USING SEGUES

I have a table based off Sam's Teach Yourself iOS Development's FlowerViewController, that, under didSelectRowAtIndesPath it goes to a website in a new nib (I tweaked part of the passing data).
MY QUESTION: I would like to update this to, instead of going to a nib, to segue within a storyboard. I know that instead of using didSelectRow... I use prepareForSegue...but I can't figure out the details...
my I have ViewController.m with the following:
- (void)viewDidLoad {
[self movieData];
[super viewDidLoad];
self.title = #"Movies";
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
#pragma mark -
#pragma mark Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [movieSections count];
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[movieData objectAtIndex:section] count];
}
// Customize the appearance of table view cells.
- (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];
}
// Configure the cell.
[[cell textLabel]
setText:[[[movieData
objectAtIndex:indexPath.section]
objectAtIndex: indexPath.row]
objectForKey:#"name"]];
[[cell imageView]
setImage:[UIImage imageNamed:[[[movieData
objectAtIndex:indexPath.section]
objectAtIndex: indexPath.row]
objectForKey:#"picture"]]];
[[cell detailTextLabel]
setText:[[[movieData
objectAtIndex:indexPath.section]
objectAtIndex: indexPath.row]
objectForKey:#"detail"]];
cell.detailTextLabel.numberOfLines = 0;
cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
// Override to support row selection in the table view.
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
WebViewController *webViewController =
[[WebViewController alloc] initWithNibName:
#"WebViewController" bundle:nil];
webViewController.detailURL=
[[NSURL alloc] initWithString:
[[[movieData objectAtIndex:indexPath.section] objectAtIndex:
indexPath.row] objectForKey:#"url"]];
webViewController.title=
[[[movieData objectAtIndex:indexPath.section] objectAtIndex:
indexPath.row] objectForKey:#"name"];
[self.navigationController pushViewController:
webViewController animated:YES];
}
#pragma mark -
#pragma mark Table view delegate
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)movieData {
NSMutableArray *myMovies;
movieSections=[[NSMutableArray alloc] initWithObjects:
#"Movies",nil];
myMovies=[[NSMutableArray alloc] init];
[myMovies addObject:[[NSMutableDictionary alloc]
initWithObjectsAndKeys:#"Movie1",#"name",
#"1.png",#"picture",
#"http://www.url1.com",#"url",#"Some information",#"detail",nil]];
[myMovies addObject:[[NSMutableDictionary alloc]
initWithObjectsAndKeys:#"Movie2",#"name",
#"2.png",#"picture",
#"http://www.url2.com",#"url",#"Some information 2",#"detail",nil]];
[myMovies addObject:[[NSMutableDictionary alloc]
initWithObjectsAndKeys:#"Movie3",#"name",
#"3.png",#"picture",
#"http://www.url3.com",#"url",#"Some information 3",#"detail",nil]];
[myMovies addObject:[[NSMutableDictionary alloc]
initWithObjectsAndKeys:#"Movie4",#"name",
#"4.png",#"picture",
#"http://www.url4.com",#"url",#"Some information 4",#"detail",nil]];
movieData=[[NSMutableArray alloc] initWithObjects:
myMovies,nil];
}
I attempted to comment out the didSelectRowAtIndexPath and add the following for the segue, but the cell highlights and nothing happens (thankfully it doesn't freeze/crash, but there's nothing positive)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"movieSegue"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
WebViewSegue *_webViewSegue = [segue destinationViewController];
_webViewSegue.detailURL =
[[NSURL alloc] initWithString:[[[movieData objectAtIndex:selectedRowIndex.section] objectAtIndex:
selectedRowIndex.row] objectForKey:#"url"]];
}
}
Then I want it to pass to WebViewSegue
WebViewSegue.h:
#interface WebViewSegue : UIViewController {
IBOutlet UIWebView *detailWebView;
NSURL *detailURL;
IBOutlet UIActivityIndicatorView *activity;
NSTimer *timer;
}
#property (nonatomic, weak) NSURL *detailURL;
#property (nonatomic, weak) UIWebView *detailWebView;
#property (nonatomic, weak) UIActivityIndicatorView *activity;
#end
WebViewSegue.m:
#synthesize detailWebView =_detailWebView;
#synthesize detailURL = _detailURL;
#synthesize activity =_activity;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (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.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
[detailWebView loadRequest:[NSURLRequest requestWithURL:detailURL]];
timer = [NSTimer scheduledTimerWithTimeInterval:(1.0/2.0)
target:self
selector:#selector(tick)
userInfo:nil
repeats:YES];
}
-(void)tick {
if (!detailWebView.loading)
[activity stopAnimating];
else
[activity startAnimating];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
-(void)wevView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:#"Cannot connect"
message:#"Please check your connection and try again"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
#end
I've answered your question in another post on the site. See my answer here.
Specifically on how to pass data from a table to the next storyboard segue, first create a property for the data in the next storyboard segue (i.e. the destination view controller). Then set that property in the prepareForSegue method of the table (the source view controller).
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// needed if you have multiple segues
if ([[segue identifier] isEqualToString:#"changeNameAndDate"])
{
[[segue destinationViewController] setDataProperty:self.tableData];
// where dataProperty is the property in the designation view controller
// and tableData is the data your are passing from the source
{
}
This is a lot of code to digest; you should try to simplify. But if I've read it correctly, your basic approach seems correct.
First, put a breakpoint on prepareForSegue:sender:, and make sure it's being called, and that the identifier is what you expect it to be.
Then put a breakpoint on viewDidLoad and make sure it's called when you think it should be.
I would pull the loadRequest: out into its own method and call it both in viewDidLoad and in setDetailURL:. It's likely that setDetailURL: is being called after viewDidLoad if all of this is in a single storyboard.
EDIT What I'm saying is that prepareForSegue:sender: is likely correct. You're problem is in the presented view controller.
- (void)reloadWebView { // Pull the loadRequest: out...
[self.detailWebView loadRequest:[NSURLRequest requestWithURL:self.detailURL]];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self reloadWebView]; // ...and call it both in viewDidLoad...
...
}
- (void)setDetailURL:(NSURL *)URL {
[URL retain];
[detailURL release];
detailURL = URL;
[self reloadWebView]; // ...and in setDetailURL:
}
Also note that there is no reason for your timer. Just turn on your progress indicator in reloadWebView and turn it off in webViewDidFinishLoad and webView:didFailLoadWithError:. Your current approach makes it impossible to deallocate this view controller because the timer retains it forever.

iPhone Multiple UITableView controls on one View

Im having a little issue with using more than 1 UITableView on a view.
Here's what I've done so far (using examples, etc from here and other places):
Created a class for each table. Each class is pretty basic:
.h:
#interface ConstructionDocumentsJobTable : UITableViewController <UITableViewDataSource, UITableViewDelegate> {
NSMutableArray *tableItems;
IBOutlet UITableView *itemsTable;
NSInteger recordSelected;
id <JobTableSelectionDelegate> tableSelectDelegate;
}
#property (nonatomic, retain) NSMutableArray *tableItems;
#property (nonatomic, assign) id <JobTableSelectionDelegate> tableSelectDelegate;
#end
.m:
#implementation ConstructionDocumentsJobTable
#synthesize tableItems, tableSelectDelegate;
#pragma mark -
#pragma mark View Life Cycle
-(void) loadView
{
}
-(void) dealloc
{
[tableItems release];
[super dealloc];
}
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [tableItems count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [tableItems objectAtIndex:indexPath.row];
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//pass the tap value back to the delegate
}
Both are completely identical, save the names.
When Im making the call to the first one, it is called in the ViewDidLoad method of the controller of the view. It's pretty basic:
NSMutableArray *tableItems = [[NSMutableArray alloc] initWithCapacity:intMax];
//strDocumentType is set elsewhere and loaded here
if(strDocumentType == #"typea"){
[tableItems addObject:#"Type A - Value 1"];
[tableItems addObject:#"Type A - Value 2"];
}
else {
[tableItems addObject:#"Type B - Value 1"];
}
if(jobTableController == nil){
jobTableController = [[ConstructionDocumentsJobTable alloc] init];
[jobTableController loadView];
jobTableController.tableItems = tableItems;
jobTableController.tableSelectDelegate = self;
}
[tableJobList setDataSource:jobTableController];
[tableJobList setDelegate:jobTableController];
jobTableController.view = jobTableController.tableView;
The second table is built when a cell in the first table is selected. So, in the first tables selection method, the delegate is called back from the parent controller, which then has this:
NSMutableArray *tableTypeItems = [[NSMutableArray alloc] initWithCapacity:100];
if(tableSelect == #"plumbing"){
[tableTypeItems addObject:#"Something"];
[tableTypeItems addObject:#"Other"];
}
if(typeTableController == nil){
typeTableController = [[ConstructionDocumentsTypeTable alloc] init];
[typeTableController loadView];
typeTableController.tableItems = tableTypeItems;
typeTableController.tableSelectDelegate = self;
}
[tableTypeList setDataSource:typeTableController];
[tableTypeList setDelegate:typeTableController];
typeTableController.view = typeTableController.tableView;
[typeTableController.tableView reloadData];
//Code to move the first table off the screen and move this one into view goes here
Ive been stuck on this for days, and I really need to get this done!!!
Im sure it's something REALLLLLLY simple.
Any help you guys can pass along would be HUGELY appreciated.
Thanks everyone.
Your only defining itemsTable in your header, try defining another table, and in your cellForRowAtIndexPath try this:
if(itemsTable1){
/* stuff for first table */
} else {
/* stuff for second table */
}
And do the same for each UITableVIew Delegate

iPhone - creating a tableview sectioned and in alphabetical order

I am pretty new to programming any sort of device and am on a steep learning curve, so please forgive me if this doesnt make too much sense or the code in the question is awful - we all ave to start somewhere, and beleive me, i have read and read and read!
I am creating a table from a plist which is an array of dictionarys - i need it in this format as later i wish to be able to change some of the values and write back to the relevant plist 'key'.
I am hoping that someone will be able to look at this and give me some pointers as to how to...
Make the table sort the data under the key/value 'name' from the plist in the fashion A to Z in a grouped style - this seems to be ok, however, it creates the number of sections according to the number of dictionaries in the array in the plist whereas some of the dictionaries should be grouped together under the same section (see below)
Divide the table up into sections according to the items in the plist ie. if i have 7 items, ranging across the alphabet then i want 7 sections.
have an index on the right hand side that only has the relevant number of entries - if i dont have any data under 'Q' then I dont want 'Q' to show in the index!
Obviously i'm a long way from sorting all this out - the code itself is a bit of a 'dogs-dinner' at the moment as i have been trying so many different things without much success, so if you see something you dont like please let me know!
I have been trying to read up on all the relevant sections such as UILocalizedIndexedCollation and sortedArrayUsingDescriptors but i guess my brain just isnt up to it...
Any and all advice (except 'give it up you're not bright enough for this' as i never give up on anything i start!) would be much appreciated!
(there are lots of unused variables synthesized at the beginning - i have taken the relevant code out in order to simplify what i have posted here, the code compiles with no problems, and works given me the following result:
a table with 27 letters indexed on the right hand side of which only A-J work (which correlates to the number of sections produced in the table - there are only section A-J. The contents of the cells are exactly what i want.)
#import "RootViewController.h"
#import "View2Controller.h"
#import "tableviewsAppDelegate.h"
#import "SecondViewController.h"
#import "HardwareRootViewController.h"
#import "HardwareSecondViewController.h"
#import "SoftwareRootViewController.h"
#implementation SoftwareRootViewController
#synthesize dataList2;
#synthesize names;
#synthesize keys;
#synthesize tempImageType;
#synthesize tempImageName;
#synthesize finalImageName;
#synthesize tempSubtitle;
#synthesize finalSubtitleName;
#synthesize tempSubtitleType;
#synthesize finalSubtitleText;
#synthesize sortedArray;
#synthesize cellName;
#synthesize rowName;
//Creates grouped tableview//
- (id)initWithStyle:(UITableViewStyle)style {
if (self = [super initWithStyle:UITableViewStyleGrouped]) {
}
return self;
}
- (void)viewDidLoad {
//loads in backgroundimage and creates page title//
NSString *backgroundPath = [[NSBundle mainBundle] pathForResource:#"background1" ofType:#"png"];
UIImage *backgroundImage = [UIImage imageWithContentsOfFile:backgroundPath];
UIColor *backgroundColor = [[UIColor alloc] initWithPatternImage:backgroundImage];
self.tableView.backgroundColor = backgroundColor;
[backgroundColor release];
self.navigationController.navigationBar.tintColor = [UIColor colorWithRed:.5 green:.4 blue:.3 alpha:5];
self.title = #"Software";
[super viewDidLoad];
//Defines path for DATA For ARRAY//
NSString *path = [[NSBundle mainBundle] pathForResource:#"DataDetail3" ofType:#"plist"];
//initialises the contents of the ARRAY with the PLIST//
NSMutableArray* nameArray = [[NSMutableArray alloc]
initWithContentsOfFile:path];
//Sorts the items in the list alphabetically//
NSSortDescriptor *nameSorter = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(caseInsensitiveCompare:)];
[nameArray sortUsingDescriptors:[NSArray arrayWithObject:nameSorter]];
[nameSorter release];
self.dataList2 = nameArray;
[nameArray release];
}
- (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 anything that can be recreated in viewDidLoad or on demand.
// e.g. self.myOutlet = nil;
}
#pragma mark Table view methods
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:
SectionsTableIdentifier ];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier: SectionsTableIdentifier ] autorelease];
}
// Configure the cell.
cell.indentationLevel = 1;
cell.textLabel.text = [[self.dataList2 objectAtIndex:indexPath.row]
objectForKey:#"name"];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
//Detremines the cell color according to the value in 'owned' in the plist//
NSString *textColor = [[self.dataList2 objectAtIndex:indexPath.row]
objectForKey:#"owned"];
if ([textColor isEqualToString: #"greenColor"]) {
[cell setBackgroundColor:[UIColor colorWithRed:0.1 green:0.7 blue:0.1 alpha:1]];
}
if ([textColor isEqualToString: #"blackColor"]) {
[cell setBackgroundColor:[UIColor whiteColor]];
}
return cell;
}
// Code For Loading of The View2Controller//
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [[self.dataList2 objectAtIndex:indexPath.row]
objectForKey:#"name"];
NSString *rowTitle = CellIdentifier;
NSLog(#"rowTitle = %#", rowTitle);
[tableView deselectRowAtIndexPath:indexPath animated:YES];
SecondViewController *second = [[SecondViewController alloc] init];
[second setCategory: rowTitle];
[self.navigationController pushViewController:second animated:YES];
[second release];
}
- (void)dealloc {
[dataList2 release];
[super dealloc];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [dataList2 count];
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [dataList2 count]; ///Tells the table that it only needs the amount of cells listed in the DATALIST1 ARRAY//
}//
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)help
{
return [[[UILocalizedIndexedCollation currentCollation] sectionTitles] objectAtIndex:help];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return [[UILocalizedIndexedCollation currentCollation] sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [[UILocalizedIndexedCollation currentCollation] sectionForSectionIndexTitleAtIndex:index];
}
#end
Any advice would be greatly appreciated - at the moment i have been working on this for about a week with no success and am close to just giving up, which i really dont want to do!
If the worst come to the worst and i cant get this done would ayone be willing to write the functionality in for me, for a small fee of course!!
Cheers, and heres hoping...
Chubs
Use UILocalizedIndexCollation =]