TableView Controller using JSON NSURL - objective-c

Good afternoon,
I'm trying to use a TableView Controller to display X number of items from my MySQL database but I'm a little bit lost at the moment.
I have another project where I can show the data using JSON output data, but I don't know how to add that code to my project in order to show the data from my database. That's the code I used:
#implementation HomeModel
- (void)downloadItems
{
// Download the json file
NSURL *jsonFileUrl = [NSURL URLWithString:#"http://website.com/service.php"];
// Create the request
NSURLRequest *urlRequest = [[NSURLRequest alloc] initWithURL:jsonFileUrl];
// Create the NSURLConnection
[NSURLConnection connectionWithRequest:urlRequest delegate:self];
}
#pragma mark NSURLConnectionDataProtocol Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// Initialize the data object
_downloadedData = [[NSMutableData alloc] init];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the newly downloaded data
[_downloadedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Create an array to store the locations
NSMutableArray *_locations = [[NSMutableArray alloc] init];
// Parse the JSON that came in
NSError *error;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData:_downloadedData options:NSJSONReadingAllowFragments error:&error];
// Loop through Json objects, create question objects and add them to our questions array
for (int i = 0; i < jsonArray.count; i++)
{
NSDictionary *jsonElement = jsonArray[i];
// Create a new location object and set its props to JsonElement properties
Location *newLocation = [[Location alloc] init];
newLocation.name = jsonElement[#"user"];
newLocation.address = jsonElement[#"imagen"];
newLocation.latitude = jsonElement[#"date"];
// Add this question to the locations array
[_locations addObject:newLocation];
}
// Ready to notify delegate that data is ready and pass back items
if (self.delegate)
{
[self.delegate itemsDownloaded:_locations];
}
}
#end
Currently that's my code:
TableViewController.m
#import "CarTableViewController.h"
#import "CarTableViewCell.h"
#import "CarTableViewController.h"
#import "CarDetailViewController.h"
#implementation CarTableViewController
#synthesize carMakes = _carMakes;
#synthesize carModels = _carModels;
#synthesize carImages = _carImages;
- (void)viewDidLoad
{
[super viewDidLoad];
self.carMakes = [[NSArray alloc]
initWithObjects:#"Chevy",
#"BMW",
#"Toyota",
#"Volvo",
#"Smart", nil];
self.carModels = [[NSArray alloc]
initWithObjects:#"Volt",
#"Mini",
#"Venza",
#"S60",
#"Fortwo", nil];
self.carImages = [[NSArray alloc]
initWithObjects:#"chevy_volt.jpg",
#"mini_clubman.jpg",
#"toyota_venza.jpg",
#"volvo_s60.jpg",
#"smart_fortwo.jpg", nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.carModels count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"carTableCell";
CarTableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CarTableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
// Configure the cell...
cell.makeLabel.text = [self.carMakes
objectAtIndex: [indexPath row]];
cell.modelLabel.text = [self.carModels
objectAtIndex:[indexPath row]];
UIImage *carPhoto = [UIImage imageNamed:
[self.carImages objectAtIndex: [indexPath row]]];
cell.carImage.image = carPhoto;
return cell;
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"ShowCarDetails"])
{
CarDetailViewController *detailViewController =
[segue destinationViewController];
NSIndexPath *myIndexPath = [self.tableView
indexPathForSelectedRow];
detailViewController.carDetailModel = [[NSArray alloc]
initWithObjects: [self.carMakes
objectAtIndex:[myIndexPath row]],
[self.carModels objectAtIndex:[myIndexPath row]],
[self.carImages objectAtIndex:[myIndexPath row]],
nil];
}
}
#end
TableViewController.h
#import <UIKit/UIKit.h>
#interface CarTableViewController : UITableViewController
#property (nonatomic, strong) NSArray *carImages;
#property (nonatomic, strong) NSArray *carMakes;
#property (nonatomic, strong) NSArray *carModels;
#end
How can I add the first code (results from my database) to the other project? I'm lost at the moment and I will appreciate a lot if you can give me some light on this problem, because I want to edit the info from the storyboard as I have in the second project.
Thanks in advance.
Regards.
Thanks in advance.

It's because you don't connect to your database directly from your iphone. In general ou have a web service (also call API) for expose your data (in JSON format for example). So you have to build an API, in PHP, Ruby or Node, for expose the data of your database and access it.
EDIT:
What i see is in your HomeModel, you can set a delegate, this delegate have a function itemsDownloaded where you pass the data get from your API.
So you want your CarTableViewController to be that delegate for receive those data.
First you have to have an object HomeModel, in your TableViewController.h add:
#property (strong, nonatomic) HomeModel *homeModel;
Now you have to call the code that get the data from your server. Something like
- (void)viewDidLoad
{
[super viewDidLoad];
homeModel = [HomeModel new];
homeModel.delegate = self;
[homeModel downloadItems];
}
And finally you have to implement itemsDownloaded in your CarTableViewController. Do something like this:
- (void)itemsDownloaded:(NSArray *)items
{
self.carMakes = items; // Problem here
[self.tableView reloadData];
}
But the problem is HomeModel parse something different from what you have in carMakes, you have to adapt the Loop through Json objects in HomeModel.
You may wanna try AFNetworking which is a library easier to use than NSURLConnection.

Related

How to Get Duplicate Contact list iOS and merge or delete Contact?

I Want to Delete Duplicate or Merge duplicate Contact Can anyOne Provide me Sample Code for it !!!!!
I want to get the List of Duplicate Contact in tableview and merge them or delete them
I created sample project for you.I got the solution.it works perfectly.
Addressbook framework is deprecated from iOS 9.So we need to use Contact framework.
We must import Contact framework
Next in plist If you want to access contacts,you have to get
authorization permission so you need to add Privacy - Contacts Usage
Description
Key is Privacy - Contacts Usage Description
Type is string
Value is contact (whatever you want add here as string)
ViewController.h
#import <UIKit/UIKit.h>
#import <Contacts/Contacts.h>
#interface ViewController : UIViewController<UISearchBarDelegate,UITableViewDataSource,UITableViewDelegate>
#property (strong, nonatomic) IBOutlet UITableView *tblViewContact;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray *arrData;
NSMutableArray *arraySearchContactData;
}
#end
#implementation ViewController
#synthesize tblViewContact;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arrData = [[NSMutableArray alloc]init];
[self getContact];
[tblViewContact registerClass:[UITableViewCell class] forCellReuseIdentifier:#"cell"];
}
//Get Contact and Authorization Access
-(void)getContact
{
// Request authorization to Contacts
CNContactStore *store = [[CNContactStore alloc] init];
[store requestAccessForEntityType:CNEntityTypeContacts completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted == YES)
{
//keys with fetching properties
NSArray *keys = #[CNContactFamilyNameKey, CNContactGivenNameKey, CNContactPhoneNumbersKey, CNContactImageDataKey];
NSString *containerId = store.defaultContainerIdentifier;
NSPredicate *predicate = [CNContact predicateForContactsInContainerWithIdentifier:containerId];
NSError *error;
NSArray *cnContacts = [store unifiedContactsMatchingPredicate:predicate keysToFetch:keys error:&error];
if (error) {
NSLog(#"error fetching contacts %#", error);
} else {
NSString *phone;
NSString *fullName;
NSString *firstName;
NSString *lastName;
UIImage *profileImage;
NSMutableArray *contactNumbersArray = [[NSMutableArray alloc]init];
NSMutableArray *arrContacts = [[NSMutableArray alloc]init];
for (CNContact *contact in cnContacts)
{
// copy data to my custom Contacts class.
firstName = contact.givenName;
lastName = contact.familyName;
if (lastName == nil) {
fullName=[NSString stringWithFormat:#"%#",firstName];
}else if (firstName == nil){
fullName=[NSString stringWithFormat:#"%#",lastName];
}
else{
fullName=[NSString stringWithFormat:#"%# %#",firstName,lastName];
}
UIImage *image = [UIImage imageWithData:contact.imageData];
if (image != nil) {
profileImage = image;
}else{
profileImage = [UIImage imageNamed:#"person-icon.png"];
}
for (CNLabeledValue *label in contact.phoneNumbers)
{
phone = [label.value stringValue];
if ([phone length] > 0) {
[contactNumbersArray addObject:phone];
}
}
NSDictionary* personDict = [[NSDictionary alloc] initWithObjectsAndKeys: fullName,#"fullName",profileImage,#"userImage",phone,#"PhoneNumbers", nil];
[arrContacts addObject:[NSString stringWithFormat:#"%#",[personDict objectForKey:#"fullName"]]];
}
//Removing Duplicate Contacts from array
NSOrderedSet *orderedSet = [NSOrderedSet orderedSetWithArray:arrContacts];
NSArray *arrayWithoutDuplicates = [orderedSet array];
arrData = [arrayWithoutDuplicates mutableCopy];
NSLog(#"The contacts are - %#",arrData);
dispatch_async(dispatch_get_main_queue(), ^{
[tblViewContact reloadData];
});
}
}
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - UITableView Data Source Methods
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return arrData.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *strCell = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:strCell];
if(cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:strCell];
}
cell.textLabel.text = arrData[indexPath.row];
return cell;
}
The Printed results For Contacts
The contacts are - (
"John Appleseed",
"Kate Bell",
"Anna Haro",
"Daniel Higgins",
"David Taylor",
"Hank Zakroff"
)
Screenshot below
When first you run the app
Now it shows contacts in table view

Hiding an autocomplete UITableView that was created programmatically

I'm building an application with an autocomplete UITableView from this tutorial. I have the autocomplete functionality working properly, but I would like the UITableView-autocomplete drop down to disappear when the word is clicked on or when it is touched up outside. I'm not sure how to set up a delegate when the object is set up programmatically. I've only done this using the interface builder.
.h
#interface slrpViewController : UIViewController<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>
{
NSMutableArray *dataArray;
NSMutableData *receivedData;
NSMutableArray *pastUrls;
NSMutableArray *autocompleteUrls;
UITableView *autocompleteTableView;
}
#property(nonatomic, retain) IBOutlet UITextField *eWordEntered;
#property (nonatomic, retain) NSMutableArray *pastUrls;
#property (nonatomic, retain) NSMutableArray *autocompleteUrls;
#property (retain, nonatomic) NSMutableData *responseData;
#property (nonatomic, retain) UITableView *autocompleteTableView;
-(void)setReceivedData:(NSMutableData*)pReceivedData;
-(NSMutableData *) getReceivedData;
-(void) getAutoCompleteArray;
-(void)searchAutocompleteEntriesWithSubstring:(NSString *)substring;
.m
- (void)viewDidLoad
{
[super viewDidLoad];
[self getAutoCompleteArray];
pastUrls = [[NSMutableArray alloc] init];
NSLog(#"In the viewDidLoad and pasturl is: %#", self.pastUrls);
self.autocompleteUrls = [[NSMutableArray alloc] init];
autocompleteTableView = [[UITableView alloc] initWithFrame:CGRectMake(210, 225, 310, 120) style:UITableViewStylePlain];
self.autocompleteTableView.delegate = self;
self.autocompleteTableView.dataSource = self;
autocompleteTableView.scrollEnabled = YES;
autocompleteTableView.hidden = YES;
[self.view addSubview:autocompleteTableView];
-(void)setReceivedData:(NSMutableData*)pReceivedData
{
receivedData = pReceivedData;
}
-(NSMutableData *) getReceivedData{
return receivedData;
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
[receivedData setLength:0];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{[receivedData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *e = nil;
NSError *error = nil;
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: receivedData options: NSJSONReadingMutableContainers error: &e];
NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:receivedData
options:kNilOptions
error:&error];
seneca_word.ids = [jsonDict objectForKey:#"ids"];
NSArray *array_ids = [jsonDict objectForKey:#"ids"];
NSString *ids = array_ids[0];
seneca_word.ids = ids;
for (id key in jsonDict)
{
NSLog(#"key: %#, value: %#", key, [jsonDict objectForKey:key]);
NSLog(#"The value of bases by itself is: %#", [jsonDict objectForKey:#"bases"]);
}
if (!jsonArray)
{
NSLog(#"Error parsing JSON: %#", e);
}
else
{
if([jsonDict objectForKey:#"english"] != nil){
pastUrls = [jsonDict objectForKey:#"bases"];
}
else{
//Some of JSON object that I don't want to use here
}//else
}//(void)connectionDidFinishLoading
- (void)searchAutocompleteEntriesWithSubstring:(NSString *)substring {
[autocompleteUrls removeAllObjects];
for(NSString *curString in pastUrls) {
NSRange substringRange = [curString rangeOfString:substring];
if (substringRange.location == 0) {
[autocompleteUrls addObject:curString];
}
}
[autocompleteTableView reloadData];
}
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
autocompleteTableView.hidden = NO;
NSString *substring = [NSString stringWithString:textField.text];
substring = [substring stringByReplacingCharactersInRange:range withString:string];
[self searchAutocompleteEntriesWithSubstring:substring];
return YES;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger) section {
return autocompleteUrls.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = nil;
static NSString *AutoCompleteRowIdentifier = #"AutoCompleteRowIdentifier";
cell = [tableView dequeueReusableCellWithIdentifier:AutoCompleteRowIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AutoCompleteRowIdentifier];
}
cell.textLabel.text = [autocompleteUrls objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
self.eWordEntered.text = selectedCell.textLabel.text;
if(tableView == autocompleteTableView){
//The autocomplete table view is the one that fired the didSelect delegate method
//So hide the autocomplete table.
//do whatever else you need to do to empty the autocompleteTableView's data source
//or/and simply hide the table after that
[autocompleteTableView setHidden:YES];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//When the user clicks outside of the uitableview it will disappear
[autocompleteTableView setHidden:YES];
}
As you can see I populate the autocomplete UITableView with JSON data that I'm getting from a RESTful API.
I'm getting the warning, Assigning to 'id<UITableViewDelegate>' from incompatible type 'ViewController *const __strong' for the lines:
self.autocompleteTableView.delegate = self;
self.autocompleteTableView.dataSource = self;
I imagine once I get the delegate stuff sorted out I'll be able to do what I want. I did some research and tried to create a delegate class but wasn't able to get that solution working. I'm not even sure if that's the right way to go about this as I usually do this stuff by interface builder and not programmatically. Any direction or help is greatly appreciated. Thanks!
You should be using the tableView's didSelectCellAtIndexPathRow delegate method to identify user taps on a cell from a tableView. It's ok if you created your tableView progammatically.
Simply make sure the UIViewController conforms to the UITableViewDelegate and UITableViewDataSource` protocols.
make sure you set the tableView's delegate and dataSource property to self.
Implement the didSelectCellAtIndexPathRow delegate method in your viewController's .m file like so:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
}
Then inside that delegate method you need to help detect from which tableView your didSelect method got fired from as you only want to hide the autocomplete table when the user selects a cell from that table. So you do a simple tableView check like so:
if(tableView == autocompleteTableView){
//The autocomplete table view is the one that fired the didSelect delegate method
//So hide the autocomplete table.
//do whatever else you need to do to empty the autocompleteTableView's data source
//or/and simply hide the table after that
[autocompleteTableView setHidden:YES];
}
You probably also want to make sure that you set the autocompleteTableView hidden property to NO when the user types in something in the textfield so that the auto complete can show appear again.
And thats all buddy.
try setting self.autocompleteTableView.hidden = YES;

Problems Populating TableView with NSMutableArray

I'm using SudzC for an iPhone app. I'm succesfully calling my ASP.Net webservice and pulling the needed data into an NSMutable array called tableData. I have a tableView that should display the contents of tableData; however this is not working. I've looked for hours at this problem. I'm very new to the Objective C world so I'm thinking it's a small oversight on my part. I've linked my TableView to the ViewController (delegate/datasource) as well.
Here's is the code I have:
#import "ViewController.h"
#import "DocumentServiceJSONService.h"
#interface ViewController ()
#end
#implementation ViewController
NSMutableArray *tableData;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewWillAppear:(BOOL) animated {
tableData = [[NSMutableArray alloc] init];
DocumentServiceJSONService* service = [[DocumentServiceJSONService alloc] init];
[service GetAllEMSDocumentsXMLAsString: self action:#selector(handleGetAllEMSDocuments:)];
[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(void) handleGetAllEMSDocuments:(id) result {
if ([result isKindOfClass:[NSError class]]) {
//if an error has occurred, handle it
return;
}
if([result isKindOfClass: [SoapFault class]]) {
return;
}
NSString* xmlString = result;
CXMLDocument *xmlDoc = [[CXMLDocument alloc] initWithXMLString:xmlString options:0 error:nil];
NSArray *nodes = NULL;
nodes = [xmlDoc nodesForXPath:#"//EMSDocuments" error:nil];
for (CXMLElement *node in nodes) {
NSMutableDictionary *item = [[NSMutableDictionary alloc] init];
int counter;
for (counter = 0; counter < [node childCount]; counter++) {
[item setObject:[[node childAtIndex:counter] stringValue] forKey:[[node childAtIndex:counter] name]];
}
//[item setObject:[[node attributeForName:#"DisplayName"] stringValue] forKey:#"DisplayName"];
NSString *displayName = [item objectForKey:#"DisplayName"];
[tableData addObject:displayName];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tableData count];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
cell.textLabel.text = [tableData objectAtIndex:indexPath.row];
return cell;
}
#end
Any advice is appreciated.
Make sure you have in your .h the delegate and datasource correctly set:
#interface YourViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
And if you are using XIBs for the user interface, that the tableview is connected to the File's Owner as datasource and delegate.
--
EDIT:
Creating a Outlet for you tableview:

TableView doesn't push to WebView

I'm trying to make an RSS Feed for my website inside the app. I'm trying to make it so that when the user clicks a cell in my TableView it brings you to the link of the specific post parsed. The link is being parsed, but the console gives me this error:
Application tried to push a nil view controller on target .
Here is my code:
WebViewController.h
#import <Foundation/Foundation.h>
#interface WebViewController : UIViewController
#property (nonatomic, readonly) UIWebView *webView;
#end
WebViewController.m
#import "WebViewController.h"
#implementation WebViewController
-(void)loadView
{
CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
[wv setScalesPageToFit:YES];
[self setView:wv];
}
-(UIWebView *)webView
{
return (UIWebView *)[self view];
}
#end
MasterViewController.h My TableView
#import <UIKit/UIKit.h>
// A forward declaration; we'll import the header in the .m
#class RSSChannel;
#class WebViewController;
#interface MasterViewController : UITableViewController
<NSXMLParserDelegate>
{
NSURLConnection *connection;
NSMutableData *xmlData;
RSSChannel *channel;
}
#property (strong, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) IBOutlet UINavigationItem *navigationBar;
#property (nonatomic, strong) WebViewController *webViewController;
- (void)fetchEntries;
#end
MasterViewController.m
#import "MasterViewController.h"
#import "WebViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
#implementation MasterViewController
#synthesize tableView = _tableView;
#synthesize navigationBar;
#synthesize webViewController;
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self fetchEntries];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#pragma mark - Table View
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIImage *myImage = [UIImage imageNamed:#"SephardiJewsHeader.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:myImage];
imageView.frame = CGRectMake(0,-1,320,93);
return imageView;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 93;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"The amount of items in the table: %u", [[channel items] count]);
return [[channel items] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"UITableViewCell"];
}
RSSItem *item = [[channel items] objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[item title]];
[[cell detailTextLabel] setText:[item date]];
return cell;
}
- (void)fetchEntries
{
// Create a new data container for the stuff that comes back from the service
xmlData = [[NSMutableData alloc] init];
// Construct a URL that will ask the service for what you want -
// Note we can concatenate literal strings together on multiple lines in this way it
// results in a single NSString instance
NSURL *url = [NSURL URLWithString:
#"http://sephardijews.com/feed/"];
// Putting the URL we made into an NSURLRequest, so we can connect to the url data that we specifed
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Creating a connecting that will exchange this request for the data from the URL we specifed
connection = [[NSURLConnection alloc] initWithRequest:req
delegate:self
startImmediately:YES];
}
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifedName
attributes:(NSDictionary *)attributeDict
{
NSLog(#"%# found a %# element", self, elementName);
if ([elementName isEqual:#"channel"]) {
// If the parser saw a channel, create new instance, store in our ivar
channel = [[RSSChannel alloc] init];
// Give the channel object a pointer back to ourselves for later
[channel setParentParserDelegate:self];
// Set the parser's delegate to the channel object
[parser setDelegate:channel];
}
}
// This method will be called several times as the data arrives
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always comes in the correct order
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
// Give it a delegate - don't worry about the warning
[parser setDelegate:self];
// Tell it to start parsing - the documet will be parsed and the delegate of NSXMLParser will get all of its delegate messages sent to it before this line finishes execution - it is blocking
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
// Get rid of the connection, no longer need it
connection = nil;
// Reload the table
[[self tableView] reloadData];
NSLog(#"%#\n %#\n %#\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we are done with it cause' there is no connection
// Setting the connection to nil will stop the connection because it is nothing/0
connection = nil;
// Release the xmlData object. We stopped to connection to put the data in the xmlData object, so we set it to nil also
xmlData = nil;
// Grab the description of the error object passed to us, so we can tell the user
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
// Create and show an alert view to the user with the error string to tell them the error in the process of the connection
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Error"
message:errorString
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
}
/* - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
WebViewController *aWebViewController = [[WebViewController alloc] init];
self.webViewController = aWebViewController;
[self.navigationController pushViewController:self.webViewController animated:YES];
RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];
NSURL *url = [NSURL URLWithString:[entry link]];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[[webViewController webView] loadRequest:req];
[[webViewController navigationItem] setTitle:[entry title]];
} */
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPost"]) {
WebViewController *awebViewController = [segue destinationViewController];
self.webViewController = awebViewController;
NSIndexPath *selectedRow = [self.tableView indexPathForSelectedRow];
RSSItem *entry = [[channel items] objectAtIndex:[selectedRow row]];
NSURL *url = [NSURL URLWithString:[entry link]];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[[webViewController webView] loadRequest:req];
[[webViewController navigationItem] setTitle:[entry title]];
}
}
#end
Thanks for your help!
Your WebViewController isn't being initialized anywhere. Try this in your tableView:didSelectRowAtIndexPath::
WebViewController *aWebViewController = [WebViewController alloc] init];
self.webViewController = aWebViewController;
[self.navigationController pushViewController:self.webViewController animated:YES];
[aWebViewController release];
If you're using Storyboard, add a view controller and change its class to WebViewController. From the MasterViewController in the Storyboard, right-click on a cell and connect the push segue to the WebViewController. Click the push segue and change its identifier to something like "showPost" or whatever.
Go back to MasterViewController.m and delete your code from tableView:didSelectRowAtIndexPath: and add this:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showPost"]) {
WebViewController *aWebViewController = [segue destinationViewController];
NSIndexPath *selectedRow = [self.tableView indexPathForSelectedRow];
RSSItem *entry = [[channel items] objectAtIndex:[selectedRow row]];
NSURL *url = [NSURL URLWithString:[entry link]];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[aWebViewController.webView loadRequest:req];
aWebViewController.title = entry.title
}
}

How to make my UITableViewCell not just have a title and a subtitle, but a title, subtitle (date), and another label (summary)?

Trying to make an my RSS Feed app have the summary inside the label, I have parsed the description (summary), but I don't understand how to add it in the UITableViewCell. I am currently using UITableViewCellStyleSubtitle, so I can show the title of each post and the date below it. How do I add one more below it to show summary of each post?
MasterViewController.h (TableView Header)
#import <UIKit/UIKit.h>
#class RSSChannel;
#class WebViewController;
#interface MasterViewController : UITableViewController
<NSXMLParserDelegate>
{
NSURLConnection *connection;
NSMutableData *xmlData;
RSSChannel *channel;
}
- (void)fetchEntries;
#property (nonatomic, strong) WebViewController *webViewController;
#end
MasterViewController.m (TableView Implementation)
#import "MasterViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#interface MasterViewController () {
NSMutableArray *_objects;
}
#end
#implementation MasterViewController
#synthesize webViewController;
- (void)awakeFromNib
{
[super awakeFromNib];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self fetchEntries];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (void)insertNewObject:(id)sender
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"The amount of items in the table: %u", [[channel items] count]);
return [[channel items] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:#"UITableViewCell"];
}
RSSItem *item = [[channel items] objectAtIndex:[indexPath row]];
[[cell textLabel] setText:[item title]];
[[cell detailTextLabel] setText:[item date]];
return cell;
}
- (void)fetchEntries
{
// Create a new data container for the stuff that comes back from the service
xmlData = [[NSMutableData alloc] init];
// Construct a URL that will ask the service for what you want -
// Note we can concatenate literal strings together on multiple lines in this way it
// results in a single NSString instance
NSURL *url = [NSURL URLWithString:
#"http://sephardijews.com/feed/"];
// Putting the URL we made into an NSURLRequest, so we can connect to the url data that we specifed
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Creating a connecting that will exchange this request for the data from the URL we specifed
connection = [[NSURLConnection alloc] initWithRequest:req
delegate:self
startImmediately:YES];
}
- (void)parser:(NSXMLParser *)parser
didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qualifedName
attributes:(NSDictionary *)attributeDict
{
NSLog(#"%# found a %# element", self, elementName);
if ([elementName isEqual:#"channel"]) {
// If the parser saw a channel, create new instance, store in our ivar
channel = [[RSSChannel alloc] init];
// Give the channel object a pointer back to ourselves for later
[channel setParentParserDelegate:self];
// Set the parser's delegate to the channel object
[parser setDelegate:channel];
}
}
// Method used to start at the beginning of the instance of the tableview, it will intialize the connection method to retrieve the posts from the URL
/* - (id) initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
[self fetchEntries];
}
return self;
}
*/
// This method will be called several times as the data arrives
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always comes in the correct order
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:xmlData];
// Give it a delegate - don't worry about the warning
[parser setDelegate:self];
// Tell it to start parsing - the documet will be parsed and the delegate of NSXMLParser will get all of its delegate messages sent to it before this line finishes execution - it is blocking
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
// Get rid of the connection, no longer need it
connection = nil;
// Reload the table
[[self tableView] reloadData];
NSLog(#"%#\n %#\n %#\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we are done with it cause' there is no connection
// Setting the connection to nil will stop the connection because it is nothing/0
connection = nil;
// Release the xmlData object. We stopped to connection to put the data in the xmlData object, so we set it to nil also
xmlData = nil;
// Grab the description of the error object passed to us, so we can tell the user
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
// Create and show an alert view to the user with the error string to tell them the error in the process of the connection
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Error"
message:errorString
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Push the web view controller onto the navigation stack - this implicitly
// creates the web view controller's view the first time through
[[self navigationController] pushViewController:webViewController animated:YES];
//Grab the selected item
RSSItem *entry = [[channel items] objectAtIndex:[indexPath row]];
//Constructs a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Load the request into the web view
[[webViewController webView] loadRequest:req];
// Set the title of the web view controller's navifation item
[[webViewController navigationItem] setTitle:[entry title]];
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#end
Try changing the UITableViewCellStyle to custom and dragging in your own UITextLabel objects to the prototype cell. Make #propertys for each of your data items in your TableViewController...
#interface MasterViewController ()
NSMutableArray *_objects;
#property (nonatomic, strong) IBOutlet UILabel *title;
#property (nonatomic, strong) IBOutlet UILabel *date;
#property (nonatomic, strong) IBOutlet UILabel *summary;
#end
Then connect the UITextLabels to their respective data.