I create a UITableViewController using storyboard, and want to reload the tableview every time it detect a device(for bonjour protocol).
However, the reload data method only calls numberofRows, but not call CellForRowatIndexPath. So I have nothing changed. The mutablearray I checked is always going correctly. NewObjects are added. But the tableview doesn't change with the array. So I am wondering if I set sth wrong here.
From the NSLog I added, I found, I could load the tableview at the beginning with
the initialized array
self.serviceArray = [[NSMutableArray alloc]initWithObjects:#"test", nil];
But in the method
- (void)addService:(NSNetService *)....
Everytime I reload, the new object can be added to the mutableArray, but the tableview doesn't change with the array. (It called the numberOfRows, and I check the array size returned is not 0, but then it doesn't call the cellOfRowAtIndex)
Here is my code
.h file
#import <UIKit/UIKit.h>
#import "Server.h"
#interface BrowserViewController : UITableViewController <ServerDelegate>
{
Server *_server;
NSMutableArray *_serviceArray;
}
#property (retain,nonatomic) NSMutableArray *serviceArray;
#property (nonatomic,retain) Server *server;
- (void)addService:(NSNetService *)service moreComing:(BOOL)more;
#end
.m file
#import "BrowserViewController.h"
#implementation BrowserViewController
#synthesize serviceArray = _serviceArray;
#synthesize server = _server;
- (void) dealloc
{
[self.serviceArray release];
[self.tableView release];
[super dealloc];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
self.title = #"Service Browser";
_serviceArray = nil;
self.serviceArray = nil;
[self.tableView setDelegate: self];
[self.tableView setDataSource:self];
//actually I set this in the storyboard already
[self.tableView reloadData];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
_serviceArray = nil;
NSLog(#"viewwilldisappear");
}
- (NSMutableArray *)serviceArray {
if(nil == _serviceArray) {
self.serviceArray = [[NSMutableArray alloc]initWithObjects:#"test", nil];
}
else
{
NSLog(#"update array");
}
return _serviceArray;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)addService:(NSNetService *)service moreComing:(BOOL)more{
[self.serviceArray addObject:service];
if (!more) {
[self.tableView reloadData];
}
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return #"Connection Choices";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.serviceArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *Cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (Cell == nil) {
Cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]autorelease];
}
NSString *text = [self.serviceArray objectAtIndex:indexPath.row];
Cell.textLabel.text = text;
return Cell;
}
#end
I checked some solution, it's either delegate setting problem, or the array is null. or cell initialized without space. Is there any way to check what's the delegate of some method ?
I also tried to create a tableview property in the .h file, linked IBOutlet, then synthesize it in the .m. But still doesn't work. Could anyone help me?
Since a lot of tutorials are based on window-based application, could someone maybe provide me some tutorial using storyboard and using reloadData ? I could check if the Outlets are wrong.
Thanks in advance.
UPDATE1
AddService method is called in the appDelegate
appDelegate.h
#import <UIKit/UIKit.h>
#import "Server.h"
#class BrowserViewController;
#interface iphoneNetworkAppDelegate : NSObject <UIApplicationDelegate,UITableViewDataSource, UITableViewDelegate, ServerDelegate>
{
Server *_server;
UIWindow *window;
IBOutlet BrowserViewController *BrowserVC;
}
#property (strong, nonatomic) UIWindow *window;
#end
appDelegate.m
#import "iphoneNetworkAppDelegate.h"
#import "BrowserViewController.h"
#implementation iphoneNetworkAppDelegate
#synthesize window;
- (void)dealloc
{
[window release];
[_server release];
_server = nil;
[BrowserVC release];
BrowserVC = nil;
[super dealloc];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSString *type = #"TestingProtocol";
_server = [[Server alloc] initWithProtocol:type];
_server.delegate = self;
NSError *error = nil;
if(![_server start:&error]) {
NSLog(#"error = %#", error);
}
BrowserVC = [BrowserViewController alloc];
if (BrowserVC == nil) {
NSLog(#"need to init");
}
BrowserVC.server = _server;
return YES;
}
#pragma mark Server Delegate Methods
- (void)serverRemoteConnectionComplete:(Server *)server {
NSLog(#"Server Started");
BrowserVC.server = server;
}
- (void)serverStopped:(Server *)server {
NSLog(#"Server stopped");
}
- (void)server:(Server *)server didNotStart:(NSDictionary *)errorDict {
NSLog(#"Server did not start %#", errorDict);
}
- (void)server:(Server *)server didAcceptData:(NSData *)data {
NSLog(#"Server did accept data %#", data);
}
- (void)server:(Server *)server lostConnection:(NSDictionary *)errorDict {
NSLog(#"Server lost connection %#", errorDict);
}
- (void)serviceAdded:(NSNetService *)service moreComing:(BOOL)more {
NSLog(#"service added in delegate");
[BrowserVC addService:service moreComing:more];
}
#pragma mark -
- (void)applicationWillTerminate:(UIApplication *)application {
[_server stop];
[_server stopBrowser];
}
If the appDelegate setting is like this, reloadData cannot be called ?
Please check this terms may help you:
self.tableView is object bind in TableView in XIB.
Included <UITableViewDelegate,UITableViewDataSource> delegates in .h file?
Properly set getter setter your object "self.tableView"
Delegate set?
a)[self.tableView setDelegate: self];
b)[self.tableView setDataSource:self];
i think No need for the following lines in view will appear
_serviceArray = nil;
self.serviceArray = nil;
And also makes sure that the function addService got called:
Related
I followed this tutorial from AppCoda and I noticed that when I create another calendar, choose it (indicated by the checkmark beside it), then hit the Back button, the events in the main UIViewController view are not refreshed. I already added this code in my ViewController.m but nothing new happened:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
if (self.tblEvents == nil) {
NSLog(#"Your TableView becomes nil");
return;
}
[self.tblEvents reloadData];
}
Any ideas? Let me know if you need more information.
Edit:
.m
#import "MainViewController.h"
#import "AppDelegate.h"
#interface MainViewController ()
#property (nonatomic, strong) AppDelegate *appDelegate;
#property (nonatomic, strong) NSArray *arrEvents;
- (void)requestAccessToEvents;
- (void)loadEvents;
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
[self performSelector:#selector(requestAccessToEvents) withObject:nil afterDelay:0.4];
[self performSelector:#selector(loadEvents) withObject:nil afterDelay:0.5];
[self.tblEvents reloadData];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.tblEvents reloadData];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"idSegueEvent"]) {
EventViewController *eventViewController = [segue destinationViewController];
eventViewController.delegate = self;
}
}
#pragma mark - UITableView Delegate and Datasource method implementation
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%lu", (unsigned long)self.arrEvents.count);
return self.arrEvents.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"idCellEvent"];
// Get each single event.
EKEvent *event = [self.arrEvents objectAtIndex:indexPath.row];
// Set its title to the cell's text label.
cell.textLabel.text = event.title;
// Get the event start date as a string value.
NSString *startDateString = [self.appDelegate.eventManager getStringFromDate:event.startDate];
// Get the event end date as a string value.
NSString *endDateString = [self.appDelegate.eventManager getStringFromDate:event.endDate];
// Add the start and end date strings to the detail text label.
cell.detailTextLabel.text = [NSString stringWithFormat:#"%# - %#", startDateString, endDateString];
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60.0;
}
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
// Keep the identifier of the event that's about to be edited.
self.appDelegate.eventManager.selectedEventIdentifier = [[self.arrEvents objectAtIndex:indexPath.row] eventIdentifier];
// Perform the segue.
[self performSegueWithIdentifier:#"idSegueEvent" sender:self];
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the selected event.
[self.appDelegate.eventManager deleteEventWithIdentifier:[[self.arrEvents objectAtIndex:indexPath.row] eventIdentifier]];
// Reload all events and the table view.
[self loadEvents];
}
}
#pragma mark - EEventViewControllerDelegate method implementation
- (void)eventWasSuccessfullySaved
{
// Reload all events.
[self loadEvents];
}
#pragma mark - IBAction method implementation
- (IBAction)showCalendars:(id)sender
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
[self performSegueWithIdentifier:#"idSegueCalendars" sender:self];
}
}
- (IBAction)createEvent:(id)sender
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
[self performSegueWithIdentifier:#"idSegueEvent" sender:self];
}
}
#pragma mark - Private method implementation
- (void)requestAccessToEvents
{
[self.appDelegate.eventManager.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (error == nil) {
// Store the returned granted value.
self.appDelegate.eventManager.eventsAccessGranted = granted;
} else {
// In case of error, just log its description to the debugger.
NSLog(#"%#", [error localizedDescription]);
}
}];
}
- (void)loadEvents
{
if (self.appDelegate.eventManager.eventsAccessGranted) {
self.arrEvents = [self.appDelegate.eventManager getEventsOfSelectedCalendar];
[self.tblEvents reloadData];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
To make UITableView work you need to set the delegate and datasource object like this..
in you ViewController.m file try to add Delegate and DataSource like this.
#interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
#end
now add these two lines in your view did load.
self.tblEvents.delegate = self;
self.tblEvents.dataSource = self;
And check the implimentation of you Data Source methods like this
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//This method should return the number of rows you want to create in your tableView
return yourArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"yourCellIdentifier"];
//Now show what you want to show in your each cell? For Example you just want to show a simple text which is stored in you array.
cell.textLabel.text = [yourArray objectAtIndex:indexPath.row];
//indexPath.row is the numeric index number of each cell. This method will automatically execute exact the same number of time you return in above method.
return cell;
}
Now When your class/View Controller is open you might have zero data in your array and after some manipulation you got some data in your array Either by Call Web-Services/Loading from local Database/ by Passing Reference of array to next ViewController and on coming back to screen you want to refresh your TableView so now calling [tblEvents reloadData] will restart the process from numberOfRowsInSection method to cellForRowAtIndexPath method
I am trying to copy the array from tableview controller to view controller. I have checked the code multiple times and it seems to be okay.
//Delegate class
#import <UIKit/UIKit.h>
#protocol Category <NSObject>
#required
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory;
#end
#interface Categories : UIViewController <UITableViewDelegate,UITableViewDataSource>
#property (nonatomic) id<Category> delegate;
#property (nonatomic,strong) NSArray *sports;
#property (strong, nonatomic) IBOutlet UITableView *tableview;
#property (nonatomic,strong) NSMutableArray *selectedIndexes;
#end
//Delegate methods
#import "Categories.h"
#interface Categories ()
{
NSMutableArray *array ;
}
#end
#implementation Categories
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_sports= [[NSArray alloc] initWithObjects: #"Baseball", #"Soccer", #"Hockey",
#"Other",nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
return _sports.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
array = [[NSMutableArray alloc]init];
// Configure the cell...
cell.textLabel.text=[self.sports objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = selectedCell.textLabel.text;
if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryNone)
{ [tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryCheckmark;
[array addObject:cellText];
}else if([tableView cellForRowAtIndexPath:indexPath].accessoryType==UITableViewCellAccessoryCheckmark){
[tableView cellForRowAtIndexPath:indexPath].accessoryType=UITableViewCellAccessoryNone;
[array removeObject:cellText];
}
}
- (IBAction)doneButton:(id)sender {
[self.delegate delegateMethodForCategory:array];
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
#import <UIKit/UIKit.h>
#import "Categories.h"
#interface ActivityCreator : UIViewController <UIPopoverPresentationControllerDelegate, Category>
#property (nonatomic) Categories *requestClass;
#property (nonatomic,strong) NSMutableArray *arrayOfSports;
#end
//This class implements delegate
import "ActivityCreator.h"
#interface ActivityCreator ()
#end
#implementation ActivityCreator
- (void)viewDidLoad {
[super viewDidLoad];
[self settingUp];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(UIModalPresentationStyle)adaptivePresentationStyleForPresentationController:(UIPresentationController *)controller{
return UIModalPresentationNone;
}
-(void)settingUp{
_requestClass = [[Categories alloc]init];
self.requestClass.delegate = self;
}
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"hubabuba"]){
Categories *pop = (Categories *)segue.destinationViewController;
pop.modalPresentationStyle = UIModalPresentationPopover;
pop.popoverPresentationController.delegate = self;
}
}
-(void) delegateMethodForCategory : (NSMutableArray *) arrayOfCategory {
_arrayOfSports = arrayOfCategory;
NSLog(#"%#",_arrayOfSports);
}
Any guidance where I am doing wrong will be of great help. Have been stuck on this for a while.
The delegate method is not being called at all.
Thanks
Set the delegate of Categories class in prepareForSegue method instead of setting in settingUp method.
Write
pop.delegate = self;
In prepareForSegue method.
I have a viewcontroller set up on my storyboard, and I have inserted a tableView inside this view controller. I want to do a [self.tableView reloadData].
This is what my viewController.m looks like. My tableView is an IBOutlet called sharedView, hence the names in the methods, but I am doing something wrong as on viewDidLoad when I call configureView, and subsequently [self.sharedView reloadData]; the data doesn't show up inside the table.
#import "DetailViewController.h"
#import "sharedUsersTable.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [[self.detailItem objectForKey:#"lock_name"] description];
activeUsers = [self.detailItem objectForKey:#"active_shared_users"];
[self.sharedView reloadData];
//NSLog(#"Info: %#", activeUsers);
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSString *)sharedView:(UITableView *)sharedView titleForHeaderInSection:(NSInteger)section {
return #"Shared with";
}
- (NSInteger)sharedView:(UITableView *)sharedView numberOfRowsInSection:(NSInteger)section
{
return activeUsers.count;
}
- (sharedUsersTable *)sharedView:(UITableView *)sharedView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"sharedUser";
sharedUsersTable *cell = [sharedView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[sharedUsersTable alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *key;
NSString *name;
NSString *email;
// NSString *permission;
key = [activeUsers objectAtIndex:indexPath.row];
name = [key objectForKey:#"shared_user_name"];
email = [key objectForKey:#"email"];
NSLog(#"Info: %#", name);
cell.textLabel.text = [NSString stringWithFormat:#"%#", name];
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", email];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
#end
You should add info about protocols that Your VC is implementing:
#interface DetailViewController () <UITableViewDataSource, UITableViewDelegate>
- (void)configureView;
#end
and then:
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [[self.detailItem objectForKey:#"lock_name"] description];
activeUsers = [self.detailItem objectForKey:#"active_shared_users"];
/* I assume that Your table view is self.sharedView though You should change the name and I assume that it is connected to VC */
self.sharedView.dataSource = self;
self.sharedView.delegate = self;
[self.sharedView reloadData];
//NSLog(#"Info: %#", activeUsers);
}
}
You can also set data source and delegate directly in storyboard - I think that You have to ctrl+drag from table view to vc. Sorry if this is not correct - I do not use IB for quite some time no - only code.
And one more thing - read this:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDataSource_Protocol/Reference/Reference.html#//apple_ref/occ/intf/UITableViewDataSource
And change method names to be exactly the same as in the protocol - If You do not It won't work.
For better undesstanding data sources and delegates try:
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/CreateConfigureTableView/CreateConfigureTableView.html
You mentioned that you are using a UIViewController and not UITableViewController. If you are using UIViewController then you will need to implement UITableViewDelegate and UITableViewDataSourceDelegate. You will also need to connect those delegates either through code or using the interface builder or Storyboard.
I have searched the internet and got absolutely no results for this. My ios app is just a simple navigation controller with a indexpath that should send the title of the row selected of a custom dynamic cell () to a uilabel. The catch is that the datasource is from mysql that is xml parsed in an nsarray (called coolarray). The error happens just before moving to the next view and is in the log as: Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[__NSDictionaryI isEqualToString:]: unrecognized selector sent to instance 0x8887670'. However, it does give the nslog result of indexPathrow:0 or 1 or whatever was selected. It must be a problem with the delivery of the array to the uilabel, but I cannot figure it out! I have left out the code for the custom cell, because that isn't likely the reason for the error and works fine (plus is dead simple). This is a followup to an earlier question of mine at UITableView refusing to go to detailViewController, but that code is no longer relevant because, as you can see below, my code has greatly changed.
ViewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import "Player.h"
#interface ViewController : UIViewController<UITableViewDelegate, UITableViewDataSource,
CLLocationManagerDelegate,NSXMLParserDelegate, UISearchBarDelegate> {
IBOutlet UISearchBar *searchBar;
CLLocationManager *locationManager;
NSMutableArray *coolarray;
float latitude;
float longitude;
}
#property(nonatomic,strong) IBOutlet UITableView * tableView;
#property (nonatomic, retain) CLLocationManager *locationManager;
#end
ViewController.m
#import "ViewController.h"
#import "LoadingViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)dealloc
{
[super dealloc];
[self.locationManager release];
if ( coolarray )
[coolarray release];
}
- (void)viewDidLoad
{
[super viewDidLoad];
coolarray = NULL;
self.locationManager = [[[CLLocationManager alloc] init] autorelease];
self.locationManager.delegate = self;
[self.locationManager startUpdatingLocation];
[[self navigationController] setNavigationBarHidden:YES];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
// Table data delegate
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
if ( coolarray != NULL ) {
return [coolarray count];
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Player *cell = [_tableView dequeueReusableCellWithIdentifier:#"Player"];
if (cell == nil)
{
cell = [[[Player alloc] initWithFrame:CGRectZero reuseIdentifier:#"Player"] autorelease];
}
NSDictionary *itemAtIndex =(NSDictionary *)[coolarray objectAtIndex:indexPath.row];
cell.nameLabel.text = [itemAtIndex objectForKey:#"name"];
return cell;
}
// XML request and parsing
- (void)updateLocation:(CLLocation *)newLocation {
if ( coolarray ) {
[coolarray release];
}
coolarray = [[NSMutableArray alloc] init];
if ( newLocation ) {
latitude = newLocation.coordinate.latitude;
longitude = newLocation.coordinate.longitude;
}
NSString *urlString = [NSString stringWithFormat:#"(censored)"];
NSXMLParser *locationParser = [[[NSXMLParser alloc] initWithContentsOfURL:[NSURL URLWithString:urlString]] autorelease];
[locationParser setDelegate:self];
[locationParser parse];
[_tableView reloadData];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
if ( [elementName isEqualToString:#"location"]) {
[coolarray addObject:[[NSDictionary alloc] initWithDictionary:attributeDict]];
}
}
// GPS handling
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
[self updateLocation:newLocation];
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
}
// Search bar handling
- (void)searchBarSearchButtonClicked:(UISearchBar *)sb {
[self updateLocation:NULL];
[searchBar resignFirstResponder];
}
- (void)searchBarCancelButtonClicked:(UISearchBar *)sb
{
[searchBar resignFirstResponder];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"showDetail"])
{
NSIndexPath * indexPath=[self->_tableView indexPathForSelectedRow];
LoadingViewController* destViewController= segue.destinationViewController;
destViewController.myProgLang=[coolarray objectAtIndex:indexPath.row];
NSLog(#"indexPathrow:%d",indexPath.row);
}
}
#end
LoadingViewController.h (my detail view)
#import <UIKit/UIKit.h>
#interface LoadingViewController : UIViewController
{
}
#property (nonatomic, retain) IBOutlet UILabel *myLabel;
#property (nonatomic, retain) NSString *myProgLang;
#end
LoadingViewController.m (my detail view)
#import "LoadingViewController.h"
#interface LoadingViewController ()
#end
#implementation LoadingViewController
#synthesize myLabel, myProgLang;
- (void)viewDidLoad {
[super viewDidLoad];
myLabel.text = myProgLang;
[[self navigationController] setNavigationBarHidden:YES];
}
- (void)dealloc {
[myLabel release];
[myProgLang release];
[super dealloc];
}
#end
The problem is that your array appears to be a collection of dictionary objects. When you are about to segue you are taking a dictionary out of the object and are trying to store it as an NSString property.
Try changing your prepareForSegue: method as follows:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"showDetail"])
{
NSIndexPath * indexPath=[self->_tableView indexPathForSelectedRow];
LoadingViewController* destViewController= segue.destinationViewController;
destViewController.myProgLang=[[coolarray objectAtIndex:indexPath.row] objectForKey:#"name"];
NSLog(#"indexPathrow:%d",indexPath.row);
}
}
I have an array of objects, and i use following code to get in in the tableview
[source addObjectsFromArray:[UDdelegate naturArray]];
[[self tableView]reloadData];
My application fetch some data on location change, and that data is the objects in my naturArray. source is the list's datasource.
My problem is that if my list view is active while it is fetching the data, the list isn't updated. If i go to the main menu and back into the listView the data appear.
Is there a way to get the list to update while its active ?
Thanks.
Edit: Full code
VisListe.h:
#class UdINaturenAppDelegate;
#class POI;
#class webDetailView;
#interface VisListe : UITableViewController<UITableViewDelegate,UITableViewDataSource>
#property (nonatomic, retain,readwrite) IBOutlet NSMutableArray *dataSourceArray;
#property (strong, nonatomic) UdINaturenAppDelegate *UDdelegate;
#property (strong, nonatomic) POI *poi;
#property (strong, nonatomic) webDetailView *webView;
#property (strong, nonatomic) IBOutlet UITableView *tabel;
-(void)updateList;
-(NSString*)parseURL:(NSString*)url;
#end
VisListe.m:
#implementation VisListe
#synthesize dataSourceArray = source;
#synthesize UDdelegate;
#synthesize poi=_poi;
#synthesize webView = _webView;
#synthesize tabel = _tabel;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.navigationItem.title = NSLocalizedString(#"Poi List", nil);
UDdelegate = (UdINaturenAppDelegate*) [UIApplication sharedApplication].delegate;
source = [[NSMutableArray alloc]init];
_webView = [[webDetailView alloc] initWithNibName:#"webDetailView" bundle:nil];
[self updateList];
}
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
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//[source addObjectsFromArray:[UDdelegate naturArray]];
}
- (void)viewDidUnload
{
[self setTabel:nil];
[super viewDidUnload];
self.dataSourceArray = nil; // this will release and set to nil
source = nil;
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
NSLog(#"unload");
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self updateList];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
// to determine specific row height for each cell, override this.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return ([indexPath row] == 0) ? 60.0 : 60.0;
}
// to determine which UITableViewCell to be used on a given row.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//return [UDdelegate naturArray].count;
return [source count];
}
//
- (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];
}
_poi = [source objectAtIndex:indexPath.row];
cell.textLabel.text = [_poi title];
cell.detailTextLabel.text = [NSString stringWithFormat:#"Afstand: %f m.", [_poi dist]];
//[cell.imageView setImage:<#(UIImage *)#>];
return cell;
}
#pragma mark -
#pragma mark UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
_poi = [source objectAtIndex:indexPath.row];
NSLog(#"%#",[_poi title]);
NSString* u = [self parseURL:[_poi webUrl]];
[_webView setIncUrl:u];
[[self navigationController] pushViewController:_webView animated:YES];
}
-(NSString*)parseURL:(NSString*)url{
NSString* s = [url stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return s;
}
-(void)updateList{
[source removeAllObjects];
[source addObjectsFromArray:[UDdelegate naturArray]];
[_tabel reloadData];
}
-(UIImage*)setImgFromUrl:(NSString*)url{
NSURL *newurl = [NSURL URLWithString: url];
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL: newurl]];
return image;
}
When the location is fetched the updateList method is called from the AppDelegate.m
Turned out that it was just me who was a little impatient. the [_tabel reloadData] method is just a little "heavy" to call, so the list was in fact updated, but it just took a little while to update.