WCF call nested in a WCF call - ios

I have a backend made in C#, where I am making WCF calls to from iOS. It works pretty good, but I am stuck in a problem
Code:
#import "ListTableViewController.h"
#import "ListServiceSvc.h"
#import "LoginViewController.h"
#interface ListTableViewController (){
NSMutableArray *productsFromWebServer;
NSMutableDictionary *prodForList;
}
#property (nonatomic, retain) NSMutableArray *shoppingList;
#property (nonatomic, retain) NSMutableArray *productList;
#end
#implementation ListTableViewController
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
Boolean b = [standardUserDefaults boolForKey:#"HasTokenKey"];
if (!b)
{
[self showLoginViewController];
}
[self loadListsFromRemoteServer];
[self.tableView reloadData];
//self.uname.text = [standardUserDefaults objectForKey:#"username"];
}
- (void) showLoginViewController {
LoginViewController* loginController = (LoginViewController*) [ApplicationDelegate.storyBoard instantiateViewControllerWithIdentifier:#"LoginViewController"];
[self presentViewController:loginController animated:YES completion:nil];
}
- (void)userDidLeave
{
NSUserDefaults *standardUserDefaults = [NSUserDefaults standardUserDefaults];
[standardUserDefaults setBool:NO forKey:#"HasTokenKey"];
// Show the Login screen.
[self showLoginViewController];
}
- (IBAction)exitAction
{
[self userDidLeave];
}
- (void)viewDidLoad
{
_shoppingList = [NSMutableArray array];
_productList = [NSMutableArray array];
//[self loadListsFromRemoteServer];
[super viewDidLoad];
}
-(void) loadListsFromRemoteServer
{
NSString *uname = [[NSUserDefaults standardUserDefaults] objectForKey:#"username"];
NemListBinding *binding = [[ListServiceSvc NemListBinding]initWithAddress:#"http://balder/dm76_gr5/WCF.ListService.svc/custom?singleWsdl"];
binding.logXMLInOut=YES;
ListServiceSvc_GetShoppingListsWithUname *parms = [[ListServiceSvc_GetShoppingListsWithUname alloc]init];
parms.uname = uname;
[binding GetShoppingListsWithUnameAsyncUsingParameters:parms delegate:self];
}
-(void) loadItemsInList:(NSNumber*)slistId
{
NemListBinding *binding = [[ListServiceSvc NemListBinding]initWithAddress:#"http://balder/dm76_gr5/WCF.ListService.svc/custom?singleWsdl"];
binding.logXMLInOut=YES;
ListServiceSvc_GetProductsWithListId *parms = [[ListServiceSvc_GetProductsWithListId alloc]init];
parms.listId = slistId;
[binding GetProductsWithListIdAsyncUsingParameters:parms delegate:self];
}
- (void) operation:(NemListBindingOperation *)operation completedWithResponse:(NemListBindingResponse *)response
{
NSArray *responseHeaders = response.headers;
NSArray *responseBodyParts = response.bodyParts;
[NSThread sleepForTimeInterval:1.0];
NSMutableArray *shoppingListFromWebserver = [[NSMutableArray alloc] init];
productsFromWebServer = [[NSMutableArray alloc]init];
prodForList = [[NSMutableDictionary alloc]init];
// step 1 fill in the blanks.
for(id header in responseHeaders) {
// here do what you want with the headers, if there's anything of value in them
}
for (id mine in responseBodyParts)
{
if ([mine isKindOfClass:[ListServiceSvc_GetShoppingListsWithUnameResponse class]])
{
for (id slist in [[mine GetShoppingListsWithUnameResult] ShoppingList])
{
[shoppingListFromWebserver addObject:slist];
[self loadItemsInList:[slist ShoppingListId]];
//NSLog(#"new list :: RESPONSE FROM SERVER :: nList %#", [slist ShoppingListName]);
}
}
if ([mine isKindOfClass:[ListServiceSvc_GetProductsWithListIdResponse class]])
{
for (id products in [[mine GetProductsWithListIdResult] Product])
{
[prodForList setObject:[products ProductName] forKey:[products ShoppingListId]];
NSLog(#"new product :: RESPONSE FROM SERVER :: nList %#", [products ProductName]);
}
}
}
[self performSelectorOnMainThread:#selector(updateNewView:) withObject:shoppingListFromWebserver waitUntilDone:NO];
}
-(void) updateNewView:(NSMutableArray*) result
{
_shoppingList = result;
NSLog( #"new list - number of news :: %u", [_shoppingList count]);
[self.tableView reloadData];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1; // the number of different sections in your table view
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [_shoppingList count]; // the number of data in your shopping list
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ListCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
//cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
// Configure the cell...
id shopList = [_shoppingList objectAtIndex:indexPath.row];
cell.textLabel.text = [shopList ShoppingListName];
NSNumber *sid = [shopList ShoppingListId];
//[self loadItemsInList:sid];
NSNumber *prodcount = [prodForList objectForKey:sid];
NSString* pcTostring = [NSString stringWithFormat:#"%#", prodcount];
cell.detailTextLabel.text = pcTostring;
return cell;
The log actually tells me that I am getting some products for the last List it gets. Problem is that all cell.detailText.text fields are null, until the last reload, then all cells disappear.
I am pretty sure I'm doing it wrong, but I cant get my head around hot to get the products for the selected list, when I need to get the ShoppingListId from the -(void) loadListsFromRemoteServer call in order to do the -(void) loadItemsInList:(NSNumber*)slistId
WCF connection was made with the help of wsdl2obj

Related

How can I add default entries into my dictionary so that it is not empty on first run

I need some help trying to insert a couple of default entries in bandsDictionary so that it is not empty before user adds new entries.
// TableViewController.h
#import <UIKit/UIKit.h>
#class WBABand, WBABandDetailsViewController;
#interface WBABandsListTableViewController : UITableViewController
#property (nonatomic, strong) NSMutableDictionary *bandsDictionary;
#property (nonatomic, strong) NSMutableArray *firstLettersArray;
#property (nonatomic, strong) WBABandDetailsViewController *bandInfoViewController;
//NSMutableDictionary *tempDictionary;
#property (nonatomic, retain) NSMutableDictionary *tempDictionary;
-(void)addNewBand:(WBABand*)bandObject;
-(void)saveBandsDictionary;
-(void)loadBandsDictionary;
-(void)deleteBandAtIndexPath:(NSIndexPath*)indexPath;
-(void)updateBandObject:(WBABand*)bandObject atIndexPath:(NSIndexPath*)indexPath;
-(IBAction)addBandTouched:(id)sender;
#end
//TableViewController.m
#import "WBABandsListTableViewController.h"
#import "WBABand.h"
#import "WBABandDetailsViewController.h"
static NSString *bandsDictionarytKey = #"BABandsDictionarytKey";
#interface WBABandsListTableViewController ()
#end
#implementation WBABandsListTableViewController
-(id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
[self loadBandsDictionary];
self.navigationItem.rightBarButtonItem = self.editButtonItem;
self.clearsSelectionOnViewWillAppear = NO;
}
-(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 self.bandsDictionary.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSString *firstLetter = [self.firstLettersArray objectAtIndex:section];
NSMutableArray *bandsForLetter = [self.bandsDictionary objectForKey:firstLetter];
return bandsForLetter.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSString *firstLetter = [self.firstLettersArray objectAtIndex:indexPath.section];
NSMutableArray *bandsForLetter = [self.bandsDictionary objectForKey:firstLetter];
WBABand *bandObject = [bandsForLetter objectAtIndex:indexPath.row];
// Configure the cell...
cell.textLabel.text = bandObject.name;
return cell;
}
- (void)addNewBand:(WBABand*)bandObject
{
NSString *bandNameFirstLetter = [bandObject.name substringToIndex:1];
NSMutableArray *bandsForLetter = [self.bandsDictionary objectForKey:bandNameFirstLetter];
if(!bandsForLetter)
bandsForLetter = [NSMutableArray array];
[bandsForLetter addObject:bandObject];
[bandsForLetter sortUsingSelector:#selector(compare:)];
[self.bandsDictionary setObject:bandsForLetter forKey:bandNameFirstLetter];
if(![self.firstLettersArray containsObject:bandNameFirstLetter])
{
[self.firstLettersArray addObject:bandNameFirstLetter];
[self.firstLettersArray sortUsingSelector:#selector(compare:)];
}
[self saveBandsDictionary];
}
- (void)saveBandsDictionary
{
NSData *bandsDictionaryData = [NSKeyedArchiver archivedDataWithRootObject:self.bandsDictionary];
[[NSUserDefaults standardUserDefaults] setObject:bandsDictionaryData forKey:bandsDictionarytKey];
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (void)loadBandsDictionary
{
NSData *bandsDictionaryData = [[NSUserDefaults standardUserDefaults] objectForKey:bandsDictionarytKey];
if(bandsDictionaryData)
{
self.bandsDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:bandsDictionaryData];
self.firstLettersArray = [NSMutableArray arrayWithArray:self.bandsDictionary.allKeys];
[self.firstLettersArray sortUsingSelector:#selector(compare:)];
}
else
{
self.bandsDictionary = [NSMutableDictionary dictionary];
self.firstLettersArray = [NSMutableArray array];
}
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if(self.bandInfoViewController)
{
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
if(self.bandInfoViewController.saveBand)
{
if(selectedIndexPath)
{
[self updateBandObject:self.bandInfoViewController.bandObject atIndexPath:selectedIndexPath];
[self.tableView deselectRowAtIndexPath:selectedIndexPath animated:YES];
}
else
[self addNewBand:self.bandInfoViewController.bandObject];
[self.tableView reloadData];
}
else if (selectedIndexPath)
{
[self deleteBandAtIndexPath:selectedIndexPath];
}
self.bandInfoViewController = nil;
}
}
- (IBAction)addBandTouched:(id)sender
{
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
self.bandInfoViewController = (WBABandDetailsViewController *)[sb instantiateViewControllerWithIdentifier:#"bandDetails"];
[self presentViewController:self.bandInfoViewController animated:YES completion:nil];
}
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.firstLettersArray objectAtIndex:section];
}
- (NSArray*)sectionIndexTitlesForTableView:(UITableView *)tableView
{
return self.firstLettersArray;
}
- (int)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [self.firstLettersArray indexOfObject:title];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[self deleteBandAtIndexPath:indexPath];
}
}
- (void)deleteBandAtIndexPath:(NSIndexPath*)indexPath
{
NSString *sectionHeader = [self.firstLettersArray objectAtIndex:indexPath.section];
NSMutableArray *bandsForLetter = [self.bandsDictionary objectForKey:sectionHeader];
[bandsForLetter removeObjectAtIndex:indexPath.row];
if(bandsForLetter.count == 0)
{
[self.firstLettersArray removeObject:sectionHeader];
[self.bandsDictionary removeObjectForKey:sectionHeader];
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationFade];
}
else
{
[self.bandsDictionary setObject:bandsForLetter forKey:sectionHeader];
[self.tableView deleteRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
[self saveBandsDictionary];
}
- (void)updateBandObject:(WBABand*)bandObject atIndexPath:(NSIndexPath*)indexPath
{
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
NSString *sectionHeader = [self.firstLettersArray objectAtIndex:selectedIndexPath.section];
NSMutableArray *bandsForSection = [self.bandsDictionary objectForKey:sectionHeader];
[bandsForSection removeObjectAtIndex:indexPath.row];
[bandsForSection addObject:bandObject];
[bandsForSection sortUsingSelector:#selector(compare:)];
[self.bandsDictionary setObject:bandsForSection forKey:sectionHeader];
[self saveBandsDictionary];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *selectedIndexPath = [self.tableView indexPathForSelectedRow];
NSString *sectionHeader = [self.firstLettersArray objectAtIndex:selectedIndexPath.section];
NSMutableArray *bandsForSection = [self.bandsDictionary objectForKey:sectionHeader];
WBABand *bandObject = [bandsForSection objectAtIndex:selectedIndexPath.row];
self.bandInfoViewController = segue.destinationViewController;
self.bandInfoViewController.bandObject = bandObject;
self.bandInfoViewController.saveBand = YES;
}
#end
You can just add some band objects in the else clause of loadBandsDictionary and then save your user defaults. You haven't provided your WBABand class, so I don't know all of the properties, but it would be something like this -
- (void)loadBandsDictionary
{
NSData *bandsDictionaryData = [[NSUserDefaults standardUserDefaults] objectForKey:bandsDictionarytKey];
if(bandsDictionaryData)
{
self.bandsDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:bandsDictionaryData];
self.firstLettersArray = [NSMutableArray arrayWithArray:self.bandsDictionary.allKeys];
[self.firstLettersArray sortUsingSelector:#selector(compare:)];
}
else
{
self.bandsDictionary = [NSMutableDictionary dictionary];
self.firstLettersArray = [NSMutableArray array];
WBABand *sampleBand=[[WBABand alloc]init];
sampleBand.name=#"The Smashing Beatles";
//Set other band properties;
[self addNewBand:sampleBand];
WBABand *secondSampleBand=[[WBABand alloc]init]
secondSampleBand.name=#"Nine Inch Screws";
[self addNewBand:secondSampleBand];
}
}

self.objects is empty in PFQueryTableViewController

I am trying to display data in different sections using PFQueryTableViewController. The code suggested in https://parse.com/questions/using-pfquerytableviewcontroller-for-uitableview-sections seemed to work, but I couldn't get the data to load on self.objects. Here is my code:
#import "AKAdminViewStudentsViewController.h"
#interface AKAdminViewStudentsViewController ()
#property (strong, nonatomic) NSMutableDictionary *sections;
#property (strong, nonatomic) NSMutableDictionary *sectionToClassMap;
#end
#implementation AKAdminViewStudentsViewController
#synthesize sections = _sections;
#synthesize sectionToClassMap = _sectionToClassMap;
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
self.parseClassName = #"Students";
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.tableView reloadData];
NSLog(#"sections found: %#", self.sections); // returns null
NSLog(#"sectionToClassMap: %#", self.sectionToClassMap); // returns null
NSLog(#"objects in table: %#", self.objects); // this found to be empty
}
...
#pragma mark - Tableview methods
- (PFQuery *)queryForTable
{
PFQuery *queryStudents = [PFQuery queryWithClassName:#"Students"];
[queryStudents whereKey:#"student_admin" equalTo:[PFUser currentUser]];
if ([self.objects count]==0) {
queryStudents.cachePolicy = kPFCachePolicyCacheThenNetwork;
}
[queryStudents orderByAscending:#"class_name"];
return queryStudents;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return self.sections.allKeys.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *className = [self classForSection:section];
NSArray *rowIndicesInSection = [self.sections objectForKey:className];
return rowIndicesInSection.count;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *className = [self classForSection:section];
return className;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath object:(PFObject *)object
{
static NSString *CellIdentifier = #"Students";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell==nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure cell
cell.textLabel.text = [NSString stringWithFormat:#"%#", object[#"full_name"]];
NSDateFormatter *formatDate = [[NSDateFormatter alloc] init];
[formatDate setDateStyle:NSDateFormatterShortStyle];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", [formatDate stringFromDate:object[#"createdAt"]]];
return cell;
}
#pragma mark - Helper methods
- (void)objectsDidLoad:(NSError *)error
{
[super objectsDidLoad:error];
// Clear data before loading
[self.sections removeAllObjects];
[self.sectionToClassMap removeAllObjects];
NSInteger section = 0;
NSInteger rowIndex = 0;
for (PFObject *object in self.objects) {
NSString *className = [object objectForKey:#"class_name"];
NSMutableArray *objectsInSection = [self.sections objectForKey:className];
if (!objectsInSection) {
objectsInSection = [NSMutableArray array];
// Create new section for new class found
[self.sectionToClassMap setObject:className forKey:[NSNumber numberWithInt:section++]];
}
[objectsInSection addObject:[NSNumber numberWithInt:rowIndex++]];
[self.sections setObject:objectsInSection forKey:className];
}
}
- (PFObject *)objectAtIndexPath:(NSIndexPath *)indexPath
{
NSString *className = [self classForSection:indexPath.section];
NSArray *rowIndicesInSection = [self.sections objectForKey:className];
NSNumber *rowIndex = [rowIndicesInSection objectAtIndex:indexPath.row];
return [self.objects objectAtIndex:[rowIndex intValue]];
}
- (NSString *)classForSection:(NSInteger)section
{
return [self.sectionToClassMap objectForKey:[NSNumber numberWithInt:section]];
}
#end
When I look at the NSLog data, self.objects is empty. I know this is the reason why data isn't displayed, and would like some advice to sort this out please! Thanks.

Updating of a Mutable Array

I have a mutable Array in a Tableview, this is populated on View did load from an SQLite database, However this database changes as it is a favourites database for products in my app.
When a user selects one of the items in the tableview (The user then goes to a detail view, with the info from the database) the user can then select to remove it from the favourites (database) when the user then presses back in the navigation bar, the item is still there, I've tried tableview reload on view did appear, and view will appear but that doesn't help,
Can anyone shed any light on this??
Many thanks,
Andrew
Here is my code:
FavTableViewController.h:
#interface FavTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *Table;
}
#property (nonatomic, strong) UITableView *Table;
#property (nonatomic, strong) NSArray *cats;
#property (nonatomic, strong) IBOutlet UISearchBar *searchBar;
#property (nonatomic, strong) UISearchDisplayController *searchDisplayController;
#property (nonatomic, strong) NSMutableArray *filteredListContent;
#property (nonatomic, strong) NSMutableArray *listContent;
#property (nonatomic, strong) NSArray *everything;
#property (nonatomic, copy) NSString *savedSearchTerm;
#property (nonatomic) NSInteger savedScopeButtonIndex;
#property (nonatomic) BOOL searchWasActive;
#property (nonatomic, strong) NSString *cellText;
-(void) refresh;
#end
FavTableViewController.m:
#import "FavTableViewController.h"
#import "DBFavAdapter.h"
#import "MenuData.h"
#import "DBAdapter.h"
#import "DetailViewController.h"
#import "ConsoleDetailController.h"
#import "EffectDetailViewController.h"
#import "DimmersDetailController.h"
#import "ConventionalController.h"
#import "ProDetailViewController.h"
#implementation FavTableViewController
#synthesize filteredListContent, savedSearchTerm, savedScopeButtonIndex, searchWasActive, searchBar, searchDisplayController, listContent, everything, cellText, cats, Table;
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
listContent = [[NSMutableArray alloc] init];
}
return self;
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
NSLog(#"Did Load");
[super viewDidLoad];
everything = [[DBFavAdapter allProducts] mutableCopy];
for (NSDictionary *dict in everything) {
[listContent addObject: [dict objectForKey:#"Title"]];
}
// create a filtered list that will contain products for the search results table.
self.filteredListContent = [NSMutableArray arrayWithCapacity:[self.listContent count]];
// restore search settings if they were saved in didReceiveMemoryWarning.
if (self.savedSearchTerm)
{
[self.searchDisplayController setActive:self.searchWasActive];
[self.searchDisplayController.searchBar setSelectedScopeButtonIndex:self.savedScopeButtonIndex];
[self.searchDisplayController.searchBar setText:savedSearchTerm];
self.savedSearchTerm = nil;
}
// [self.tableView reloadData];
self.Table.scrollEnabled = YES;
self.navigationItem.title = #"Favourites";
// cats = [DBFavAdapter allCategories];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.filteredListContent = nil;
NSLog(#"Unload");
}
- (void)viewWillAppear:(BOOL)animated {
NSLog(#"View will Appear");
[Table reloadData];
NSLog(#"Everything: %#",everything);
NSLog(#"list Content: %#",listContent);
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
NSLog(#"View did Appear");
[super viewDidAppear:animated];
NSLog(#"list Content appeared: %#",listContent);
[Table reloadData];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
NSLog(#"Did dissapear");
// save the state of the search UI so that it can be restored if the view is re-created
self.searchWasActive = [self.searchDisplayController isActive];
self.savedSearchTerm = [self.searchDisplayController.searchBar text];
self.savedScopeButtonIndex = [self.searchDisplayController.searchBar selectedScopeButtonIndex];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(tableView == self.searchDisplayController.searchResultsTableView){
return [self.filteredListContent count];
}
else {
return [self.listContent count];
}
NSLog(#"Rows %i",[self.listContent count]);
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// NSDictionary *dictionary = [self.tableDataSource objectAtIndex:indexPath.row];
if (tableView == searchDisplayController.searchResultsTableView)
{
cellText = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
cellText = [self.listContent objectAtIndex:indexPath.row];
}
// NSString *cellText = [self.listContent objectAtIndex:indexPath.row];
UIFont *cellFont = [UIFont fontWithName:#"Heiti TC" size:17.0];
CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];
return labelSize.height + 30;
}
- (NSInteger)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = 1;
return row;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
cell.textLabel.numberOfLines = 0;
cell.textLabel.font = [UIFont fontWithName:#"Heiti TC" size:17.0];
}
// Configure the cell...
if (tableView == searchDisplayController.searchResultsTableView)
{
cell.textLabel.text = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
cell.textLabel.text = [self.listContent objectAtIndex:indexPath.row];
}
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *selectedItem;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
selectedItem = [self.filteredListContent objectAtIndex:indexPath.row];
}
else
{
selectedItem = [self.listContent objectAtIndex:indexPath.row];
}
// Is the selection a category?
// NSArray *cats = [DBAdapter allCategories];
__block BOOL cat = NO;
[cats enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([(NSString*)obj isEqualToString:selectedItem]) {
cat = YES;
*stop = YES;
}
}];
if (cat) { // the user's selection was a category
// NSLog(#"Selected item was a category");
}
else {
NSArray *mans = [DBAdapter allManufacturers];
__block BOOL man = NO;
[mans enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([(NSString*)obj isEqualToString:selectedItem]) {
man = YES;
*stop = YES;
}
}];
if (man) { // the user's selection was a manufacturer
// NSLog(#"Selected item was a manufacturer");
} else {
// the user's selection was a product
// Find selectedItem in products
__block NSDictionary *selectedRow = nil;
[self.everything enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
//everything is an array of dictionaries
if ([(NSString*)[(NSDictionary*)obj objectForKey:#"Title"] isEqualToString:selectedItem]) {
selectedRow = (NSDictionary*)obj;
*stop = YES;
}
}];
MenuData *selectionData = [MenuData menuData];
selectionData.manufacturerID = [[selectedRow objectForKey:#"Manufacturer_id"] integerValue];
selectionData.categoryID = [[selectedRow objectForKey:#"Category_id"] integerValue];
selectionData.sCategoryID = [[selectedRow objectForKey:#"SubCategory_id"] integerValue];
selectionData.ssCategoryID = [[selectedRow objectForKey:#"SuperSubCategory_id"] integerValue];
NSString *selectedTitle = [selectedRow objectForKey: #"Title"]; // You probably already have this value from your search. Here for the sake of clarity.
NSDictionary *productDetails = [DBAdapter productDetails: selectedTitle forCurrentData: selectionData];
NSArray *allKeys = [productDetails allKeys];
// NSLog(#"values: %i", [allKeys count]);
for (NSString *key in allKeys) {
id value = [productDetails objectForKey:key];
if ([value isKindOfClass:[NSString class]]) {
// NSLog(#"key: %# value: %#", key, value);
}
}
NSInteger ViewNumber = [[productDetails objectForKey:#"View"] integerValue];
switch (ViewNumber) {
case 25: {
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:[NSBundle mainBundle]];
dvController.dictionary = productDetails;
[self.navigationController pushViewController:dvController animated:YES];
}
break;
case 18: {
EffectDetailViewController *edvController = [[EffectDetailViewController alloc] initWithNibName:#"EffectDetailView" bundle:[NSBundle mainBundle]];
edvController.dictionary = productDetails;
[self.navigationController pushViewController:edvController animated:YES];
}
break;
case 17: {
ConsoleDetailController *cdvController = [[ConsoleDetailController alloc] initWithNibName:#"ConsoleDetailController" bundle:[NSBundle mainBundle]];
cdvController.dictionary = productDetails;
[self.navigationController pushViewController:cdvController animated:YES];
}
break;
case 2: {
ConsoleDetailController *cdvController = [[ConsoleDetailController alloc] initWithNibName:#"ConsoleDetailController" bundle:[NSBundle mainBundle]];
cdvController.dictionary = productDetails;
[self.navigationController pushViewController:cdvController animated:YES];
}
break;
case 3: {
DimmersDetailController *ddvController = [[DimmersDetailController alloc] initWithNibName:#"DimmersDetailController" bundle:[NSBundle mainBundle]];
ddvController.dictionary = productDetails;
[self.navigationController pushViewController:ddvController animated:YES];
}
break;
case 12: {
ConventionalController *cController = [[ConventionalController alloc] initWithNibName:#"ConventionalController" bundle:[NSBundle mainBundle]];
cController.dictionary = productDetails;
[self.navigationController pushViewController:cController animated:YES];
}
break;
case 5: {
ProDetailViewController *pController = [[ProDetailViewController alloc] initWithNibName:#"ProDetailViewController" bundle:[NSBundle mainBundle]];
pController.dictionary = productDetails;
[self.navigationController pushViewController:pController animated:YES];
}
break;
}
}
}
}
#pragma mark -
#pragma mark Content Filtering
- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope {
/*
Update the filtered array based on the search text and scope.
*/
[self.filteredListContent removeAllObjects]; // First clear the filtered array.
/*
Search the main list for products whose type matches the scope (if selected) and whose name matches searchText; add items that match to the filtered array.
*/
for (NSString *product in listContent)
{
//Edit AD - NS Range works instead of NSComparisonResult
NSRange result = [product rangeOfString:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch)];
if (result.location != NSNotFound)
{
[self.filteredListContent addObject:product];
}
/*
// NSComparisonResult result = [product compare:searchText options:(NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch) range:NSMakeRange(0, [searchText length])];
if (result == NSOrderedSame)
{
[self.filteredListContent addObject:product];
}
*/
}
}
#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
[self filterContentForSearchText:searchString scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:[self.searchDisplayController.searchBar selectedScopeButtonIndex]]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption {
[self filterContentForSearchText:[self.searchDisplayController.searchBar text] scope:
[[self.searchDisplayController.searchBar scopeButtonTitles] objectAtIndex:searchOption]];
// Return YES to cause the search result table view to be reloaded.
return YES;
}
- (void)refresh {
NSLog(#"Refresh");
if([NSThread isMainThread])
{
[self.Table reloadData];
[self.Table setNeedsLayout];
[self.Table setNeedsDisplay];
}
else
{
[self performSelectorOnMainThread:#selector(refresh) withObject:nil waitUntilDone:YES];
}
}
#end
You have 2 options.
Remove the item from the listContent as well. This can be done via a delegate method that will be called from the child view controller when you delete the item.
Move your viewDidLoad functionality where listContents is generated from the database to viewWillAppear. This will cause listContents to read the database again, after the item was deleted and you hit the back button, this will also get called when the view first opens.

How to fill a tableview with sudzc? (My property dont work)

I have a class that uses sudzc. All works fine, with NSLog I can watch the data of my web services, but when I want to use an array and then use that array in other place, the property is null. I want to fill a table view with the data of the web services, but I can't, How could do it?
This is my class
//
// RootViewController.m
// StratargetMovil
//
// Created by Giovanni Cortés on 30/03/12.
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
//
#import "RootViewController.h"
#import "Page2.h"
#interface RootViewController ()
#end
#implementation RootViewController
#synthesize myData = _myData;
#synthesize empresaID = _empresaID;
#synthesize datos = _datos;
#synthesize idUnidadNegocio = _idUnidadNegocio;
#synthesize idArray = _idArray;
-(NSString *)empresaID
{
_empresaID = #"fce";
return _empresaID;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
// Do any additional setup after loading the view from its nib.
}
return self;
}
- (void)viewDidLoad
{
// I want to fill the table view but dont work
EWSEmpresaWebServiceSvc *service = [[EWSEmpresaWebServiceSvc alloc] init];
[service ConsultarUnidadesOrganizacionalesPorEmpresa:self EmpresaId:self.empresaID];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.datos = nil;
self.myData = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
// Lo de la tabla
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.myData count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [self.myData objectAtIndex:row];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Muestra la vista 2 cuando se selecciona una fila
[[tableView cellForRowAtIndexPath:indexPath] setSelected:NO animated:YES];
self.idUnidadNegocio = [self.idArray objectAtIndex:indexPath.row];
Page2 *nextNavigator = [[Page2 alloc] init];
[[self navigationController] pushViewController:nextNavigator animated:YES];
[nextNavigator release];
}
// -------------------------------------------------
// Consultar unidades organizaciones por empresa
- (void) ConsultarUnidadesOrganizacionalesPorEmpresaHandler: (id) value {
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray*)value;
NSMutableArray *unidadOrganizacional = [[NSMutableArray alloc] init];
self.myData = [[[NSMutableArray array] init] autorelease];
for (int i = 0; i < [result count]; i++)
{
EWSUnidadNegocio *empresa = [[EWSUnidadNegocio alloc] init];
empresa = [result objectAtIndex:i];
[unidadOrganizacional addObject:[empresa Descripcion]];
}
self.myData = unidadOrganizacional;
}
-(void)onload:(id)value
{
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray*)value;
NSMutableArray *unidadOrganizacional = [[NSMutableArray alloc] init];
self.myData = [[[NSMutableArray array] init] autorelease];
for (int i = 0; i < [result count]; i++)
{
EWSUnidadNegocio *empresa = [[EWSUnidadNegocio alloc] init];
empresa = [result objectAtIndex:i];
NSLog(#"%ld -- %#", [empresa Id], [empresa Descripcion]); // With this I can watch the data in the console
[unidadOrganizacional addObject:[empresa Descripcion]];
}
self.myData = unidadOrganizacional; // self.myData in another place is null
}
}
#end
My data is
#property (nonatomic, retain) NSMutableArray *myData;
Thanks
Firstly, this is doing nothing for you:
self.myData = [[[NSMutableArray array] init] autorelease];
...
self.myData = unidadOrganizacional;
You are assigning myData then immediately reassigning it.
Skip the first initialization and just do this:
self.myData = [unidadOrganizacional mutableCopy];
I suspect you are losing the pointer to the unidadOrganizacional array at some point and that is why you are getting null for myData.
Personally though I would just do this initialize myData in the viewDidLoad call and then add the objects to myData directly:
- (void)viewDidLoad
{
self.myData = [[NSMutableArray alloc] init];
// I want to fill the table view but dont work
EWSEmpresaWebServiceSvc *service = [[EWSEmpresaWebServiceSvc alloc] init];
[service ConsultarUnidadesOrganizacionalesPorEmpresa:self EmpresaId:self.empresaID];
}
and then:
- (void) ConsultarUnidadesOrganizacionalesPorEmpresaHandler: (id) value {
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray*)value;
for (int i = 0; i < [result count]; i++)
{
EWSUnidadNegocio *empresa = [[EWSUnidadNegocio alloc] init];
empresa = [result objectAtIndex:i];
[self.myData addObject:[empresa Descripcion]];
}
}
-(void)onload:(id)value
{
// Handle errors
if([value isKindOfClass:[NSError class]]) {
NSLog(#"%#", value);
return;
}
// Handle faults
if([value isKindOfClass:[SoapFault class]]) {
NSLog(#"%#", value);
return;
}
// Do something with the NSMutableArray* result
NSMutableArray *result = (NSMutableArray*)value;
for (int i = 0; i < [result count]; i++)
{
EWSUnidadNegocio *empresa = [[EWSUnidadNegocio alloc] init];
empresa = [result objectAtIndex:i];
NSLog(#"%ld -- %#", [empresa Id], [empresa Descripcion]); // With this I can watch the data in the console
[self.myData addObject:[empresa Descripcion]];
}
}
You may want to clear out myData before the ConsultarUnidadesOrganizacionalesPorEmpresa call, I'm not really sure what the different between that and onload is really. It looks like they are duplicates of each other.
Good luck!
I think myData autoreleased.
You can alloc and init the myData array but not auto-/release it. (remove autorelease at the myData allocation in the
ConsultarUnidadesOrganizacionalesPorEmpresaHandler method)
Don't forget to add a dealloc method for releasing the myData (and other) properties.

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