UICollectionView Cells Loading Same Items too many times - ios

Here is the layout of my app. I have a UICollectionView in a Tab Bar Controller. I have two different XML files located on server. Depending on subscription purchases, one of two xmls will be parsed, and each item gets added to an array, which the UICollectionView in turn displays. I use MKiCloudSync to store the NSUserDefault values across iCloud as the method to determine if a subscription is still valid or not, so the user can access the app on multiple devices.
I call [MKiCloudSync start]; on didFinishLaunchingWithOptions in the AppDelegate implementation file.
In the UICollectionViewController file, the layout is essentially this:
viewDidLoad adds listener for MKiCloudSync changes. If change is made, it runs the code to update the UI. viewWillAppear checks the NSUserDefaults to see if it should load paid or free XML, and parses based off of that. If user does not have subscription, the right bar button item allows them to purchase it, which calls the code to do so. Upon successful code, it runs the code refreshpaid which parses the paid xml.
That is the setup in theory. I ran the app on my device from Ad Hoc build, and purchased the subscription in sandbox environment. The UI Updated as it should to show the additional content available in the Paid XML.
I then deleted the app, restarted the device, and reinstalled the ad hoc build to ensure the iCloud sync was working. When the app started, it showed 11 cells for every single item (assuming somehow code to refresh got called 11 times somehow). If I navigate to another tab and come back, or click on a cell and pop back, it corrects itself and just shows 1 cell per item in the XML.
Now, here is the full code from my UICollectionView.m file:
- (void)viewDidLoad {
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver: self selector: #selector(updatetheui) name: NSUserDefaultsDidChangeNotification object: nil];
UINib *cellNib = [UINib nibWithNibName:#"NibCell" bundle:nil];
[self.collectionView registerNib:cellNib forCellWithReuseIdentifier:#"cvCell"];
self.collectionView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"shelves.png"]];
}
-(void)updatetheui {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *status = [defaults objectForKey:#"Pay?"];
NSString *expirationdate = [defaults objectForKey:#"expiration"];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MM/dd/yyyy"];
NSDate *date = [dateFormat dateFromString:expirationdate];
NSLog(#"Date: %#", [dateFormat stringFromDate:date]);
if ([status isEqualToString:#"PaidUp"]|([date timeIntervalSinceNow] > 0.0)) {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Status" style:UIBarButtonItemStyleBordered target:self action:#selector(statusofsubscription)];
self.navigationItem.leftBarButtonItem = nil;
NSLog(#"UPDATEUI PAY");
[_allEntries removeAllObjects];
[self.collectionView reloadData];
[self refreshpaid];
} else {
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Subscribe" style:UIBarButtonItemStyleBordered target:self action:#selector(buyButtonTapped:)];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Restore" style:UIBarButtonItemStyleBordered target:self action:#selector(timetorestore)];
[_allEntries removeAllObjects];
[self.collectionView reloadData];
[self refreshfree];
NSLog(#"UPDATEUI FREE");
}
}
- (void)viewWillAppear:(BOOL)animated {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *status = [defaults objectForKey:#"Pay?"];
NSString *expirationdate = [defaults objectForKey:#"expiration"];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MM/dd/yyyy"];
NSDate *date = [dateFormat dateFromString:expirationdate];
NSLog(#"Date: %#", [dateFormat stringFromDate:date]);
if ([status isEqualToString:#"PaidUp"]|([date timeIntervalSinceNow] > 0.0)) {
[self refreshpaid];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Status" style:UIBarButtonItemStyleBordered target:self action:#selector(statusofsubscription)];
self.navigationItem.leftBarButtonItem = nil;
NSLog(#"WILLAPPEARPAID");
}
else {
[self refreshfree];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Subscribe" style:UIBarButtonItemStyleBordered target:self action:#selector(buyButtonTapped:)];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Restore" style:UIBarButtonItemStyleBordered target:self action:#selector(timetorestore)];
}
//[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:YES];
}
- (void)viewWillDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)timetorestore {
[MKiCloudSync start];
UIAlertView *syncing = [[UIAlertView alloc]initWithTitle:#"Syncing" message:#"Now attempting to restore your subscription from iCloud. If unsuccessful, your subscription may have expired, or you may need to try again in a stronger network." delegate:self cancelButtonTitle:#"Okay" otherButtonTitles: nil];
[syncing show];
[syncing release];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
NSLog(#"1");
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [_allEntries count];
NSLog(#"2");
}
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
[UIView animateWithDuration:5.0
delay:0
options:(UIViewAnimationOptionAllowUserInteraction)
animations:^{
NSLog(#"animation start");
[cell setBackgroundColor:[UIColor colorWithRed: 180.0/255.0 green: 238.0/255.0 blue:180.0/255.0 alpha: 1.0]];
}
completion:^(BOOL finished){
NSLog(#"animation end");
[cell setBackgroundColor:[UIColor whiteColor]];
}
];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad )
{
if (_webViewController2 == nil) {
self.webViewController2 = [[[WebViewController2 alloc] initWithNibName:#"WebViewController2" bundle:[NSBundle mainBundle]] autorelease];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
_webViewController2.entry = entry;
[self.navigationController pushViewController:_webViewController2 animated:YES];
}
else {
if (_webViewController == nil) {
self.webViewController = [[[WebViewController alloc] initWithNibName:#"WebViewController" bundle:[NSBundle mainBundle]] autorelease];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
_webViewController.entry = entry;
[self.navigationController pushViewController:_webViewController animated:YES];
}
#endif
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
static NSString *cellIdentifier = #"cvCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
UIImageView *titleLabel = (UIImageView *)[cell viewWithTag:100];
UILabel *titleLabel2 = (UILabel *)[cell viewWithTag:200];
NSString *thearticleImage = entry.articleImage;
[titleLabel setImageWithURL:[NSURL URLWithString:entry.articleImage] placeholderImage:[UIImage imageNamed:#"icon#2x.png"]];
// [titleLabel2 setText:entry.articleTitle];
return cell;
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items) {
NSString *issueTitle = [item valueForChild:#"title"];
NSString *issueURL = [item valueForChild:#"link"];
NSString *articleDateString = [item valueForChild:#"pubDate"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
NSString *issueCoverArt = [item valueForChild:#"guid"];
NSLog(#"Title%#", issueTitle);
NSLog(#"Link%#", issueURL);
NSLog(#"Date%#", articleDateString);
NSLog(#"CoverArt%#", issueCoverArt);
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:issueTitle
articleUrl:issueURL
articleDate:articleDate
articleImage:issueCoverArt] autorelease];
[entries addObject:entry];
}
}
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:#"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
} else if ([rootElement.name compare:#"feed"] == NSOrderedSame) {
[self parseAtom:rootElement entries:entries];
} else {
NSLog(#"Unsupported root element: %#", rootElement.name);
}
}
- (void)requestFinished:(ASIHTTPRequest *)request {
[_queue addOperationWithBlock:^{
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
options:0 error:&error];
if (doc == nil) {
NSLog(#"Failed to parse %#", request.url);
} else {
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:entry atIndex:insertIdx];
[self.collectionView reloadData];
}
}];
}
}];
}

One possibility: you should always make sure that what get displayed is always what you intended. Take this as an example: (from my WFAsyncImageCell for iOS, it is largely the same principle on OS X.)
- (void)loadImage
{
if ([self.lastLoadedURL isEqual:self.imageURL])
{
return; // The current image URL is being reloaded. Ignore.
}
self.imageView.image = nil;
NSURL *loadURL = self.imageURL;
dispatch_group_async(WFBackgroundTasks,
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
0),
^
{
// Get the image data. Possible check cached data
NSData *imageData = [NSData dataWithContentsOfURL:loadURL];
UIImage *image = [[UIImage alloc] initWithData:imageData];
if (!image)
{
// Oops, image file downloaded is bad.
image = [UIImage imageNamed:#"defaultFallback"];
}
else
{
// Cache it. Not gonna implement here in the demo.
}
dispatch_async(dispatch_get_main_queue(),
^
{
if ([loadURL isEqual:self.imageURL])
{
self.imageView.image = image;
}
else
{
// Oops, reload.
[self loadImage];
}
});
});

Related

iOS - Why my next view callback my previous view?

My situation is the next :
I have two view controller.
The first contains an UITableView. When I tap on a cell, the second view is called and display another UITableView.
Problem :
Immediately that my second view has been displayed, it's removed and my app come back on the first view.
In debug mode, I can see that viewDidLoad() is called and the TableView has been initialised because the TableView is filled.
But I don't know why, viewWillDisappear() is called immediately, as if the view was removed...
Could someone to help me out please?
EDIT :
My first View :
#import "CIMSaddlesResearchesSavedViewController.h"
#import <Foundation/Foundation.h>
#interface CIMSaddlesResearchesSavedViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation CIMSaddlesResearchesSavedViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackground"] forBarMetrics:UIBarMetricsDefault];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
}
- (UIStatusBarStyle) preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.researches count];
}
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"researchCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
CIMSaddleResearch *research;
research = self.researches[indexPath.row];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"researchCell"];
}
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor clearColor];
if (research.dbId && ![research.dbId isEqual:#""]) {
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"dd/MM/yyyy"];
NSMutableString *minPrice = [NSMutableString stringWithString:#""];
NSMutableString *maxPrice = [NSMutableString stringWithString:#""];
NSMutableString *currencyS = [NSMutableString stringWithString:#""];
CIMCurrency *currency = [[CIMCurrency alloc] init];;
NSMutableString *researchText = [NSMutableString stringWithString:#""];
if (research.customer && ![research.customer isEqual:#""]) {
CIMCustomer *customer = [[CIMCustomer alloc] init];
customer.dbId = research.customer;
customer = [dbMngr firstObjectFromDb:customer];
[researchText appendFormat:#"%# le %#", customer.lastName, [formatter stringFromDate:research.date]];
}
CIMSaddleResearchLine *researchLine = [[CIMSaddleResearchLine alloc] init];
researchLine.saddleResearch = research.dbId;
NSArray *lines = [dbMngr objectsFromDb:researchLine];
for(CIMSaddleResearchLine *line in lines){
if([line.field isEqualToString:#"PRIX_MIN"])
[minPrice appendFormat:#"%#", line.value];
else if([line.field isEqualToString:#"PRIX_MAX"])
[maxPrice appendFormat:#"%#", line.value];
else if([line.field isEqualToString:#"DEVISE"])
[currencyS appendFormat:#"%#", line.value];
}
if(![minPrice isEqual:#""] || ![maxPrice isEqual:#""]){
if(currencyS){
currency.dbId = currencyS;
currency = [dbMngr firstObjectFromDb:currency];
} else {
currency = [dbMngr defaultSocietyCurrency];
}
[researchText appendString:#" | Budget : "];
if(![minPrice isEqual:#""] && ![maxPrice isEqual:#""])
[researchText appendFormat:#"%#%# → %#%#", minPrice, currency.symbol, maxPrice, currency.symbol];
else if(![minPrice isEqual:#""] && [maxPrice isEqual:#""])
[researchText appendFormat:#"%#%# min.", minPrice, currency.symbol];
else if([minPrice isEqual:#""] && ![maxPrice isEqual:#""])
[researchText appendFormat:#"%#%# max.", maxPrice, currency.symbol];
}
NSMutableString *researchDetailText = [NSMutableString stringWithFormat:#"Relance le : %#", [formatter stringFromDate:research.deadline]];
CIMResearchStatus *status = [[CIMResearchStatus alloc] init];
status.dbId = research.status;
status = [dbMngr firstObjectFromDb:status];
if(status){
[researchDetailText appendFormat:#" (%#)", status.name];
}
cell.textLabel.text = researchText;
cell.detailTextLabel.text = researchDetailText;
if (research.comment && ![research.comment isEqual:#""] ) {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
} else {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"saddleCell"];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.text = NSLocalizedString(#"The saddle is not in this list", nil);
cell.textLabel.textAlignment = NSTextAlignmentCenter;
}
return cell;
}
-(void) tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath {
CIMSaddleResearch *research = self.researches[indexPath.row];
if (research.comment && ![research.comment isEqual:#""] ) {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:NSLocalizedString(#"Comment", nil)
message:research.comment
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *actionOk = [UIAlertAction actionWithTitle:NSLocalizedString(#"Ok", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action){}];
[alert addAction:actionOk];
[self presentViewController:alert animated:YES completion:nil];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.navigationController popViewControllerAnimated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"openResultResearch"]) {
UITableView *table = (UITableView*)[(UITableViewCell*)sender superview];
NSIndexPath *index = [table indexPathForCell:(UITableViewCell*) sender];
CIMSaddleResearch *research = self.researches[index.row];
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
CIMSaddleResearchLine *researchLine = [[CIMSaddleResearchLine alloc] init];
CIMSaddleResearchFormViewController *form = [[CIMSaddleResearchFormViewController alloc] init];
form.minimumPriceRow = [[XLFormRowDescriptor alloc] init];
form.maximumPriceRow = [[XLFormRowDescriptor alloc] init];
form.minimumYearRow = [[XLFormRowDescriptor alloc] init];
form.maximumYearRow = [[XLFormRowDescriptor alloc] init];
form.currency = [[CIMCurrency alloc] init];
NSMutableDictionary *filters = [[NSMutableDictionary alloc] initWithObjectsAndKeys:
[[NSMutableArray alloc] init], #"brand",
[[NSMutableArray alloc] init], #"model",
[[NSMutableArray alloc] init], #"size",
[[NSMutableArray alloc] init], #"color",
[[NSMutableArray alloc] init], #"finishing",
nil];
researchLine.saddleResearch = research.dbId;
NSArray *lines = [dbMngr objectsFromDb:researchLine];
NSSortDescriptor *sortFieldDesc = [[NSSortDescriptor alloc] initWithKey:#"field" ascending:YES selector:#selector(compare:)];
NSSortDescriptor *sortOrderDesc = [[NSSortDescriptor alloc] initWithKey:#"order" ascending:YES selector:#selector(compare:)];
lines = [lines sortedArrayUsingDescriptors:#[sortFieldDesc, sortOrderDesc]];
for(CIMSaddleResearchLine *line in lines){
if([line.field isEqualToString:#"PRIX_MIN"]){
form.minimumPriceRow.value = line.value;
}else if([line.field isEqualToString:#"PRIX_MAX"]){
form.maximumPriceRow.value = line.value;
}else if([line.field isEqualToString:#"ANNEE_MIN"]){
form.minimumYearRow.value = line.value;
}else if([line.field isEqualToString:#"ANNEE_MAX"]){
form.maximumYearRow.value = line.value;
}else if([line.field isEqualToString:#"DEVISE"]){
form.currency.dbId = line.value;
form.currency = [dbMngr firstObjectFromDb:form.currency];
}
else if([line.field isEqualToString:#"GA_REFCONSTRUC"]){
form.serialNumberRow.value = line.value;
}else if([line.field isEqualToString:#"GA_QUARTIER"]){
form.flapRow.value = line.value;
}else if([line.field isEqualToString:#"GA_MARQUE"]){
CIMBrand *brand = [[CIMBrand alloc] init];
brand.dbId = line.value;
[[filters objectForKey:#"brand"] addObject:[dbMngr firstObjectFromDb:brand]];
}else if([line.field isEqualToString:#"GA_MODEL"]){
CIMModel *model = [[CIMModel alloc] init];
model.dbId = line.value;
[[filters objectForKey:#"model"] addObject:[dbMngr firstObjectFromDb:model]];
}else if([line.field isEqualToString:#"GA_TAILLE"]){
CIMSize *size = [[CIMSize alloc] init];
size.dbId = line.value;
[[filters objectForKey:#"size"] addObject:[dbMngr firstObjectFromDb:size]];
}else if([line.field isEqualToString:#"GA_COULEUR"]){
CIMColor *color = [[CIMColor alloc] init];
color.dbId = line.value;
[[filters objectForKey:#"color"] addObject:[dbMngr firstObjectFromDb:color]];
}else if([line.field isEqualToString:#"GA_FINITION"]){
CIMFinishing *finishing = [[CIMFinishing alloc] init];
finishing.dbId = line.value;
[[filters objectForKey:#"finishing"] addObject:[dbMngr firstObjectFromDb:finishing]];
}
}
if(!form.currency.dbId && [form.currency.dbId isEqualToString:#""]){
CIMCustomer *customer = [[CIMCustomer alloc] init];
customer.dbId = research.customer;
customer = [dbMngr firstObjectFromDb:customer];
form.currency.dbId = customer.currency;
form.currency = [dbMngr firstObjectFromDb:form.currency];
}
CIMSaddlesViewController *saddlesViewController = segue.destinationViewController;
saddlesViewController.filters = filters;
saddlesViewController.saddleDbId = [NSMutableString stringWithString:#""];
saddlesViewController.selectionMode = NO;
saddlesViewController.saddleNotFoundOption = NO;
saddlesViewController.showSaddlePictures = YES;
saddlesViewController.showSaddleWarehouse = YES;
saddlesViewController.showToolbar = NO;
saddlesViewController.saddles = [dbMngr stockSaddlesWithFilters:filters
andSerialNumber:form.serialNumberRow.value
andFlap:form.flapRow.value
betweenMinimumPrice:form.minimumPriceRow.value
andMaximumPrice:form.maximumPriceRow.value
inCurrency:form.currency.dbId
betweenMinimumYear:form.minimumYearRow.value
andMaximumYear:form.maximumYearRow.value
inStock:YES];
saddlesViewController.formResearch = form;
saddlesViewController.saddlesPricesCurrency = form.currency;
}
}
#end
My second view :
#import "CIMSaddlesViewController.h"
#interface CIMSaddlesViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#end
#implementation CIMSaddlesViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
}
- (void) viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:#"NavigationBarBackground"] forBarMetrics:UIBarMetricsDefault];
}
- (void) viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
}
- (UIStatusBarStyle) preferredStatusBarStyle {
return UIStatusBarStyleLightContent;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.saddles count];
}
- (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
static NSString *reuseIdentifier = #"saddleCell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
CIMItem *saddle;
saddle = self.saddles[indexPath.row];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"saddleCell"];
}
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.backgroundColor = [UIColor clearColor];
if (saddle.dbId && ![saddle.dbId isEqual:#""]) {
NSMutableString *saddleText = [NSMutableString stringWithString:saddle.dbId];
NSMutableString *saddleDetailText = [NSMutableString stringWithString:saddle.name];
// Serial number
if (saddle.serialNumber && ![saddle.serialNumber isEqual:#""]) {
[saddleText appendFormat:#" - %#", saddle.serialNumber];
}
// Warehouse
if (self.showSaddleWarehouse) {
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
CIMStock *stock = [[CIMStock alloc] init];
stock.item = saddle.dbId;
stock.quantity = [NSNumber numberWithInt:1];
stock = [dbMngr firstObjectFromDb:stock];
if (stock) {
CIMWarehouse *warehouse = [[CIMWarehouse alloc] init];
warehouse.dbId = stock.warehouse;
warehouse = [dbMngr firstObjectFromDb:warehouse];
[saddleText appendFormat:#" → [%#]", warehouse.name];
}
}
// Estimed price
if (self.saddlesPricesCurrency) {
CIMDbManager *dbMngr = [[CIMDbManager alloc] init];
CIMSaddlePrices *saddlePrices = [[CIMSaddlePrices alloc] init];
saddlePrices.item = saddle.dbId;
saddlePrices.currency = self.saddlesPricesCurrency.dbId;
saddlePrices = [dbMngr firstObjectFromDb:saddlePrices];
if (saddlePrices) {
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setMaximumFractionDigits:0];
[numberFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[numberFormatter setCurrencyCode:self.saddlesPricesCurrency.isoCode];
NSString *isEstimateStr;
if ([saddlePrices.isEstimate isEqual:#"-"]) {
isEstimateStr = NSLocalizedString(#"Official price", nil);
} else {
isEstimateStr = NSLocalizedString(#"Estimation", nil);
}
[saddleText appendFormat:#" | %# (%#)", [numberFormatter stringFromNumber:saddlePrices.price], isEstimateStr];
}
}
cell.textLabel.text = saddleText;
cell.detailTextLabel.text = saddleDetailText;
// Saddle pictures
if (self.showSaddlePictures && [[self.saddlesPicturesDictionary allKeys] containsObject:saddle.dbId]) {
UIButton *accessoryButton = [[UIButton alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 40.0f, 40.0f)];
if ([self.saddlesiPadPictures containsObject:saddle.dbId]) {
[accessoryButton setImage:[UIImage imageNamed:#"SaddleiPadPictureButton"] forState:UIControlStateNormal];
} else {
[accessoryButton setImage:[UIImage imageNamed:#"SaddlePictureButton"] forState:UIControlStateNormal];
}
accessoryButton.tag = indexPath.row;
[accessoryButton addTarget:self action:#selector(showSaddlePicturesViewForSaddleWithSender:) forControlEvents:UIControlEventTouchDown];
cell.accessoryView = accessoryButton;
} else {
cell.accessoryView = nil;
}
} else {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"saddleCell"];
cell.backgroundColor = [UIColor whiteColor];
cell.textLabel.text = NSLocalizedString(#"The saddle is not in this list", nil);
cell.textLabel.textAlignment = NSTextAlignmentCenter;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (self.selectionMode) {
CIMItem *saddle = self.saddles[indexPath.row];
[self.saddleDbId setString:saddle.dbId];
[self.navigationController popViewControllerAnimated:YES];
} else {
[self.tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}
#end
To be honest, this project is very big, I begun to work on it since 2 month ago and I'm alone to work on it. I didn't work in Objective-C before and even less with X-Code. I'm discovering features and Objective-C gradually...
In your first VC you call [self.navigationController popViewControllerAnimated:YES]; which tells the navigationVC to pop the currently visible view controller. If you set breakpoints to the tableview didSelectRowAtIndexPath: in first VC and to viewDidLoad in your second VC you'll see in what order they are called. I have a feeling that the order of execution could be the following:
prepare for segue in firstVC
view did load in secondVC
didSelectRowAtIndexPath in first VC
finally your second VC unloads
This is my idea without testing it. Please make sure you really need to pop the VC in didSelectRow

Xcode Table view Data is getting duplicated when I pull to refresh

Hi My data is getting duplicated every time I use the pull to refresh.. for eg. 5 initial entries in the table view are doubled to 10 with one pull to refresh and adding 5 more in the subsequent pull to refresh. How can I stop the duplication.. I would like to make sure that only new items are downloaded and existing data in the table is not downloaded again.
#implementation RootViewController
#synthesize allEntries = _allEntries;
#synthesize feeds = _feeds;
#synthesize queue = _queue;
#synthesize webViewController = _webViewController;
#pragma mark -
#pragma mark View lifecycle
- (void)addRows {
RSSEntry *entry1 = [[[RSSEntry alloc] initWithBlogTitle:#"1"
articleTitle:#"1"
articleUrl:#"1"
articleDate:[NSDate date]] autorelease];
RSSEntry *entry2 = [[[RSSEntry alloc] initWithBlogTitle:#"2"
articleTitle:#"2"
articleUrl:#"2"
articleDate:[NSDate date]] autorelease];
RSSEntry *entry3 = [[[RSSEntry alloc] initWithBlogTitle:#"3"
articleTitle:#"3"
articleUrl:#"3"
articleDate:[NSDate date]] autorelease];
[_allEntries insertObject:entry1 atIndex:0];
[_allEntries insertObject:entry2 atIndex:0];
[_allEntries insertObject:entry3 atIndex:0];
}
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Songs";
self.allEntries = [NSMutableArray array];
self.queue = [[[NSOperationQueue alloc] init] autorelease];
self.feeds = [NSArray arrayWithObjects:
#"http://hindisongs.bestofindia.co/?feed=rss2",
nil];
self.refreshControl = [UIRefreshControl new];
self.refreshControl.attributedTitle = [[NSAttributedString alloc] initWithString:#"Pull to refresh"];
[self.refreshControl addTarget:self action:#selector(bindDatas) forControlEvents:UIControlEventValueChanged];
[self bindDatas]; //called at the first time
}
-(void)bindDatas
{
//GET YOUR DATAS HERE…
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
//update the tableView
[self.tableView reloadData];
if(self.refreshControl != nil && self.refreshControl.isRefreshing == TRUE)
{
[self.refreshControl endRefreshing];
}
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = [item valueForChild:#"link"];
NSString *articleDateString = [item valueForChild:#"pubDate"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate] autorelease];
[entries addObject:entry];
}
}
}
- (void)parseAtom:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSString *blogTitle = [rootElement valueForChild:#"title"];
NSArray *items = [rootElement elementsForName:#"entry"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = nil;
NSArray *links = [item elementsForName:#"link"];
for(GDataXMLElement *link in links) {
NSString *rel = [[link attributeForName:#"rel"] stringValue];
NSString *type = [[link attributeForName:#"type"] stringValue];
if ([rel compare:#"alternate"] == NSOrderedSame &&
[type compare:#"text/html"] == NSOrderedSame) {
articleUrl = [[link attributeForName:#"href"] stringValue];
}
}
NSString *articleDateString = [item valueForChild:#"updated"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC3339];
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate] autorelease];
[entries addObject:entry];
}
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:#"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
} else if ([rootElement.name compare:#"feed"] == NSOrderedSame) {
[self parseAtom:rootElement entries:entries];
} else {
NSLog(#"Unsupported root element: %#", rootElement.name);
}
}
- (void)requestFinished:(ASIHTTPRequest *)request {
[_queue addOperationWithBlock:^{
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
options:0 error:&error];
if (doc == nil) {
NSLog(#"Failed to parse %#", request.url);
} else {
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:entry atIndex:insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
}
}];
}
}];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
NSLog(#"Error: %#", error);
}
/*
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
*/
/*
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
*/
/*
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
*/
/*
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
}
*/
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
#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 [_allEntries count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
cell.textLabel.text = entry.articleTitle;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", articleDateString, entry.blogTitle];
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the row from the data source.
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
*/
/*
// 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;
}
*/
#pragma mark -
#pragma mark Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (_webViewController == nil) {
self.webViewController = [[[WebViewController alloc] initWithNibName:#"WebViewController" bundle:[NSBundle mainBundle]] autorelease];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
_webViewController.entry = entry;
[self.navigationController pushViewController:_webViewController animated:YES];
}
#pragma mark -
#pragma mark Memory management
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Relinquish ownership any cached data, images, etc that aren't in use.
self.webViewController = nil;
}
- (void)viewDidUnload {
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
// For example: self.myOutlet = nil;
}
- (void)dealloc {
[_allEntries release];
_allEntries = nil;
[_queue release];
_queue = nil;
[_feeds release];
_feeds = nil;
[_webViewController release];
_webViewController = nil;
[super dealloc];
}
The issue is that you keep inserting object to _allEntries without ever reseting it. You will want to empty it out at some point, either when the user pulls to refresh or when the new data comes in before you add any new objects to it.
[_allEntries removeAllObjects];
Try putting it at the start of bindDatas.

iOS XMPP received message in conversation screen

I am working on XMPP based project. I am able to send message and it displays in conversation screen but when I receive message it only show in alertview not able to see in conversation screen.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(messageReceived:) name:MessageRecivedNotif object:nil];
appdelegate=(AppDelegate*)[[UIApplication sharedApplication] delegate];
[self getAllMessagesArrayWithOppositeUser:_jid];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(keyboardWasShown:)
name:UIKeyboardDidShowNotification
object:nil];
}
#pragma mark table delegate and datasource methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return data.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tblobj dequeueReusableCellWithIdentifier:#"cell"];
UILabel *lbl;
if (cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
if (chatLblRight == 1)
{
lbl = [[UILabel alloc]initWithFrame:CGRectMake(200, 10, 150, 44)];
[lbl setTextColor:[UIColor redColor]];
[cell.contentView addSubview:lbl];
}
}
if (chatLblRight == 1)
{
lbl.text = [[data objectAtIndex:indexPath.row]valueForKey:#"text"];
chatLblRight = 0;
lbl = [[UILabel alloc]initWithFrame:CGRectMake(200, 10, 150, 44)];
[lbl setTextColor:[UIColor redColor]];
[cell.contentView addSubview:lbl];
return cell;
}
else
{
cell.textLabel.text=[[data objectAtIndex:indexPath.row]valueForKey:#"text"];
return cell;
}
}
-(void)messageReceived:(NSNotification*)notif
{
XMPPMessage *message=(XMPPMessage*)notif.object;
NSString *body = [[message elementForName:#"body"] stringValue];
NSMutableDictionary *dic_recive = [[NSMutableDictionary alloc]init];
[dic_recive setObject:body forKey:#"text"];
[data addObject:dic_recive];
chatLblRight = 1;
[tblobj reloadData];
}
-(IBAction)btnsend:(id)sender
{
[txtmsg resignFirstResponder];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.2];
[msgview setFrame:CGRectMake(0, self.view.bounds.size.height-53, self.view.bounds.size.width, 53)];
[UIView commitAnimations];
[((AppDelegate*)[[UIApplication sharedApplication]delegate]) sendMessage:txtmsg.text toUserWithJid:_jid];
NSMutableDictionary *dic_send = [[NSMutableDictionary alloc]init];
[dic_send setObject:txtmsg.text forKey:#"text"];
[data addObject:dic_send];
[tblobj reloadData];
txtmsg.text=#"";
}
-(NSMutableArray *)getAllMessagesArrayWithOppositeUser:(XMPPJID *)xmppUser
{
XMPPMessageArchivingCoreDataStorage *storage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
NSManagedObjectContext *moc = [storage mainThreadManagedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:#"XMPPMessageArchiving_Message_CoreDataObject"
inManagedObjectContext:moc];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entityDescription];
NSError *error;
NSArray *messages = [moc executeFetchRequest:request error:&error];
data=[[NSMutableArray alloc] init];
#autoreleasepool {
for (XMPPMessageArchiving_Message_CoreDataObject *message in messages) {
if ([message.bareJid isEqual:xmppUser])
{
NSMutableDictionary *dict=[[NSMutableDictionary alloc] init];
[dict setObject:message.body forKey:#"text"];
[dict setObject:message.timestamp forKey:#"date"];
if ([message isOutgoing]) {
[dict setObject:#"1" forKey:#"type"];
[dict setObject:[[message.bareJidStr componentsSeparatedByString:#"#"] firstObject] forKey:#"username"];
[dict setObject:[UIColor greenColor] forKey:#"color"];
}
else{
[dict setObject:#"2" forKey:#"type"];
[dict setObject:[[message.bareJidStr componentsSeparatedByString:#"#"] firstObject] forKey:#"username"];
// [dict setObject:userName forKey:#"username"];
[dict setObject:[UIColor blueColor] forKey:#"color"];
}
[data addObject:dict];
}
}
}
return data;
}
Where is my mistake ?
EDIT
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
DDLogVerbose(#"%#: %#", THIS_FILE, THIS_METHOD);
if ([message isChatMessageWithBody])
{
XMPPMessageArchivingCoreDataStorage *xmppMessageStorage = [XMPPMessageArchivingCoreDataStorage sharedInstance];
XMPPMessageArchiving *xmppMessageArchiving = [[XMPPMessageArchiving alloc] initWithMessageArchivingStorage:xmppMessageStorage];
[xmppMessageArchiving activate:xmppStream];
[xmppMessageArchiving addDelegate:self delegateQueue:dispatch_get_main_queue()];
XMPPUserCoreDataStorageObject *user = [xmppRosterStorage userForJID:[message from]
xmppStream:xmppStream
managedObjectContext:[self managedObjectContext_roster]];
[[NSNotificationCenter defaultCenter] postNotificationName:MessageRecivedNotif object:message];
NSString *body = [[message elementForName:#"body"] stringValue];
NSString *displayName = [user displayName];
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alertView show];
}
else
{
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = #"Ok";
localNotification.alertBody = [NSString stringWithFormat:#"From: %#\n\n%#",displayName,body];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
}
you need to set your logic in uitableviewcellforrowatindexpath method like this.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tblobj dequeueReusableCellWithIdentifier:#"cell"];
UILabel *lbl;
if (cell==nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
if([[[data objectAtIndex:indexPath.row]valueForKey:#"type"] isEqualToString:#"2"])
//if (chatLblRight == 1)
{
lbl = [[UILabel alloc]initWithFrame:CGRectMake(200, 10, 150, 44)];
[lbl setTextColor:[UIColor redColor]];
[cell.contentView addSubview:lbl];
}
}
if([[[data objectAtIndex:indexPath.row]valueForKey:#"type"] isEqualToString:#"2"])
//if([[[data objectAtIndex:indexPath.row]valueForKey:#"type"] isEqualToString:#"1"])
//if (chatLblRight == 1)
{
lbl.text = [[data objectAtIndex:indexPath.row]valueForKey:#"text"];
chatLblRight = 0;
lbl = [[UILabel alloc]initWithFrame:CGRectMake(200, 10, 150, 44)];
[lbl setTextColor:[UIColor redColor]];
[cell.contentView addSubview:lbl];
return cell;
}
else
{
cell.textLabel.text=[[data objectAtIndex:indexPath.row]valueForKey:#"text"];
return cell;
}
}
please check this code once.
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage*)message
{
//in this the (XMPPMessage*)message parameter is xml data
//parse you xml and create dictionary For eg : sampledict
}
Normally when you are getting reply from XMPP it comes like XML data. That you have to parse and use for your operations.
And in your code here
if ([[UIApplication sharedApplication] applicationState] == UIApplicationStateActive)
{
// UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:displayName
message:body
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
// [alertView show];
}
else
{
// We are not active, so use a local notification instead
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.alertAction = #"Ok";
localNotification.alertBody = [NSString stringWithFormat:#"From: %#\n\n%#",displayName,body];
[[UIApplication sharedApplication] presentLocalNotificationNow:localNotification];
}
You have used alertview. So you have to hide your alertview so that you don't get alerts. Instead manage your observer method to get data and use it
-(void)messageReceived:(NSNotification*)notif
{
XMPPMessage *message=(XMPPMessage*)notif.object;
NSString *body = [[message elementForName:#"body"] stringValue];
NSMutableDictionary *dic_recive = [[NSMutableDictionary alloc]init];
[dic_recive setObject:body forKey:#"text"];
[data addObject:dic_recive];
chatLblRight = 1;
[tblobj reloadData];
}
I think this will help you..
Please go to xmpp custom class and post a notification like this
- (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
//parse you xml and create dictionary For eg : sampledict
NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
[notificationCenter postNotificationName:#"updateValue" object:nil userInfo:sampledict];
}
and receive notification from your class like
using notification like
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(receiveUpdatedValues:)
name:#"updateValue"
object:nil];
-(void)receiveUpdatedValues : (NSNotification *)notification
{
NSDictionary *dictinfo=notification.userInfo;
// here use your info dict to get your message
}

Implement Pull to Refresh for RSS Feed [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I have an RSS feed in my app and I'm trying to figure out how to implement pull to refresh. Here is my code:
#import "ActionAlertsViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#import "DTCustomColoredAccessory.h"
#import "SVProgressHUD.h"
#implementation ActionAlertsViewController
{
UIActivityIndicatorView *loadingIndicator;
}
#synthesize webViewController;
- (void)viewDidLoad
{
UIImageView *background = [[UIImageView alloc]init];
background.image = [UIImage imageNamed:#"plain_app-background.png"];
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
[self.tableView setBackgroundView:background];
self.title = #"Action Alerts";
[[SVProgressHUD appearance]setHudBackgroundColor:[UIColor blackColor]];
[[SVProgressHUD appearance]setHudForegroundColor:[UIColor whiteColor]];
[SVProgressHUD showWithStatus:#"Loading"];
}
- (void)viewDidDisappear:(BOOL)animated
{
[SVProgressHUD dismiss];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 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];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// return 0;
NSLog(#"channel items %d", [[channel items]count]);
return [[channel items]count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 50;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return nil;
UIImageView *image = [[UIImageView alloc]init];
image.image = [UIImage imageNamed:#"CellImage.png"];
UIImageView *background = [[UIImageView alloc]init];
background.image = [UIImage imageNamed:#"plain_app-background.png"];
UIImageView *highlightedCellImage = [[UIImageView alloc]init];
highlightedCellImage.image = [UIImage imageNamed:#"HighlightedCellImage"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"UITableViewCell"];
cell.textLabel.font=[UIFont systemFontOfSize:16.0];
}
RSSItem *item = [[channel items]objectAtIndex:[indexPath row]];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:#"EEE, dd MMM yyyy HH:mm:ssZ"];
NSDate *pubDate = [formatter dateFromString:[item date]];
[formatter setDateStyle:NSDateFormatterMediumStyle];
NSString *dateString = [formatter stringFromDate:pubDate];
NSLog(#"Date String: %#", dateString);
[[cell textLabel]setText:[item title]];
[[cell detailTextLabel]setText:dateString];
NSLog(#"Date: %#", [item date]);
tableView.backgroundColor = [UIColor clearColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.highlightedTextColor = [UIColor blueColor];
cell.textLabel.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:20.0];
cell.textLabel.textColor = [UIColor whiteColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.highlightedTextColor = [UIColor blueColor];
cell.detailTextLabel.font = [UIFont fontWithName:#"FranklinGothicStd-ExtraCond" size:14.0];
cell.detailTextLabel.textColor = [UIColor whiteColor];
cell.backgroundView = image;
cell.selectedBackgroundView = highlightedCellImage;
tableView.backgroundView = background;
DTCustomColoredAccessory *accessory = [DTCustomColoredAccessory accessoryWithColor:cell.textLabel.textColor];
accessory.highlightedColor = [UIColor blueColor];
cell.accessoryView =accessory;
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
NSURL *url = [NSURL URLWithString:#"http://kyfbnewsroom.com/category/public-affairs/notifications/feed/"];
// Put that URL into an NSURLRequest
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Create a connection that will exchange this request for data from the URL
connection = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];
}
- (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
{
/* We are just checking to make sure we are getting the XML
NSString *xmlCheck = [[NSString alloc]initWithData:xmlData encoding:NSUTF8StringEncoding];
NSLog(#"xmlCheck = %#", xmlCheck);*/
[SVProgressHUD dismiss];
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:xmlData];
[parser setDelegate:self];
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
// Reload the table.. for now, the table will be empty
NSMutableArray *notActionAlerts = [NSMutableArray array];
for (RSSItem *object in channel.items) {
if (!object.isActionAlert) {
[notActionAlerts addObject:object];
}
}
for (RSSItem *object in notActionAlerts) {
[channel.items removeObject:object];
}
[[self tableView]reloadData];
NSLog(#"%#\n %#\n %#\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we're done with it
connection = nil;
// Release the xmlData object, we're done with it
xmlData = nil;
[SVProgressHUD dismiss];
// Grab the description of the error object passed to us
NSString *errorString = [NSString stringWithFormat:#"Fetch failed: %#", [error localizedDescription]];
// Create and show an alert view with this error displayed
UIAlertView *av = [[UIAlertView alloc]initWithTitle:#"Error" message:errorString delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[av show];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[[webViewController webView]loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:#"about:blank"]]];
// 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];
[self.navigationController pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
// Construct 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];
webViewController.hackyURL = url;
// Set the title of the web view controller's navigation item
// [[webViewController navigationItem]setTitle:[entry title]];
}
#end
If you're using storyboard for that you have native support for pull-to-refresh.
Only change Refreshing to enabled and then you can hook up an action for this event.

Add only SOME items from XML to TableView

Using this tutorial, I made an iPhone blog app. It uses the count of the array created to setup the number of rows. I don't want to do every single item, because there are over 200 right now and growing. When I return any number for rows in section, it always crashes with the error about 0 beyond bounds of empty array. What else do I need to tweak from this tutorial to only allow the first 20 items to show in tableview?
UPDATE: I think I am making some progress. In the reqeustFinished method where it sorts the array, I edited it to make it this:
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[entries removeLastObject];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
NSLog(#"%#", entries);
[_allEntries insertObject:entry atIndex:insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
Adding the line to removeLastObject for entries, removed the first item (which is ideally the ONLY one I would want on the first day). Are there other methods that would allow me to remove a range of objects at Index?
Here is the code I have for the Table View Class and DataSources.
- (void)refresh {
self.allEntries = [NSMutableArray array];
self.queue = [[[NSOperationQueue alloc] init] autorelease];
self.feeds = [NSArray arrayWithObjects:#"addressofxmlfile",
nil];
for (NSString *feed in _feeds) {
NSURL *url = [NSURL URLWithString:feed];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:self];
[_queue addOperation:request];
}
}
- (void)viewDidLoad {
[super viewDidLoad];
self.refreshControl = [[UIRefreshControl alloc] init];
[self.refreshControl addTarget:self action:#selector(refreshInvoked:forState:) forControlEvents:UIControlEventValueChanged];
[self refresh];
}
-(void) refreshInvoked:(id)sender forState:(UIControlState)state {
// Refresh table here...
[_allEntries removeAllObjects];
[self.tableView reloadData];
[self refresh];
}
- (void)parseRss:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
NSArray *channels = [rootElement elementsForName:#"channel"];
for (GDataXMLElement *channel in channels) {
NSString *blogTitle = [channel valueForChild:#"title"];
NSArray *items = [channel elementsForName:#"item"];
for (GDataXMLElement *item in items) {
NSString *articleTitle = [item valueForChild:#"title"];
NSString *articleUrl = [item valueForChild:#"guid"];
NSString *articleDateString = [item valueForChild:#"pubdate"];
NSDate *articleDate = [NSDate dateFromInternetDateTimeString:articleDateString formatHint:DateFormatHintRFC822];
NSString *articleImage = [item valueForChild:#"description"];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *dateofarticle = [dateFormatter stringFromDate:articleDate];
NSString *days = [articleImage substringFromIndex:7];
RSSEntry *entry = [[[RSSEntry alloc] initWithBlogTitle:blogTitle
articleTitle:articleTitle
articleUrl:articleUrl
articleDate:articleDate
articleImage:articleImage
date:thedate] autorelease];
[entries addObject:entry];
}
}
}
- (void)parseFeed:(GDataXMLElement *)rootElement entries:(NSMutableArray *)entries {
if ([rootElement.name compare:#"rss"] == NSOrderedSame) {
[self parseRss:rootElement entries:entries];
}else {
NSLog(#"Unsupported root element: %#", rootElement.name);
}
}
- (void)requestFinished:(ASIHTTPRequest *)request {
[_queue addOperationWithBlock:^{
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:[request responseData]
options:0 error:&error];
if (doc == nil) {
NSLog(#"Failed to parse %#", request.url);
} else {
NSMutableArray *entries = [NSMutableArray array];
[self parseFeed:doc.rootElement entries:entries];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
for (RSSEntry *entry in entries) {
int insertIdx = [_allEntries indexForInsertingObject:entry sortedUsingBlock:^(id a, id b) {
RSSEntry *entry1 = (RSSEntry *) a;
RSSEntry *entry2 = (RSSEntry *) b;
return [entry1.articleDate compare:entry2.articleDate];
}];
[_allEntries insertObject:entry atIndex:insertIdx];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:insertIdx inSection:0]]
withRowAnimation:UITableViewRowAnimationRight];
}
}];
}
}];
[self.refreshControl endRefreshing];
}
- (void)requestFailed:(ASIHTTPRequest *)request {
NSError *error = [request error];
NSLog(#"Error: %#", error);
[self refresh];
}
#pragma mark -
#pragma mark Table view data source
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// [tableView setBackgroundColor:[UIColor redColor]];
return 1;
}
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_allEntries count];
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
RSSEntry *entry = [_allEntries objectAtIndex:indexPath.row];
CALayer * l = [cell.imageView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:11];
[l setBorderWidth:2.0];
[l setBorderColor:[[UIColor blackColor] CGColor]];
NSDateFormatter * dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
NSString *articleDateString = [dateFormatter stringFromDate:entry.articleDate];
UIFont *cellFont = [UIFont fontWithName:#"Papyrus" size:19];
UIFont *cellFont2 = [UIFont fontWithName:#"Papyrus" size:17];
// cell.imageView.image = [UIImage imageNamed:#"icon#2x.png"];
cell.textLabel.text = entry.date;
cell.detailTextLabel.text = entry.articleTitle;
cell.detailTextLabel.textColor = [UIColor blackColor];
cell.textLabel.font = cellFont;
cell.detailTextLabel.font = cellFont2;
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 73.4;
}
You are assigning allEntries to new Array in the Refresh method here:
- (void)refresh {
self.allEntries = [NSMutableArray array];
The tutorial only does this in the ViewDidLoad Method. Not sure if this is a problem as i don't know exactly when/how refresh is called.
Found this answer that shows how to hide cells/rows here.

Resources