UITableViewController doesn't refresh correctly - ios

I'm building an app (UITabBar) where I'm storing a NSMutableArray of custom objects. My custom object is called DayModel.
My DayModel.h file:
#import <Foundation/Foundation.h>
#interface DayModel : NSObject
#property (nonatomic, retain) NSDate *mydate;
#property (nonatomic) float myFloat;
#end
My DayModel.m file:
#import "DayModel.h"
#implementation DayModel
#synthesize myDate, myFloat;
-(id)init {
// Init self
self = [super init];
if (self) {
// Setup
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder;
{
[coder encodeObject:self.myDate forKey:#"myDate"];
[coder encodeObject:self.myFloat forKey:#"myFloat"];
}
- (id)initWithCoder:(NSCoder *)coder;
{
self = [[DayModel alloc] init];
if (self != nil)
{
self.myDate = [coder decodeObjectForKey:#"myDate"];
self.myFloat = [coder decodeFloatForKey:#"myFloat"];
}
return self;
}
#end
The "main" ViewController, saving the new objects:
// Add data to the DayModel class
DayModel *currentDay = [[DayModel alloc] init];
currentDay.myDate = myDate;
currentDay.myFloat = myFloat;
// Add currentDay to the _objects NSMutableArray
[_objects insertObject:currentDay atIndex:0];
// Save this array using NSKeyedArchiver
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:_objects] forKey:#"objects"];
my UITableViewController displaying this:
viewWillAppear
// Load the _objects array
NSData *objectsData = [defaults objectForKey:#"objects"];
if (objectsData != nil)
{
NSArray *oldArray = [NSKeyedUnarchiver unarchiveObjectWithData:objectsData];
if (oldArray != nil)
{
_objects = [[NSMutableArray alloc] initWithArray:oldArray];
} else
{
_objects = [[NSMutableArray alloc] init];
}
} else
{
_objects = [[NSMutableArray alloc] init];
}
Other methods:
- (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 [_objects count];
}
Loading the data:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
// Get the DayModel
DayModel *currentModel = [[DayModel alloc] init];
currentModel = _objects[indexPath.row];
// Get the UILabels
UILabel *dateLabel = (UILabel *)[cell viewWithTag:10];
UILabel *floatLabel = (UILabel *)[cell viewWithTag:20];
// Create the DateFormatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"dd-MM-yyyy"];
// Set the text
dateLabel.text = [dateFormatter stringFromDate:currentModel.myDate];
floatLabel.text = [NSString stringWithFormat:#"%.02f", currentModel.myFloat];
return cell;
}
Reproducing the problem:
Add item from tab nr 1
Go to tab nr 2 (table). Data is displayed correctly
Go to tab nr 1 and add new object
Go to tab nr 2 (table). New item is displayed with data from previews item, not new data.
When the app is reloaded, the table displays correctly.
EDIT
What happens is that the new item is added at index 0 to appear at the top of the list, while the tableview class get's the new information from the last row when it should be getting it from the top. How can I "reverse" this?
Thanks!
Erik

I fixed it by reloading the whole list, not only adding the new item. This code is going under the lines loading the list from NSUserDefaults (viewWillAppear).
// Reload the UITableView completely
[self.tableView reloadData];
Please tell me if there's a better solution:)

Related

iOS table view with data from an NSDictionary

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

TableViewController - one key value offset to the others

I've got a problem with my TableViewController. I'm posting 3 values to the tableViewController. A scoreID, a scoreDate, and a scoreValue. It all seems to work correctly, but my problem is, that the scoreValue is offset by 1 to the scoreID and Date. It's easier to show with a picture:
("A good business idea" Should have the value of "another good idea" and so on and and so on)
Now, I know from looking in the .sqlite database file, that the scores are offset by one. So my question is how to fix it?
My tableViewController.m looks like this:
#import "CEWTableViewCell.h"
#interface CEWScoreTableViewController ()
#property (nonatomic) NSInteger countOfRows;
#property (nonatomic, strong) NSMutableArray *scoreIDsForTableCells;
#property (nonatomic, strong) NSArray *fetchedObjects;
#property (nonatomic, strong) NSDictionary *getScoreDataToDict;
#end
#implementation CEWScoreTableViewController{
UITableView *tableView;
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
CGFloat topLayoutGuide = self.topLayoutGuide.length;
tableView.contentInset = UIEdgeInsetsMake(topLayoutGuide, 0, 0, 0);
tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
tableView.delegate = self;
tableView.dataSource = self;
[self.tableView registerClass:[CEWTableViewCell class] forCellReuseIdentifier:#"CellID"];
tableView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:tableView];
//INITIALISE APPDELEGATE AND CREATE INSTANCE. MAKE FETCH REQUEST AND POPULATE DATA TO NSDICTIONARY
CEWAppDelegate* appDelegate = [UIApplication sharedApplication].delegate;
self.managedObjectContext = appDelegate.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
fetchRequest.resultType = NSDictionaryResultType;
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ScoreData" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSError *error = nil;
self.fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchRequest == nil) {
NSLog(#"an error occured fetching objects...!");
}
NSLog(#"objectForKey returns: %#", self.scoreIDFromEntity);
NSUInteger countIDsForRows = [self.fetchedObjects count];
self.countOfRows = countIDsForRows;
}
- (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.
//This value is set to the number of #"scoreID"s returned
return self.countOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellIdentifier = #"CellID";
CEWTableViewCell *cell = (CEWTableViewCell *)[self.tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[CEWTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
self.getIndexPath = indexPath.row;
NSDictionary *getScoreIDs = [self.fetchedObjects objectAtIndex:[indexPath row]];
NSDictionary *getDates = [self.fetchedObjects objectAtIndex:[indexPath row]];
//This is just formatting the date to the format I want displayed
NSDate *pullDates = [getDates valueForKey:#"scoreDate"];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MMM-yyyy HH:MM"];
NSString *formattedDate = [dateFormat stringFromDate:pullDates];
//Here I fetch the #"scoreValue"s and convert them from a string, so I can add them up
NSDictionary *getScoreValues = [self.fetchedObjects objectAtIndex:[indexPath row]];
NSString *convertDictKeyToString = [getScoreValues objectForKey:#"scoreValue"];
NSArray *items = [convertDictKeyToString componentsSeparatedByString:#","];
double total = 0.0;
for (NSString *string in items)
{
total += [string floatValue];
}
cell.descriptionLabel.text = [getScoreIDs objectForKey:#"scoreID"];
cell.dateLabel.text = formattedDate;
cell.tableCellScoreLabel.text = [NSString stringWithFormat:#"%1.1f", total];
return cell;
}
I hope this is enough code, otherwise let me know, and I will try and provide more
ANSWER
Sooooooo. It turns out, that my labels was offset because of the CGRect x,y,x,y values.... Ehrm...
In my experience cellForRowAtIndexPath gets called really fast so it doesn't have a lot of time to perform calculations, and for what I've read formatters take more resources than what you think.
I usually solve this issue by creating a new method that gets called from viewDidLoad or viewWillAppear, and in this method I create an array or some sort of container for the data I need.
Then cellForRowAtIndexPath only has to call the array by indexes.

How to implement MWFeedParser in my project

I'm trying to use the MWFeedParser library in my app. On my homescreen, I have a view controller named NewsViewController.
In the MWFeedParser library, the root view controller is called RootViewController. I've tried to copy all the code from the RootViewController into the NewsViewController .H + .M and in IB I've linked the tableview to "dataSource" and "delegate". But when my app starts the tableview is empty.
Here's how to code looks like:
.H:
#import <UIKit/UIKit.h>
#import "MWFeedItem.h"
#import "MWFeedParser.h"
#interface NewsViewController : UITableViewController <MWFeedParserDelegate, UITableViewDelegate, UITableViewDataSource> {
// Parsing
MWFeedParser *feedParser;
NSMutableArray *parsedItems;
// Displaying
NSArray *itemsToDisplay;
NSDateFormatter *formatter;
IBOutlet UITableView *tableView;
}
// Properties
#property (nonatomic, retain) NSArray *itemsToDisplay;
#property (nonatomic, retain) IBOutlet UITableView *tableView;
-(IBAction)goHome;
#end
.M:
#import "NSString+HTML.h"
#import "MWFeedParser.h"
#import "DetailTableViewController.h"
#implementation NewsViewController
#synthesize itemsToDisplay, tableView;
#pragma mark -
#pragma mark View lifecycle
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(#"News", #"News");
self.tabBarItem.image = [UIImage imageNamed:#"icon_news"]; }
return self;
}
- (void)viewDidLoad
{
label.shadowOffset = CGSizeMake(0.0f, 1.0f);
label.textColor = [UIColor colorWithRed:0xB3/249.0 green:0xB3/252.0 blue:0xB3/253.0 alpha:1];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// Date
// Setup
formatter = [[NSDateFormatter alloc] init];
[formatter setDateStyle:NSDateFormatterShortStyle];
[formatter setTimeStyle:NSDateFormatterShortStyle];
parsedItems = [[NSMutableArray alloc] init];
self.itemsToDisplay = [NSArray array];
// Refresh button
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(refresh)];
// Parse
NSURL *feedURL = [NSURL URLWithString:#"http://www.mywebsite.com/feed/"];
feedParser = [[MWFeedParser alloc] initWithFeedURL:feedURL];
feedParser.delegate = self;
feedParser.feedParseType = ParseTypeFull; // Parse feed info and all items
feedParser.connectionType = ConnectionTypeAsynchronously;
[feedParser parse];
UIImage *someImage = [UIImage imageNamed:#"back_active1#2x.png"];
[button setBackgroundImage:someImage forState:UIControlStateHighlighted];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)viewDidAppear:(BOOL)animated {
static BOOL first = YES;
if (first) {
UIViewController *popup = [[Home1ViewController alloc] initWithNibName:#"Home1ViewController" bundle:nil];
[self presentViewController:popup animated:NO completion:nil];
first = NO;
}
}
#pragma mark -
#pragma mark Parsing
// Reset and reparse
- (void)refresh {
self.title = #"Refreshing...";
[parsedItems removeAllObjects];
[feedParser stopParsing];
[feedParser parse];
self.tableView.userInteractionEnabled = NO;
self.tableView.alpha = 0.3;
}
- (void)updateTableWithParsedItems {
self.itemsToDisplay = [parsedItems sortedArrayUsingDescriptors:
[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:#"date"
ascending:NO]]];
self.tableView.userInteractionEnabled = YES;
self.tableView.alpha = 1;
[self.tableView reloadData];
}
#pragma mark -
#pragma mark MWFeedParserDelegate
- (void)feedParserDidStart:(MWFeedParser *)parser {
NSLog(#"Started Parsing: %#", parser.url);
}
- (void)feedParser:(MWFeedParser *)parser didParseFeedInfo:(MWFeedInfo *)info {
NSLog(#"Parsed Feed Info: “%#”", info.title);
self.title = info.title;
}
- (void)feedParser:(MWFeedParser *)parser didParseFeedItem:(MWFeedItem *)item {
NSLog(#"Parsed Feed Item: “%#”", item.title);
if (item) [parsedItems addObject:item];
}
- (void)feedParserDidFinish:(MWFeedParser *)parser {
NSLog(#"Finished Parsing%#", (parser.stopped ? #" (Stopped)" : #""));
[self updateTableWithParsedItems];
}
- (void)feedParser:(MWFeedParser *)parser didFailWithError:(NSError *)error {
NSLog(#"Finished Parsing With Error: %#", error);
if (parsedItems.count == 0) {
self.title = #"Failed"; // Show failed message in title
} else {
// Failed but some items parsed, so show and inform of error
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Parsing Incomplete"
message:#"There was an error during the parsing of this feed. Not all of the feed items could parsed."
delegate:nil
cancelButtonTitle:#"Dismiss"
otherButtonTitles:nil];
[alert show];
}
[self updateTableWithParsedItems];
}
#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 itemsToDisplay.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];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell.
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
if (item) {
// Process
NSString *itemTitle = item.title ? [item.title stringByConvertingHTMLToPlainText] : #"[No Title]";
NSString *itemSummary = item.summary ? [item.summary stringByConvertingHTMLToPlainText] : #"[No Summary]";
// Set
cell.textLabel.font = [UIFont boldSystemFontOfSize:15];
cell.textLabel.text = itemTitle;
NSMutableString *subtitle = [NSMutableString string];
if (item.date) [subtitle appendFormat:#"%#: ", [formatter stringFromDate:item.date]];
[subtitle appendString:itemSummary];
cell.detailTextLabel.text = subtitle;
}
return cell;
}
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Show detail
DetailTableViewController *detail = [[DetailTableViewController alloc] initWithStyle:UITableViewStyleGrouped];
detail.item = (MWFeedItem *)[itemsToDisplay objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detail animated:YES];
// Deselect
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#end
Please help me fix this!
you can follow the following link to use MWFeedParser : https://0club1.blogspot.in/
If your Table view is empty, you could have got the following error:
NSURLSession/NSURLConnection HTTP load failed
To allow HTTP, we need to allow arbitrary loads in App Transport Security Settings. Select info.plist in your project, in Information property list add new list as App Transport Security Settings.
Within that add Allow Arbitary Loads and mark it as YES.

Problems populating UITableView with videos in iPod Library using MPMediaQuery

I'm trying to put together a simple app that lists all videos in the iPod library (movies, TV shows, etc) and allows the user to play any video they choose. The app is using a storyboard that has a NavigationController with the UITableView in it.
It looks like the query is actually getting the MPMediaItems, but the cells aren't being updated with the title of each movie. Can you take a look at this and tell me what I'm doing wrong?
Here's the .h:
#import <UIKit/UIKit.h>
#import <MediaPlayer/MediaPlayer.h>
#interface MovieListViewController : UITableViewController
{
MPMediaQuery * _movieQuery;
NSArray * _movieArray;
}
#property (nonatomic,strong) MPMediaQuery *movieQuery;
#property (nonatomic,strong) NSArray *movieArray;
#end
And here's the .m:
#import "MovieListViewController.h"
#interface MovieListViewController ()
#end
#implementation MovieListViewController
#synthesize movieQuery = _movieQuery,
movieArray = _movieArray;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInteger:MPMediaTypeAnyVideo] forProperty:MPMediaItemPropertyMediaType];
MPMediaQuery *movieQuery = [[MPMediaQuery alloc] init];
[movieQuery addFilterPredicate:predicate];
NSLog(#"movieQuery got back %u results",[[movieQuery items]count]);
self.movieArray = [movieQuery items];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Dispose of any resources that can be recreated.
self.movieQuery = nil;
self.movieArray = nil;
}
- (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 0;
}*/
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSLog(#"UITableView has %u rows",[self.movieArray count]);
return [self.movieArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
// Configure the cell...
MPMediaItem *item = [[self.movieQuery items]objectAtIndex:[indexPath row]];
cell.textLabel.text = [item valueForProperty:MPMediaItemPropertyTitle];
return cell;
}
Issue is with this line:
MPMediaItem *item = [[self.movieQuery items]objectAtIndex:[indexPath row]];
Change that to:
MPMediaItem *item = [movieArray objectAtIndex:[indexPath row]];
You didn't added anything to movieQuery object, you created a local MPMediaQuery object in viewDidLoad and used that.
Another solution:
Change the viewDidLoad like:
- (void)viewDidLoad
{
[super viewDidLoad];
MPMediaPropertyPredicate *predicate = [MPMediaPropertyPredicate predicateWithValue:[NSNumber numberWithInteger:MPMediaTypeAnyVideo] forProperty:MPMediaItemPropertyMediaType];
self.movieQuery = [[MPMediaQuery alloc] init];
[movieQuery addFilterPredicate:predicate];
NSLog(#"movieQuery got back %u results",[[self.movieQuery items]count]);
self.movieArray = [self.movieQuery items];
}

EXC_BAD_ACCESS crash when switching back and forth between views

I'm getting a EXC_BAD_ACCESS crash when switching back and forth between views. I'm having a problem finding the cause of this crash. In the simulator it always goes back to the main.m file and reports the crash in it.
But on my device the EXC_BAD_ACCESS show up on my custom UITableViewCell when I release it in the dealloc method. If I enable NSZombieEnabled my app doesn't crash at all.
Here is the .h file
#import <UIKit/UIKit.h>
#define kWinsAmountTagValue 2 // how many wins you have
#define kWinningsAmountTagValue 3 // how much money you won
#interface MyStatsViewController : UIViewController
<UITableViewDelegate, UITableViewDataSource,
UINavigationBarDelegate, UINavigationControllerDelegate>{
NSArray *list;
UITableView *theTable;
UITableViewCell *theCell;
}
#property (nonatomic, retain) NSArray *list;
#property (nonatomic, retain) IBOutlet UITableView *theTable;
#property (nonatomic, retain) IBOutlet UITableViewCell *theCell;
// dealloc and cleanup
-(void) dealloc;
// misc methods
-(void)loadData;
// demo data
-(NSArray *)tableData;
#end
Here is my .m file
#import "MyStatsViewController.h"
#implementation MyStatsViewController
#synthesize list;
#synthesize theTable;
#synthesize theCell;
#pragma mark - dealloc and cleanup
- (void)didReceiveMemoryWarning
{
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
NSLog(#"Memory Warning");
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.list = nil;
self.theTable = nil;
self.theCell = nil;
}
- (void)dealloc
{
[super dealloc];
[list release];
[theTable release];
[theCell release];
}
#pragma mark - misc methods
-(void) loadData
{
self.list = [self tableData];
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(void)viewWillAppear:(BOOL)animated
{
[self loadData];
[theTable reloadData];
}
#pragma mark - Table Data Source Methods
-(NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [list count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier =#"MyStatsCustomCellIdentifer";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier];
NSUInteger row = [indexPath row];
if (cell == nil) {
if (row == [list count] -1) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
} else {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MyStatsCustomCell"
owner:self
options:nil];
if ([nib count] > 0) {
cell = self.theCell;
} else {
NSLog(#"failed to load MyStatsCustomCell");
}
}
}
// Add custom stuff here for rows
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (row == [list count] -1) {
cell.textLabel.text = [list objectAtIndex:row];
} else {
UILabel *prizeLevel = (UILabel *)[cell viewWithTag:kPrizeLevelTagValue];
prizeLevel.text = [[list objectAtIndex:row] objectForKey:#"prizeLevel"];
UILabel *winsAmount = (UILabel *)[cell viewWithTag:kWinsAmountTagValue];
winsAmount.text = [[list objectAtIndex:row] objectForKey:#"winsAmount"];
UILabel *winningsAmount = (UILabel *)[cell viewWithTag:kWinningsAmountTagValue];
winningsAmount.text = [[list objectAtIndex:row] objectForKey:#"winningsAmount"];
}
//NSLog(#"theCell Retain: %i",[theCell retainCount]);
return cell;
}
#pragma mark - Table View Delegate Methods
-(void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - demo data
-(NSArray *)tableData
{
NSArray *prizeLevels = [[NSArray alloc] initWithObjects:
#"6-of-6", #"5-of-6", #"4-of-6",#"3-of-6", nil];
NSArray *winsAmount = [[NSArray alloc] initWithObjects:
#"0", #"0", #"2", #"100", nil];
NSArray *winngingsAmount = [[NSArray alloc] initWithObjects:
#"$0",#"$0", #"$45.50",#"$125.00", nil];
NSMutableArray *myGames = [[[NSMutableArray alloc] init] autorelease];
for (int i = 0; i < [prizeLevels count]; i++) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:[prizeLevels objectAtIndex:i] forKey:#"prizeLevel"];
[dict setObject:[winsAmount objectAtIndex:i] forKey:#"winsAmount"];
[dict setObject:[winngingsAmount objectAtIndex:i] forKey:#"winningsAmount"];
[myGames addObject:dict];
[dict release];
}
[prizeLevels release];
[winsAmount release];
[winngingsAmount release];
[myGames addObject:#"Spent: $1250.00"];
return myGames;
}
#end
Any help would be appreciated.
It is a good practice to clean up class's own variables before calling the super's destructor. A lot more details can be found here: Why do I have to call super -dealloc last, and not first?.

Resources