I have a UICollectionView that's connected to myclass datasource and delegate. When I call [self.collectionview reloaddata] it works normally but after a while (random time and number of times) when I reload the collection again it doesn't work any more.
collection reference delegate and datasource are correctly defined.
self.devicesCollectionViewDataSource= devices;
self.devicesCollectionView.delegate = self;
self.devicesCollectionView.dataSource = self;
[self.devicesCollectionView reloadData];
Overwrite the setDelegate method of your collection view subclass, set a breakpoint and observe who's changing it.
-(void)setDelegate:(id<YOUR_PROTOCOL>)delegate {
_delegate = delegate; // breakpoint here -> look at the trace log, it should give you the caller that's overwriting your delegate
}
Clarification: this doesn't solve your problem per se, but at least you know where to look
Related
I have a tabBarView which have two tableViews. each of these tableViews will represent some news from a remote server. I want to populate tableView's datasource when tableViewController's init method is called. so I have put the needed networking operation inside init method. My init method is this:
- (instancetype) init{
self = [super init];
[NewsManager fetch:10 remoteNewsOfLanguage:#"fa" withOffsett:1 andCompletionHandler:^(NSMutableArray *news) {
self.newsList = news;
}];
self.tabBarItem.title = #"my title";
return self;
}
newsList is an array holding news loaded from server.
But when I run my project the order of invocation for tableViewController's methods is like the following:
tableViewController's init method is called and finished (but the completion handler block is not called yet)
tableViewController's viewDidLoad method is called ( it is called when the tableViewController is added to tabBarView's viewControllers array)
tableViewController's delegate method tableView:numberOfRowsInSection is called
the network operation's completionHandler block is called and the newsList array is set to the retrieved news from server
So my problem is that before my newsList array is populated the method tableView:numberOfRowsInSection is called and so my tableView is not filled with any news. How should I solve this issue?
Thanks
you should reload table data after you get data from server. then only your table will show updated data.
[NewsManager fetch:10 remoteNewsOfLanguage:#"fa" withOffsett:1 andCompletionHandler:^(NSMutableArray *news) {
self.newsList = news;
[yourTableview reloadData];//add this line
}];
The added line does the job and makes the new data to be loaded in the tableView but there is a small point that I think you should consider
[tableView reloadData]
will be executed in a thread other than mainThread and this will cause a 5 to 10 seconds delay for the data to be loaded on the tableView.
to prevent this you should somehow tell it to run the reloadData method on the main thread. this is done with the dispatch_async. So you should call [tableView reloadData] like this:
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
Can someone clarify something for me. Apple documentation for UITableView says
`UITableView` overrides the layoutSubviews method of `UIView` so that it calls reloadData only when you create a new instance of `UITableView` or when you assign a new data source.
I'm getting the following behaviour:
In my viewDidLoad, I have tableView.dataSource = self.
In my getDataFromDatabase, I call [tableView reloadData]. This seems to work fine, but I think what's happening is the table is being populated with a blank array, then, when the db call comes back, it's reloading it with an array with data.
I'm trying to do the following:
In viewDidLoad, remove tableView.dataSource = self;, and add it in the getDataFromDatabase method. e.g.
(void)getDataFromDatabase
{
[getData completionHandler^() // an async db call
{
tableView.dataSource = self;
}];
}
This doesn't seem to be working. The table is not populated. It works if I add [tableView reloadData] after setting the dataSource = self, but from the documentation, shouldn't it call reloadData automatically when I set the dataSource = self "it calls reloadData only when you create a new instance of UITableView or when you assign a new data source." ?
Is your "completionHandler" running on main thread? If not or you are not sure about that, try executing your code on main thread. Because according to apple documentation, the result of not updating the UI on main thread is uncertain. You can try this:
[getData completionHandler^() // an async db call
{
dispatch_async(dispatch_get_main_queue(), ^{
tableView.dataSource = self;
});
}];
I am designing a one-to-one chatting interface using table view. This table view is modified to show bubbles as some new message arrives. The new message arrives through a push-notification in this case. I call following code in my function which receives message through the push notification:
-(void)messageReceived: (NSString *)message{
_message=[message retain];
[tableView reloadData];
}
However, it seems this does not reload my table view.
If I place the call for reloadData in the viewDidAppear function, it reloads fine. It also reloads fine, if I place the reloadData call in a function whose return type is IBAction (ex: a function binding to button click)
What could be the reason for reloadData to not get triggered through custom declared functions ?
reloaddata method is called but the trick here that you didn't add the incoming message to the datasource that the tableview load from !
may be you have not Connect the Tableview with table view Delegates and Datasource
Objective-C
#interface YourClass : UIViewController <UITextFieldDelegate, UITextViewDelegate>
yourtableview.delegate = self;
yourtableview.dataSource = self;
[tableView reloadData];
Swift 3
class YourClass: UIViewController , UITableViewDelegate, UITableViewDataSource
yourtableview.delegate = self
yourtableview.dataSource = self
yourtableview.reloadData()
the other way is! for Swift and Objective-C both.
Right Click on the Table view and drag and drop the delegates.
I want to draw a chart in an UIView. The question is how do I get the data (Points) to the view. If I create a protocol and set the UIViewController as the delegate where in the UIView do I call the delegate methods (initWithFrame? might be to early, and the delegate might not be set, awakeFromNib? but the view is 100% created in code, it has no nib file) ..
initWithFrame? might be to early, and the delegate might not be set.
In fact, the delegate cannot be set by the time you're in initWithFrame:, since the first thing you do with an object after allocation is initialization, i. e. until the init method returns, you can't call (well, it's idiomatic not to do so, at least) any other methods.
What you have to do is have a loadData or reloadData method, that the delegate must call explicitly after having set itself as the delegate of your view. I. e., from the view controller, you can call it like this:
#implementation ChartViewController
- (id)init
{
if ((self = [super init])) {
chartView = [[ChartView alloc] initWithFrame:self.view.frame];
chartView.delegate = self;
[self.view addSubview:chartView];
[chartView reloadData];
}
return self;
}
Then, in your chart drawing view, implement - reloadData as follows:
- (void)reloadData
{
// Call the delegate here,
// then do the drawing
}
A better way is to use UIViewController instead of a UIView. Because your that view has to manage data. Managing data is a UIViewController's job.
make a protocol but dont call it delegate. call it dataSource :D
anyways, call it when you first need the data .... as late as possible.. NOT in init.. maybe in the setDataSource call.
or when you draw for the first time and see you have no data..
look at UITableView to see how he does it and imitate that
The prequel of this problem is here.
I am trying to create and set a custom delegate and datasource to my programmatically created UITableView. I've googled around, but couldn't find any clear solution for my problem.
Meanwhile, I've created a new class that conforms to UITableViewDelegate,UITableViewDataSource
protocols. In this class:
tableView numberOfRowsInSection: 20
tableView cellForRowAtIndexPath: cell.textLabel.text=#"Nominals";
Class that contains UIViews:
Method that creates UITableView:
-(IBAction)segmentValueChaged:(id)sender
{
if(self.segment.selectedSegmentIndex==0)
{
[self.coinageView removeFromSuperview];
[self.view addSubview:nominalsView];
[self populateNominals:self.subCountryID];
}
else
{
[self.nominalsView removeFromSuperview];
[self.view addSubview:coinageView];
[self populateCoinages:self.subCountryID];
}
}
-(void)populateNominals:(int)subCountryID
{
NominalsTableViewDelegate *del=[[NominalsTableViewDelegate alloc]init];
UITableView *nominalsTableView=[[UITableView alloc]initWithFrame:CGRectMake(0, 0, 320, 372) style:UITableViewStylePlain];
[nominalsTableView setDelegate:del];
[nominalsTableView setDataSource:del];
[self.nominalsView addSubview:nominalsTableView];
[nominalsTableView reloadData];
}
Finally, I'm getting EXC_BAD_ACCESS.
The evil is in [nominalsTableView setDelegate:del]; [nominalsTableView setDataSource:del]; rows. What's wrong with them.
Help is much appreciated. Thanks in advance.
I am not sure if you are adding a new UITableView to your current view or not, but I will assume you are doing so.
If you have a class that conforms to the UITableViewDelegate. But when i needed to create a UITableView programmatically, I create a new UITableView class (with the .h and .m) then make a MutableArray and exposing it as a property to the parent view so it can set the data source.
From there, you can create an instance of the class along with the datasource (which you exposed from the child object). Finally, you then add the view onto your current view. This method you dont need to set the delegate because your child class conforms to the tableview delegate protocol.
If you are just modifying the data inside the current tableview then, you use a NSMutableArray and then change the data in it. After then do a
[self.tableView reloadData];
Hope this helps!
EDITED
I might have misunderstood your question, what you (most likely) need to do is create a property of the delegate class then create an instance of your delgate class and assign it to the property.
Then do a
[myTableView setDelegate:self.myProperty];
[myTableView setDatasource:self.myProperty];
This, I believe, would solve you bad access problem.
EDITED AGAIN
Create a property inside your .h of the tableview class as such:
#property (nonatomic, retain) NominalsTableViewDelegate *myDelegate;
From there then inside your .m file, you do something similar to this:
NominalsTableViewDelegate* delegateClass = [[NominalsTableViewDelegate alloc] init];
[self setMyDelegate:delegateClass];
[delegateClass release];
Then you can set your tableview datasource as such:
[myTableView setDelegate:self.myDelegate];
[myTableView setDatasource:self.myDelegate];
Note: I currently have no access to a machine to test this, but just something to point you towards.