My ParseXML method reads the value of NSNumber, which can be incremented by a click of a button.
My ParseXML method has 240 objects, each 8 have an ID from 1 to 30.
The idea is that if i increment the NSNumber from 1 to 2, it refreshes my view and grabs the 8 objects that match the ID and displays it in my view.
That is exactly what is not doing.
.h
#interface FixturesController : UITableViewController
{
NSMutableData *_responseDataFixtures;
int goUp;
NSNumber *test;
}
#property (nonatomic, retain) NSArray *tableDataFixtures;
#property (nonatomic, strong) NSMutableArray *roundParser;
#property (nonatomic, strong) NSString *seasonRoundString;
#property (nonatomic, strong) NSNumber *seasonRoundNumber;
- (IBAction)goUpByOne:(UIButton *)sender;
-(void) parseXMLFixtures:(NSNumber *) giveME;
#end
.m
- (void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self parseXMLFixtures:#2];
}
- (void)viewDidLoad
{
[super viewDidLoad];
goUp = 1;
test = [NSNumber numberWithInt:goUp];
}
// this allows me to increment the count of NSNumber.
- (IBAction)goUpByOne:(UIButton *)sender {
goUp++;
test = [NSNumber numberWithInt:goUp];
goUp = [test intValue];
}
-(void) parseXMLFixtures:(NSNumber *) giveME
{
giveME = test;
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"There's no going back"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *xmlString = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSDictionary *xml = [NSDictionary dictionaryWithXMLString:xmlString];
NSMutableArray *items = [xml objectForKey:#"Match"];
NSMutableArray *newFixtureObjectArray = [[NSMutableArray alloc] init];
NSNull *nullValue = [NSNull null];
[newFixtureObjectArray insertObject:nullValue atIndex:0];
[newFixtureObjectArray insertObject:nullValue atIndex:1];
for (NSDictionary *dict in items) {
FixturesObject *myFixtures = [FixturesObject fixtureFromXMLDictionary:dict];
[newFixtureObjectArray addObject:myFixtures];
}
///////
_seasonRoundString = [NSString stringWithFormat:#"%d", [giveME intValue]];
_roundParser = [[NSMutableArray alloc]init];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"round == %#", _seasonRoundString];
NSArray *filteredArray = [newFixtureObjectArray filteredArrayUsingPredicate:predicate];
_roundParser = [NSMutableArray arrayWithArray:filteredArray];
[_roundParser insertObject:nullValue atIndex:0];
NSLog(#" Objects of Fixtures in my array %#", _roundParser);
/////
[self setTableDataFixtures:_roundParser];
}
Any suggestions? Thank you. I really need this to work so i can go sleep ˆˆ
Have you impleted the UITableViewDelegate, UITableViewDataSource methods yet?
The methods are:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{ }
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { }
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{}
You can follow this tutorial
Related
I'm trying to sort my tableview using NSSortDescriptor in a UISegmentedControl. When I log the Array to sort it shows the correct sorting order, but the tableview doesn't update after calling [self.tableView reloadData];
The data comes from an array which is populated by a json feed. I'm not using NSObjects to display the tableview, it's all populated from the NSArray. See code below:
#interface LinksTableViewController (){
NSArray *data;
}
#property (strong, nonatomic) NSArray *links;
#property (strong, nonatomic) NSArray *tNames;
#property (strong, nonatomic) NSArray *dThor;
#property (strong, nonatomic) NSArray *theLinker;
#property (strong, nonatomic) NSArray *anText;
#property (strong, nonatomic) NSArray *noDo;
#end
#implementation LinksTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
UISegmentedControl *statFilter = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"STAT1", #"STAT2", #"STAT3", #"STAT4", nil]];
[statFilter sizeToFit];
[statFilter addTarget:self action:#selector(MySegmentControlAction:) forControlEvents: UIControlEventValueChanged];
self.navigationItem.titleView = statFilter;
[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(refreshdelay:) userInfo:nil repeats:NO];
}
- (void)MySegmentControlAction:(UISegmentedControl *)segment
{
NSArray *arrayToSort = data;
if (segment.selectedSegmentIndex == 0)
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"pda" ascending:NO];
arrayToSort = [arrayToSort sortedArrayUsingDescriptors:#[sortDescriptor]];
NSLog(#"%#", arrayToSort);
}
else if (segment.selectedSegmentIndex == 1)
{
}
else if (segment.selectedSegmentIndex == 2)
{
}
else if (segment.selectedSegmentIndex == 3)
{
}
[self.tableView reloadData];
}
-(void)refreshdelay:(NSTimer*)timer
{
NSString *myString = [links absoluteString];
NSURL *JSONData = [NSURL URLWithString:myString];
NSData *datas = [NSData dataWithContentsOfURL:JSONData];
NSURLRequest *request = [NSURLRequest requestWithURL:JSONData];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
operation.responseSerializer = [AFJSONResponseSerializer serializer];
operation.responseSerializer.acceptableContentTypes = [operation.responseSerializer.acceptableContentTypes setByAddingObject:#"text/html"];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSArray *jsonResult = [NSJSONSerialization JSONObjectWithData:datas options:kNilOptions error:nil];
data = jsonResult;
NSMutableArray *names = [NSMutableArray array];
NSMutableArray *bLinks = [NSMutableArray array];
NSMutableArray *daThor = [NSMutableArray array];
NSMutableArray *bsLink = [NSMutableArray array];
NSMutableArray *ancTxt = [NSMutableArray array];
NSMutableArray *folLowd = [NSMutableArray array];
for (id itemfeed in jsonResult){
[names addObject:[NSString stringWithFormat:#"%#", itemfeed[#"ut"]]];
[bsLink addObject:[NSString stringWithFormat:#"%#", itemfeed[#"uu"]]];
[bLinks addObject:[NSString stringWithFormat:#"%#", itemfeed[#"upa"]]];
[daThor addObject:[NSString stringWithFormat:#"%#", itemfeed[#"pda"]]];
[ancTxt addObject:[NSString stringWithFormat:#"%#", itemfeed[#"lt"]]];
[folLowd addObject:[NSString stringWithFormat:#"%#", itemfeed[#"lf"]]];
self.links = names;
self.tNames = bLinks;
self.dThor = daThor;
self.theLinker = bsLink;
self.anText = ancTxt;
self.noDo = folLowd;
}
[self.tableView reloadData];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
}];
[operation start];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
static NSString *Cellidentifier = #"DataTableCellId";
LICustomCell *cell = (LICustomCell *) [tableView dequeueReusableCellWithIdentifier:Cellidentifier];
if (cell == nil) {
cell = [[LICustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:Cellidentifier];
NSArray *nib = [[NSBundle mainBundle]loadNibNamed:#"LiCellView" owner:self options:nil];
cell = nib[0];
NSString *sLink = self.links[indexPath.row];
NSString *aLink = self.tNames[indexPath.row];
NSString *aDa = self.dThor[indexPath.row];
NSString *theInk = self.theLinker[indexPath.row];
NSString *thAnk = self.anText[indexPath.row];
NSString *fLink = self.noDo[indexPath.row];
cell.ageLable.text = theInk;
}
return cell;
}
Looks like the data for your tableView is in 6 different arrays.
NSString *sLink = self.links[indexPath.row];
NSString *aLink = self.tNames[indexPath.row];
NSString *aDa = self.dThor[indexPath.row];
NSString *theInk = self.theLinker[indexPath.row];
NSString *thAnk = self.anText[indexPath.row];
NSString *fLink = self.noDo[indexPath.row];
Shouldn't you be sorting all of them? As your code stands now it's not clear how arrayToSort is connected to the data model of your tableView. You have NSArray *arrayToSort = data;, but it's not clear where data is initialized or where it's set (seems like you would want to set that in your JSON competition block). You also need to call [self.tableView reloadData]; at the end of MySegmentControlAction.
You can create a subclass of NSObject that has 6 NSString properties call it something like MyObject (but more descriptive). Then do something like:
for (id itemfeed in jsonResult){
MyObject *object = [[MyObject alloc]init];
object.sLink = [NSString stringWithFormat:#"%#", itemfeed[#"ut"]];
object.aLink = [NSString stringWithFormat:#"%#", itemfeed[#"uu"]];
...
[self.data addObject:object];
}
In the JSON competition block.
You then change cellForRowAtIndexPath to include something like
MyObject *object = [self.data objectAtIndex:indexPath.row]
cell.ageLable.text = object.theInk;
If you go this route you also need to update:
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"pda" ascending:NO];
specifically #"pda" to whatever you name the property in your NSObject subclass. #"dThor" if you follow the naming I used.
I am new to iOS programming and I need some advice. I want to create a table view with sections to learn how it works. I have some objects from a model class user. I fill data in the table view using dictionaries. The table view is in a view Controller in my storyboard. The code works, but I don't know if this is a good way to handle the data in my table. Is this a semantic mistake to do this like I did?
Please take a Look at my code and give me some advice.
My user object (User.h):
#interface User : NSObject
#property (nonatomic, strong) NSString *email;
#property (nonatomic, strong) NSString *firstName;
#property (nonatomic, strong) NSString *lastName;
#property (nonatomic, strong) NSString *city;
#end
Dummy function to fill users into an array (in a helper class):
- (NSMutableArray *) createUser
{
NSMutableArray *userArray = [[NSMutableArray alloc] init];
User *user1 = [[User alloc] init];
user1.firstName = #"Donald";
user1.lastName = #"Duck";
user1.email = #"donald_duck#disney.com";
user1.city = #"Entenhausen";
User *user2 = [[User alloc] init];
user2.firstName = #"Micky";
user2.lastName = #"Maus";
user2.email = #"micky#disney.com";
user2.city = #"Entenhausen";
User *user3 = [[User alloc] init];
user3.firstName = #"Daisy";
user3.lastName = #"Duck";
user3.email = #"daisy_duck#disney.com";
user3.city = #"Frankfurt";
User *user4 = [[User alloc] init];
user4.firstName = #"Goofy";
user4.lastName = #"Goof";
user4.email = #"goofy#disney.com";
user4.city = #"Berlin";
User *user5 = [[User alloc] init];
user5.firstName = #"Some";
user5.lastName = #"Body";
user5.email = #"somebody#disney.com";
user5.city = #"Somewhere";
User *user6 = [[User alloc] init];
user6.firstName = #"Dagobert";
user6.lastName = #"Duck";
user6.email = #"dagobert#disney.com";
user6.city = #"Mainz";
[userArray addObject:user1];
[userArray addObject:user2];
[userArray addObject:user3];
[userArray addObject:user4];
[userArray addObject:user5];
[userArray addObject:user6];
return userArray;
}
Function to create a dictionary object (in a helper class):
- (NSMutableDictionary *) createDictionaryFromArray: (NSMutableArray *) allData
{
NSArray *arrayKeys = [[NSArray alloc] initWithObjects:#"Entenhausen", #"Frankfurt", #"Berlin", #"Mainz", nil];
NSMutableDictionary *collection = [[NSMutableDictionary alloc] init];
for (int i=0; i < arrayKeys.count; i++) {
NSString *key = [arrayKeys objectAtIndex:i];
NSMutableArray *allValues = [[NSMutableArray alloc] init];
for (User *usr in allData) {
if([usr.city isEqualToString:key]) {
[allValues addObject:usr];
}
}
[collection setObject:allValues forKey:key];
}
return collection;
}
My table view controller class (TableViewController.h):
#import <UIKit/UIKit.h>
#import "HelperClass.h"
#interface TableViewController : UITableViewController <UITableViewDelegate, UITableViewDataSource> {
HelperClass *helper;
NSMutableArray *users;
NSArray *allKeys;
NSDictionary *dictionaryUsers;
}
TableViewController.m:
#import "TableViewController.h"
#implementation TableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
helper = [[HelperClass alloc] init];
users = [[NSMutableArray alloc] init];
users = [helper createUser];
dictionaryUsers = [[NSMutableDictionary alloc] init];
dictionaryUsers = [helper createDictionaryFromArray:users];
allKeys = [NSArray array];
allKeys = [dictionaryUsers allKeys];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{ // Return the number of sections.
return [allKeys count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSMutableArray *arrayValuesUsers = [[NSMutableArray alloc] init];
arrayValuesUsers = [dictionaryUsers objectForKey:[allKeys objectAtIndex:section]];
return [arrayValuesUsers count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [allKeys objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
User *user = [[User alloc] init];
NSMutableArray *usersInSection = [dictionaryUsers objectForKey:[allKeys objectAtIndex:indexPath.section]];
user = [usersInSection objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#, %#", user.lastName, user.firstName];
cell.detailTextLabel.text = user.email;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *usersInSection = [dictionaryUsers objectForKey:[allKeys objectAtIndex:indexPath.section]];
User *usr = [usersInSection objectAtIndex:indexPath.row];
NSLog(#"user: %#, %#", usr.lastName, usr.firstName);
}
#end
First of all thumbs up for using a HelperClass for implementing general functions. Only when you do it, make it at least a singleton, so that you not always have to call:
helper = [[HelperClass alloc] init];
Or if you only have functions like createUser, these methods should be class methods.
Here are two general hints, which came to my mind, when looking at your code:
You have too many allocations in your code. For example in your TableViewController you do:
users = [[NSMutableArray alloc] init];
users = [helper createUser];
So first you allocate a new array and the first thing the createUser function does is to allocate another array in memory, which is then returned. Your first allocated memory space is never used.
When it comes to tableViews don't use dictionaries. Always stick with arrays. A dictionary is not ordered and when iterating through a dictionary you might get different results each time. An array is ordered and objectOfIndex:i will always return the same object.
So I adjusted your code to have a dynamic tableView sorting your users into sections by their city and sorting them alphabetically. (I guess this was what you wanted to achieve). The new code is not completely clean. You could try to use NSArray instead of NSMutableArray everywhere to save some memory for example.
Your User.h is untouched.
Here is the new HelperClass.h
// HelperClass.h
#import <Foundation/Foundation.h>
#interface HelperClass : NSObject
+ (HelperClass *)sharedHelperClass;
+ (NSMutableArray *) createUser;
+ (NSMutableArray *) getAllCitiesFromUserArray: (NSMutableArray *)userArray;
+ (NSMutableArray *)getUsersOfUsersArray: (NSMutableArray *)userArray fromCity: (NSString *)city;
#end
And the HelperClass.m
// HelperClass.m
#import "HelperClass.h"
#import "User.h"
#implementation HelperClass
+ (HelperClass *)sharedHelperClass
{
//This returns always the same object of HelperClass
static dispatch_once_t pred;
static HelperClass *_sharedHelperClass = nil;
dispatch_once(&pred, ^{ _sharedHelperClass = [[self alloc] init]; });
return _sharedHelperClass;
}
- (id)init{
self = [super init];
if (!self) {
return nil;
}
return self;
}
+ (NSMutableArray *) createUser
{
NSMutableArray *userArray = [[NSMutableArray alloc] init];
User *user1 = [[User alloc] init];
user1.firstName = #"Donald";
user1.lastName = #"Duck";
user1.email = #"donald_duck#disney.com";
user1.city = #"Entenhausen";
User *user2 = [[User alloc] init];
user2.firstName = #"Micky";
user2.lastName = #"Maus";
user2.email = #"micky#disney.com";
user2.city = #"Entenhausen";
User *user3 = [[User alloc] init];
user3.firstName = #"Daisy";
user3.lastName = #"Duck";
user3.email = #"daisy_duck#disney.com";
user3.city = #"Frankfurt";
User *user4 = [[User alloc] init];
user4.firstName = #"Goofy";
user4.lastName = #"Goof";
user4.email = #"goofy#disney.com";
user4.city = #"Berlin";
User *user5 = [[User alloc] init];
user5.firstName = #"Some";
user5.lastName = #"Body";
user5.email = #"somebody#disney.com";
user5.city = #"Somewhere";
User *user6 = [[User alloc] init];
user6.firstName = #"Dagobert";
user6.lastName = #"Duck";
user6.email = #"dagobert#disney.com";
user6.city = #"Mainz";
[userArray addObject:user1];
[userArray addObject:user2];
[userArray addObject:user3];
[userArray addObject:user4];
[userArray addObject:user5];
[userArray addObject:user6];
return userArray;
}
+ (NSMutableArray *) getAllCitiesFromUserArray: (NSMutableArray *)userArray{
NSMutableArray *cityArray = [[NSMutableArray alloc] init];
for (User *user in userArray) {
if (![cityArray containsObject: user.city]){
[cityArray addObject:user.city];
}
}
//Sort the city array alphabetically (localizedCaseInsensitiveCompare even regards Umlaute)
[cityArray sortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
return cityArray;
}
+ (NSMutableArray *)getUsersOfUsersArray: (NSMutableArray *)userArray fromCity: (NSString *)city{
NSMutableArray *usersOfCityArray = [[NSMutableArray alloc] init];
for (User *user in userArray) {
if ([user.city isEqualToString:city]){
[usersOfCityArray addObject:user];
}
}
//Sort the array of custom objects by key lastName
NSSortDescriptor *sortDescriptor =
[NSSortDescriptor sortDescriptorWithKey:#"lastName"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)];
usersOfCityArray = [[usersOfCityArray sortedArrayUsingDescriptors:#[sortDescriptor]]mutableCopy];
return usersOfCityArray;
}
#end
The new TableViewController.h
// TableViewController.h
#import <UIKit/UIKit.h>
#interface TableViewController : UITableViewController
#end
And the new TableViewController.m
// TableViewController.m
#import "TableViewController.h"
#import "HelperClass.h"
#import "User.h"
#interface TableViewController ()
#property (nonatomic,strong) NSMutableArray *users;
#property (nonatomic,strong) NSMutableArray *sectionHeaders;
#end
#implementation TableViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//This gets the Array of Users from the HelperClass class method
//You could access the HelperClass Singleton with [HelperClass sharedHelperClass], but this is not needed in this case.
self.users = [HelperClass createUser];
self.sectionHeaders = [HelperClass getAllCitiesFromUserArray:self.users];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [self.sectionHeaders count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//Get the current section city
NSString *city = [self.sectionHeaders objectAtIndex:section];
NSMutableArray *sectionUsers =[HelperClass getUsersOfUsersArray:self.users fromCity:city];
return sectionUsers.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [self.sectionHeaders objectAtIndex:section];
}
- (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];
}
//Get the current section city
NSString *city = [self.sectionHeaders objectAtIndex:indexPath.section];
//Get users for the current city
NSMutableArray *sectionUsers =[HelperClass getUsersOfUsersArray:self.users fromCity:city];
//Get the user for the current cell
User *user = [sectionUsers objectAtIndex:indexPath.row];
cell.textLabel.text = [NSString stringWithFormat:#"%#, %#", user.lastName, user.firstName];
cell.detailTextLabel.text = user.email;
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//Get the current section city
NSString *city = [self.sectionHeaders objectAtIndex:indexPath.section];
//Get users for the current city
NSMutableArray *sectionUsers =[HelperClass getUsersOfUsersArray:self.users fromCity:city];
//Get the user for the current cell
User *user = [sectionUsers objectAtIndex:indexPath.row];
NSLog(#"user: %#, %#", user.lastName, user.firstName);
}
#end
I'm struggling to populate a Table View using JSON Data from Youtube (V 2.1) which has been parsed(Logged the output in the console)
Every time I am loading the Table View Controller, nothing is populated. I have even created a 'Video' class (NSObject). I'm struggling to understand what I'm doing wrong.
The following is my code:
Video.h
#import <Foundation/Foundation.h>
#interface Video : NSObject
#property (nonatomic, strong) NSString *title;
#property (nonatomic, strong) NSString *description;
#property (nonatomic, strong) NSString *thumbnail;
#property (nonatomic, strong) NSString *uploadedDate;
#property (nonatomic, strong) NSURL *url;
// Designated Initializer
- (id) initWithTitle:(NSString *)title;
+ (id) videoWithTitle:(NSString *)title;
- (NSURL *) thumbnailURL;
- (NSString *) formattedDate;
#end
Video.m
import "Video.h"
#implementation Video
- (id) initWithTitle:(NSString *)title {
self = [super init];
if ( self ){
self.title = title;
self.thumbnail = nil;
}
return self;
}
+ (id) videoWithTitle:(NSString *)title {
return [[self alloc] initWithTitle:title];
}
- (NSURL *) thumbnailURL {
// NSLog(#"%#",[self.thumbnail class]);
return [NSURL URLWithString:self.thumbnail];
}
- (NSString *) formattedDate {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *tempDate = [dateFormatter dateFromString:self.uploadedDate];
[dateFormatter setDateFormat:#"EE MMM,dd"];
return [dateFormatter stringFromDate:tempDate];
}
#end
Table View Controller implementation file (the one I'm trying to populate)
#import "FilmyViewController.h"
#import "Video.h"
#interface FilmyViewController ()
#end
#implementation FilmyViewController
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *videoURL = [NSURL URLWithString:#"http://gdata.youtube.com/feeds/api/users/OrtoForum/uploads?v=2&alt=jsonc"];
NSData *jsonData = [NSData dataWithContentsOfURL:videoURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
NSLog(#"%#",dataDictionary);
self.videoArray = [NSMutableArray array];
NSArray *videosArray = [dataDictionary objectForKey:#"items"];
for (NSDictionary *vDictionary in videosArray) {
Video *video = [Video videoWithTitle:[vDictionary objectForKey:#"title"]];
video.title = [vDictionary objectForKey:#"title"];
video.description = [vDictionary objectForKey:#"author"];
video.uploadedDate = [vDictionary objectForKey:#"uploaded"];
video.url = [NSURL URLWithString:[vDictionary objectForKey:#"url"]];
[self.videoArray addObject:video];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (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.videoArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Video *video = [self.videoArray objectAtIndex:indexPath.row];
// Configure the cell...
cell.textLabel.text = video.title;
cell.textLabel.text = video.description;
return cell;
}
/*
#pragma mark - Navigation
// In a story board-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
#end
Here's the JSON which I'm trying to extract from.
I looked for similar topics but didn't get any appropriate solution for this.
Research Link-one and Link-two is what i have been trying to follow.
Please let me know if there is any better approach for this.
What am i missing here?
Solution
Changed
NSArray *videosArray = [dataDictionary objectForKey:#"items"];
to:
NSArray *videosArray = dataDictionary[#"data"][#"items"];
Change
NSArray *videosArray = [dataDictionary objectForKey:#"items"];
to
NSArray *videosArray = dataDictionary[#"data"][#"items"];
Your items array is in the second level: rootJSON -> data -> items
If one had a NSString that needed a userid to be used as a URL for a request:
And one had a NSMutableArray that he wanted to Queue into the above call one at a time? So basically make 3 calls of NSString from the NSMutableArray .
One can check multiple UITableView cells and once completed I can index which cell rows were pushed. That is what userIDArray is used for now I want to make a call with the userID's I got back from userIDArray.
for (NSDictionary* userIDDict in userIDArray)
{
userIDArray = [[NSMutableArray alloc] init]; //I put this line in my viewdidload
NSNumber* userID = [userIDDict objectForKey:#"UserID"];
}
UserIDArray is the NSMutableArray .
This would be the NSLog from the NSMutableArray The Integer would be 1, 2 and 3.
UserID: 1
UserID: 2
UserID: 3
So in other words I would like to take the results from my NSMultiTableArray 1,2 and 3 to use within the NSString :
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=1"];
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=2"];
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=3"];
So I would make the first call and wait for a result, and then the second and finally the third.
Can this be done? I have search this link about Queues and this one but I am unsure if those are what I need?
UserDetailViewController.h file:
#interface UserDetailViewController : UIViewController <UITableViewDelegate>{
long long expectedLength;
long long currentLength;
UITableView *userTableView;
NSIndexPath* checkedIndexPath;
}
#property (nonatomic, retain) NSArray *userIDJson;
#property (strong, nonatomic) NSDictionary *userIDDict;
#property (nonatomic, retain) NSIndexPath* checkedIndexPath;
#property (nonatomic, strong) NSMutableArray *userIDArray;
#property (nonatomic) NSInteger currentUserIndex;
#end
UserDetailViewController.m file:
#interface UserDetailViewController ()
#end
#implementation UserDetailViewController
#synthesize userIDJson;
#synthesize userIDDict;
#synthesize checkedIndexPath;
#synthesize userIDArray;
#synthesize currentUserIndex;
- (void)viewDidLoad
{
[super viewDidLoad];
userIDArray = [[NSMutableArray alloc] init];
[self.navigationController setNavigationBarHidden:NO];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//return self.loadedSearches.count;
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.userIDJson.count;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
}
cell.textLabel.text = self.userIDJson[indexPath.row][#"UserName"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if([self.checkedIndexPath isEqual:indexPath])
{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else
{
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *userStringIndex = [self.userIDJson objectAtIndex:indexPath.row];
if (thisCell.accessoryType == UITableViewCellAccessoryNone)
{
thisCell.accessoryType = UITableViewCellAccessoryCheckmark;
[userIDArray addObject:userStringIndex];
}
else
{
thisCell.accessoryType = UITableViewCellAccessoryNone;
[userIDArray removeObject:userStringIndex];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.currentUserIndex < userIDArray.count) {
NSNumber* userID = [[userIDArray objectForIndex:currentUserIndex]objectForKey:#"UserID"];
//Make the actual request here, and assign the delegate.
NSString *userProfile = [NSString stringWithFormat:#"http://example.com/userid=%#",userID];
self.currentUserIndex++;
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:userProfile]];
NSString *userResult = [[NSString alloc] initWithData:dataURL encoding:NSUTF8StringEncoding];
NSURL *url = [[NSURL alloc] initWithString: userProfile];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
userIDJson = [NSJSONSerialization JSONObjectWithData:dataURL
options:kNilOptions
error:&error];
}
}
for (userIDDict in userIDArray)
{
NSNumber* userID = [userIDDict objectForKey:#"UserID"];
NSLog(#"%#", userID);
NSArray* userName = [userIDDict objectForKey:#"UserName"];
}
NSURLConnection can take a delegate through the constructor initWithRequest:delegate:. So you need the object that makes the calls conform to that protocol, I'll assume it's a UIViewController. You can use one of the required methods in the delegate to fire up the next request.
For example, assume you have property to indicate the current index.
#property (nonatomic) NSInteger currentUserIndex;
Then in the place that will fire the first request, make the call for the first user. In some delegate method, say connectionDidFinishLoading:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if (self.currentUserIndex < self.userIDArray.count) {
NSNumber* userID = [[self.userIDArray objectAtIndex:self.currentUserIndex] objectForKey:#"UserID"];
self.currentUserIndex++;
//Make the actual request here, and assign the delegate.
}
}
Of course, if your connection calls don't have to be synchronous, you can do it in an easier way.
Request my test webService for the data,
The tableView's last row is "More data..."
when click this row, send another request to get more data,
and I use [tableView reloaddata] many times, but there is nothing
happened, and I dont know why.So,please help me with this problem.
Thank you in advance.
and there is my tableViewController.h class:
#import <UIKit/UIKit.h>
#import "NoticeDetailViewController.h"
#interface NoticeViewController : UIViewController
<UITableViewDataSource,UITableViewDelegate>
{
NSMutableArray *allNoticeArray;
NSArray *addNoticeArray;
NSInteger totalNotice;
NSInteger pageIndex;
UITableView *tableView;
}
#property (nonatomic, retain) NSMutableArray *allNoticeArray;
#property (nonatomic, retain) NSArray *addNoticeArray;
#property NSInteger totalNotice;
#property NSInteger pageIndex;
#property (nonatomic, retain) UITableView *tableView;
- (NSMutableArray *)getNoticeList :(NSInteger)pageIndex;
#end
And tableViewController.m class:
#import "NoticeViewController.h"
#import "Notice.h"
#import "OAURLEncodingAdditions.h"
#interface NoticeViewController ()
#end
#implementation NoticeViewController
#synthesize allNoticeArray;
#synthesize addNoticeArray;
#synthesize pageIndex;
#synthesize tableView;
#synthesize totalNotice;
- (NSMutableArray *)getNoticeList :(NSInteger)pageIndex
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *userId = appDelegate.user.userId;
NSString *departmentId = appDelegate.user.departmentId;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"https://xxx.xxx.xx.xx/FMS/Pages/Service/FMService.svc/GetAnnouncement?userId=%#&departmentId=%#&pageIndex=%d&pageSize=%d",userId,departmentId,self.pageIndex,1]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setValidatesSecureCertificate:NO];
[request startSynchronous];
NSError *error = [request error];
if (!error)
{
NSString *responseString = [request responseString];
NSDictionary *responseDict = [responseString JSONValue];
NSArray *noticeArray = [responseDict objectForKey:#"d"];
NSMutableArray *arrayOfAllNotice = [[NSMutableArray alloc] init];
for (NSDictionary *noticeDic in noticeArray)
{
NSString *body = [noticeDic objectForKey:#"Body"];
NSString *departmentName = [noticeDic objectForKey:#"DepartmentName"];
NSString *noticeId = [noticeDic objectForKey:#"Id"];
NSString *isTop = [noticeDic objectForKey:#"IsTop"];
NSString *readState = [noticeDic objectForKey:#"ReadState"];
NSString *realName = [noticeDic objectForKey:#"RealName"];
NSString *title = [noticeDic objectForKey:#"Title"];
int noid = [noticeId intValue];
int isto = [isTop intValue];
int read = [readState intValue];
Notice *notice = [[Notice alloc] initWithBody:body
departmentName:departmentName
noticeId: noid
isTop:isto
readState:read
realName:realName
title:title];
[arrayOfAllNotice addObject:notice];
}
self.addNoticeArray = [[NSArray alloc] initWithArray:arrayOfAllNotice];
}
else
{
....
}
[allNoticeArray addObjectsFromArray:addNoticeArray];
NSLog(#"allNoticeArray count: %d",[allNoticeArray count]); //Here:When the last row clicked, the number changes:1->2
[self.tableView reloadData];
return allNoticeArray;
}
#pragma mark -
#pragma mark Table View Data Source Methods
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger theNumberOfRowsInSection;
if ( [allNoticeArray count] < (self.totalNotice))
{
theNumberOfRowsInSection = [allNoticeArray count]+1;
}
if ( [allNoticeArray count] == (self.totalNotice))
{
theNumberOfRowsInSection = [allNoticeArray count];
}
return theNumberOfRowsInSection;
}
- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView reloadData];
static NSString *NoticeListTableIdentifier = #"NoticeListTableIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:NoticeListTableIdentifier];
if ( cell == nil )
{
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NoticeListTableIdentifier] autorelease];
}
if ( [allNoticeArray count] < (self.totalNotice) )
{
if ( [indexPath row] != [allNoticeArray count])
{
NSUInteger row = [indexPath row];
Notice *noticeOfTheRow = [allNoticeArray objectAtIndex:row];
NSString *title = noticeOfTheRow.title;
cell.textLabel.text = title;
}
else
{
cell.textLabel.text = #"More...";
}
}
if ( [allNoticeArray count] == (self.totalNotice) )
{
NSUInteger row = [indexPath row];
Notice *noticeOfTheRow = [allNoticeArray objectAtIndex:row];
NSString *title = noticeOfTheRow.title;
cell.textLabel.text = title;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ( [indexPath row] != [allNoticeArray count])
{
NSUInteger row = [indexPath row];
Notice *notice = [allNoticeArray objectAtIndex:row];
NSString *noticeDetailTitle = notice.title;
NoticeDetailViewController *noticeDetailViewController = [[[NoticeDetailViewController alloc] init] autorelease];
noticeDetailViewController.title = noticeDetailTitle;
ticeDetailViewController.noticeIdForGet = notice.noticeId;
[self.navigationController pushViewController:noticeDetailViewController animated:YES];
}
if ( [indexPath row] == [allNoticeArray count])
{
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"reload...";
self.pageIndex ++;
[self getNoticeList:self.pageIndex];
[self.tableView reloadData];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
}
- (void)pushBack
{
[self dismissModalViewControllerAnimated:YES];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.allNoticeArray = [[NSMutableArray alloc] init];
self.pageIndex = 1;
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
hud.labelText = #"reload...";
self.title = #"Notice";
UIBarButtonItem *leftButton = [[UIBarButtonItem alloc] initWithTitle:#"back"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(pushBack)];
self.navigationItem.leftBarButtonItem = leftButton;
UIBarButtonItem *rightButton = [[UIBarButtonItem alloc] initWithTitle:#"reload"
style:UIBarButtonItemStyleBordered
target:self
action:#selector(reloadNotice)];
self.navigationItem.rightBarButtonItem = rightButton;
self.allNoticeArray = [self getNoticeList:self.pageIndex];
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
#end
change:
if ( [indexPath row] == [allNoticeArray count])
to:
if ( [indexPath row] == [allNoticeArray count]-1)
The reason is that array (and row) indexing are base 0. So if an array has, say 3 objects, last object's index is 2
BTW,with the new language features, there's no need to declare the ivars in the interface. The compiler will take care of them if you have already declared the properties and synthesized them.
#interface NoticeViewController : UIViewController
<UITableViewDataSource,UITableViewDelegate>
{
NSMutableArray *allNoticeArray;
NSArray *addNoticeArray;
NSInteger totalNotice;
NSInteger pageIndex;
UITableView *tableView;
}
//...
#end