UIPickerView reloadAllComponents doesn't get called - ios

I have 2 table cells, based on what i have selected in my first cell, i have to refresh the second cell, when i click the second cell a container view with a picker is changed from hidden to unhidden state.
When I press the cell I have a method which gets called where after i get the new data I reload my picker, but that line of code doesn't get called, my picker isn't refreshed:
-(void)reloadData:(NSUInteger) path{
//NSUInteger path = (NSUInteger)self.parentVC.pozOras;
NSString *parcareFile = [[NSBundle mainBundle] pathForResource:#"Parcare"
ofType:#"plist"];
self.fisier = [NSArray arrayWithContentsOfFile:parcareFile];
////Log(#"reloadData:%#",self.fisier);
NSDictionary *infoOras = [self.fisier objectAtIndex:path];
// NSLog(#"reloadData:%#",infoOras);
NSLog(#"reloadData:%d",(NSInteger)path);
NSArray *zones = [infoOras valueForKey:#"Zone"];
self.zone = [zones valueForKey:#"name"];
NSLog(#"reloadData:%#",self.zone);
self.price = [zones valueForKey:#"price"];
NSLog(#"reloadData:%#",self.price);
self.time = [zones valueForKey:#"durationminutes"];
NSLog(#"reloadData:%#",self.time);
[self.listaCuZone reloadAllComponents];
}
All the data from the Output of NSLog is what is should be in the picker.
I have the property of the UIPickerView in the header file, everything seems to be in place. I really don't know why it doesn't get called.
#interface PickerZone : UIViewController<UIPickerViewDataSource,UIPickerViewDelegate>
#property (nonatomic, assign) FirstViewController *parentVC;
#property NSInteger zona;
#property NSUInteger path;
#property NSMutableArray *fisier;
#property NSMutableArray *zone, *price, *time;
#property (strong, nonatomic) IBOutlet UIPickerView *listaCuZone;
- (IBAction)doneButton:(id)sender;
- (void)reloadData:(NSUInteger)path;
#end
Here is where i call the method from:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
if(indexPath.section == 0){
[self.listaZone viewForBaselineLayout].hidden = YES;
[self.listaOrase viewForBaselineLayout].hidden = NO;
}
else
{
PickerZone *pickerZone = [[PickerZone alloc]init];
[pickerZone reloadData:(NSUInteger)self.pozOras];
[pickerZone.listaCuZone reloadAllComponents];
[self.listaOrase viewForBaselineLayout].hidden = YES;
[self.listaZone viewForBaselineLayout].hidden = NO;
}
}
As you can see, i also try to reload the components here.
I have the delegate and the datasource also linked to the vc.
If i should post some more code please let me know, i really want to fix this.
Here is a screenshot of the storyboard: https://www.dropbox.com/s/4nkpz55zlcffh9w/Screenshot%202014-02-16%2019.31.24.png

Related

Passing data from a UITableView to a XIB Subview

I'm sure there is a simple solution and I have looked around and cannot find any help. I'm trying to pass data from a UITableview to a subview. I do not want to use a segue as I want the xib file to appear on the same viewcontroller with the required data. The NSLog outputs as expected but doesn't pass to the string in the "nowplayingnib" view.
ViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SongInfo *song = songsArray[indexPath.row];
NowPlayingNib *nowplayingnib = (NowPlayingNib *)[NowPlayingNib viewFromNib];
[self.view addSubview:nowplayingnib];
nowplayingnib.videoId = song.videoId;
NSLog(#"%#", song.videoId);
}
UPDATE
NowPlayingNib.h
#interface NowPlayingNib : UIView
#property (strong, nonatomic) NSString *videoId;
#property (strong, nonatomic) NSString *title;
+(id)viewFromNib;
#end
NowPlaying.m
#implementation NowPlayingNib
#synthesize videoId;
-(void)awakeFromNib{
NSLog(#"video id inside nib = %#", self.videoId);
}
+(id)viewFromNib{
ViewController *songinfo = [[[NSBundle mainBundle] loadNibNamed:#"NowPlayingNib" owner:self options:NULL]lastObject];
return songinfo;
}
Your output NSLog(#"video id inside nib = %#", self.videoId);
is in the awakeFromNib-method, but you are only assigning the value to videoId after the nib has been loaded and added to the superview?
what's the type of nowplayingnib.videoId ?
make it #property (nonatomic,strong) and check again
rewrite init method like:
+(id)viewFromNib{
ViewController *songinfo = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:nil options:NULL]lastObject];
return songinfo;
}

Table view cells lose their order

Goal
I'm trying to create a table view like Instegram's home screen.
I've made a custom cell, I'm initialising it with data, the cell suppose to hold the "Post".
Logic
I save each cell in a NSMutableDictionary , the key is the index of the posts order and the value is the post it self.
Current Result
I scroll down, and everything is fine. The order you see is post1, post2, post3...post 8 but when I scroll up, everything mess up and the post order is post8, post6, post7, post8, post5... You get the point.
(Before asking here I tried doing it with small objects - a REGULAR ! (not custom) cell containing only strings.
for some reason it worked ! the order was perfect.)
Code
this is my UITableViewController - my "Home" screen "cellForRow" Method.
if we scroll up and the index of the Tableview is alrdy have been initialised, I pull the post form the dictionary.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PC = #"PostCell";
PostCell *Pcell = [tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];
NSString *key = [[NSString alloc] initWithFormat:#"%i", indexPath.section];
NSLog(#"Cell %i", indexPath.section);
// Checking if alrdy visted this indexpath.
if (![_allcells objectForKey:key]) {
[self setPostUserName:[[NSString alloc] initWithFormat:#"username: %i", indexPath.section]:Pcell];
// Saving a postcell I wont return, just to save in a dictionary.
// When we get here again it will get another pointer like that my object wont change.
PostCell* toSave = [[PostCell alloc] init];
// saving it with current post data.
[self copyPost:toSave :Pcell];
[_allcells setObject:toSave forKey:key];
}
else {
// Copying post daya
[self copyPost:Pcell :[_allcells objectForKey:key]];
}
NSLog(#"Cell %i Returning: %#", indexPath.section, Pcell.userName.text);
return Pcell;
}
// Check if it reached the end
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
float endScrolling = scrollView.contentOffset.y + scrollView.frame.size.height;
if (endScrolling >= scrollView.contentSize.height)
{
NSDictionary *temparr = [[NSDictionary alloc] initWithDictionary:_allcells];
[self.tableView reloadData];
_allcells = [[NSMutableDictionary alloc] initWithDictionary:temparr];
}
}
and this is my PostCell.h , so you can see the attributes.
#interface PostCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UIImageView *profilePic;
#property (strong, nonatomic) IBOutlet UILabel *userName;
#property (strong, nonatomic) IBOutlet UILabel *checkIn;
#property (strong, nonatomic) IBOutlet UILabel *uploadedAgo;
#property (strong, nonatomic) IBOutlet UIImageView *mainPic;
#property (strong, nonatomic) IBOutlet UILabel *likes;
#property (strong, nonatomic) IBOutlet UILabel *participants;
#end
By the way, if you got a project example that has a result similar to Instagram home screen it would be great if you can link me to it!
You shouldn't store references to the cells, since they are being reused by the tableview when they leave the screen. At the moment everything works fine for you while scrolling down the first time, because you create the cells new. On scrolling up, you get the stored reference which now points to one of the newly created cells, so things look messed up.
What you should do is just populating the reused cells with the right data and only create them if needed. Like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *PC = #"PostCell";
PostCell *Pcell = (PostCell*)[tableView dequeueReusableCellWithIdentifier:PC forIndexPath:indexPath];
// feed the needed data to the cell
return Pcell;
}
Not sure why you are accessing only indexPath.section since usually you would populate the table with multiple cells per section, using indexPath.row.
Okay, I found out the mistake, Because I was first I was saving the id of each Post and than took it out of the dictionary it didn't work.
than I was trying to only save the attributes of the post by creating a "fake" postCell and saving the attribues of the original cell in the fake cell and than took it out of the array and made the cell copy ONLY the attributes of the cell I just took out and it didn't work.
why? because no matter what I was saving a POINTER ! to those fields !.
I've created a class which was ment to save my desired data that's the class I entered my dictionary.
now each time I dequeue a cell, I load it with the data of the index I'm at. :)
So nice to finally solve it and to learn something new, thanks for giving me leads !
A UITableView works best with an array. Also an array will stay in order as it is indexed, while dictionaries have no index, and thus will not retain order. Also separate cells of the same type, in this case PostCell, should not have different sections, but instead different rows. Use section to separate different categories of cells.
Another tip; NSMutableDictionary takes up more memory than an NSDictionary. Once you have set everything in your NSMutableDictionary, store it in an NSDictionary. If you want to modify it in the future, copy it back into an NSMutableDictionary, modify it, and then store it again as an NSDictionary.
#property (strong, nonatomic) NSDictionary *post;
// To create an NSDictionary
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:#"74 degrees" forKeyPath:#"weather"];
post = tempDict;
// To modify an NSDictionary
tempDict = [[NSMutableDictionary alloc] initWithDictionary:post];
[tempDict removeObjectForKey:#"weather"];
post = tempDict;
Then store it in an array.
#property (strong, nonatomic) NSArray *allPosts;
// NSMutableArray takes up more memory than NSArray
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithArray:allPosts];
[tempArray addObject:post];
allPosts = tempArray;
Finally, display it in your tableview.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *PC = #"PostCell";
PostCell *pCell = [tableView dequeueReusableCellWithIdentifier:PC];
if (!cell) {
pCcell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:PC];
}
NSDictionary *currentPost = [allPosts objectAtIndex:indexPath.row];
// Instead of having post1, post2, post3 and so forth, each post is now in currentPost. If there are 10 posts, then this function will run 10 times. Just write the code as if you are handling one post, and the UITableView will automatically fill in the rest of the posts for you.
return cell;
}

xCode Detail View is Empty

I am creating an iPad application (iOS6.1) which has a master detail view concept. First view is a table view has list of items that are been loaded from Plist, when each row gets selected the second table view gets loaded with another Plist. theirs is my Detail view which has to display an UIView with a UILabel ans an UIImage. I am using didSelectRowAtIndexPath method . The first two table Views are been displayed properly and loads the row and display corresponding View but the last detail view which is supposed to display the UILabel and an image is empty, can any one help me to solve this problem
My Code for the didSelectRowAtIndexPath method is
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
TaskDetailViewController *newTaskDetailViewController = [[TaskDetailViewController alloc] init];
// pass the row to newDetailViewController
if (weekNumber == 0)
{
newTaskDetailViewController.taskdescription = [weeklist1 objectAtIndex:indexPath.row];
}
if (weekNumber == 1)
{
newTaskDetailViewController.taskdescription = [weeklist2 objectAtIndex:indexPath.row];
}
if (weekNumber == 2)
{
newTaskDetailViewController.taskdescription = [weeklist3 objectAtIndex:indexPath.row];
}
// ...... repeated for 39 times because of the list
newTaskDetailViewController.taskNumber = indexPath.row;
[self.navigationController pushViewController:newTaskDetailViewController animated:YES];
}
DetailView header
#import <UIKit/UIKit.h>
#interface TaskDetailViewController : UIViewController
#property int taskNumber;
#property(strong , nonatomic) NSString *taskdescription;
#property (nonatomic , strong) NSMutableDictionary * tasks;
#property (strong, nonatomic) IBOutlet UIImageView *questionImage;
#property (strong, nonatomic) IBOutlet UILabel *displayText;
#end
Implemetation file has
#implementation TaskDetailViewController
#synthesize taskNumber;
#synthesize taskdescription;
#synthesize tasks;
#synthesize displayText;
#synthesize questionImage;
-(void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = taskdescription;
NSLog(#"%#", taskdescription);
}
Your problem is using alloc init to create an instance of TaskDetailViewController. You've created that controller in the storyboard so you should instantiate it from the storyboard using an identifier that you give it (DetailViewController in my example):
TaskDetailViewController *newTaskDetailViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];

Changing title in UINavigationBar when a row from UITableView is touched

Ok, so I have tried this a lot of different ways...
At the moment I have placed the UINavigationBar with the IB. Then declared it with IBOutlet.
From there I can't seem to change the title no matter what i try. Even just in ViewDidLoad.
Also, I dont need to assign the delegate of the navbar do i?
Here is my code:
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController < UITableViewDataSource, UITableViewDelegate>
{
NSArray *myArrayOne;
NSArray *myArrayTwo;
UITextView *myTextView;
UINavigationBar *myNavBar;
}
#property (nonatomic, retain) NSArray *myArrayOne;
#property (nonatomic, retain) NSArray *myArrayTwo;
#property (nonatomic, retain) IBOutlet UITextView *myTextView;
#property (nonatomic, retain) IBOutlet UINavigationBar *myNavBar;
#end
and:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
//Synthesising anything with a property call in the .h file.
#synthesize myArrayOne;
#synthesize myArrayTwo;
#synthesize myTextView;
#synthesize myNavBar;
- (void)viewDidLoad
{
//declaring and instantiating datapaths and also
// reading into arrays from plist.
NSString *datapath1 = [[NSBundle mainBundle] pathForResource:#"myListOne" ofType:#"plist"];
NSString *datapath2 = [[NSBundle mainBundle] pathForResource:#"myListTwo" ofType:#"plist"];
myArrayOne = [[NSArray alloc] initWithContentsOfFile:datapath1];
myArrayTwo = [[NSArray alloc] initWithContentsOfFile:datapath2];
self.navigationItem.title = #"Hi";
[super viewDidLoad];
}
#pragma mark - TableView Delegate stuff
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//myNavBar.title = [myArrayOne objectAtIndex:indexPath.row];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - TableView Datasource stuff
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
//returns amount of items inside myArrayOne as amount of rows
return [myArrayOne count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *myCell = nil;
myCell = [tableView dequeueReusableCellWithIdentifier:#"myReuseCell"];
if (myCell == nil)
{
myCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"myReuseCell"];
}
myCell.textLabel.text = [myArrayOne objectAtIndex:indexPath.row];
return myCell;
}
#end
the actual code to change the title is just one way i have tried...
Any other way? And do I need to link the navigationbar in the IB with anything?
If you have a navigation bar without a navigation controller, you have to give it a stack (in your case, a stack of one) navigation items.
In viewDidLoad of your view controller, add your view controller's navigation item to the stack:
self.myNavBar.items = #[self.navigationItem];
Now you can set the title like so:
self.navigationItem.title = #"Hello";
and it will appear in your navigation bar.
The solution above by jrturton works fine UNLESS you also have a UIBarButtonItem (e.g. a "Done" button) in the UINavigationBar. In that case, the proposed solution causes the UIBarButtonItem to disappear.
Here's how to do it in a way that lets you change the UINavigationBar title but also preserve the UIBarButtonItem:
Add IBOutlet UINavigationItem *myNavigationItem; to your code.
In IB, in the outline view (not the storyboard view), right click the containing UIViewController and drag to the UINavigationItem that was automatically created by IB inside the UINavigationBar and connect to myNavigationItem.
Back in your code, add self.myNavigationItem.title = #"Hello";
I think you need to have a navigationController instead why don't you check this link:
create navigation bar for tableView programmatically in objective-C
and if you already have a navigation controller in your app delegate, then you should remove the IBoutlet you've created then use:
self.navigationItem.title = #"Hi";
for this will be referring the navigationController in your app delegate.

iOS delegation does not work, cannot fix it (code inside): sending data from UITableView to UITextField in another view

I searched extensively for delegation tutorials, but could not get it to work. Here is the story and the code.
DetailViewController has a UITextField and a UIButton. When you press the button you get to another PricelistViewController with a simple sectioned table. Tapping a row in that table should return the text from the row's title to the first view and insert it into the text field. But it doesn't. Here is the code:
PricelistViewController.h (the second view):
#class PricelistViewController;
#protocol PricelistViewControllerDelegate <NSObject>
#required
//- (void)theSaveButtonOnThePriceListWasTapped:(PricelistViewController *)controller didUpdateValue:(NSString *)value;
- (void)theSaveButtonOnThePriceListWasTapped:(NSString *)value;
#end
#interface PricelistViewController : UITableViewController
#property (nonatomic, weak) id <PricelistViewControllerDelegate> delegate;
#property (retain, nonatomic) NSMutableArray * listOfSections;
#end
PricelistViewController.m
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dictionary = [listOfSections objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"ProductSections"];
NSString *selectedProduct = [array objectAtIndex:indexPath.row];
[self.delegate theSaveButtonOnThePriceListWasTapped:[NSString stringWithFormat:#"%#", selectedProduct]];
[self.navigationController popViewControllerAnimated:YES];
}
This is the code in DetailViewController.h (the first view with a text field and the button):
#import "PricelistViewController.h"
#interface DetailViewController : UIViewController <UITextFieldDelegate, PricelistViewControllerDelegate>
DetailViewController.m (this I how I am trying to change the text in the field):
- (void)theSaveButtonOnThePriceListWasTapped:(NSString *)value
{
NSLog(#"Text, sent here: %#", value);
NSLog(#"Text was sent here.");
self.detailDescriptionLabel.text = value;
}
detailDescriptionLabel is the UITextField for the text to display.
Can somebody check the code and help? I work on this matter two days with no luck!
Firstly why are you forward referencing (#class) your class in the header file of the PriceListViewController? This isn't needed.
Secondly are you using ARC, if you are your array property should be of type nonatomic, strong. If you're not your delegate property should be nonatomic, assign. You seem to be mixing your terminology
Also where and how are you initialising your array?
I figured it out.
In the PricelistViewController.m I changed the way I call the method (added If statement):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dictionary = [listOfSections objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"ProductSections"];
NSString *selectedProduct = [array objectAtIndex:indexPath.row];
if (delegatePrice && [delegatePrice respondsToSelector:#selector(theSaveButtonOnThePriceListWasTapped:didUpdateValue:)])
{
[delegatePrice theSaveButtonOnThePriceListWasTapped:self didUpdateValue:selectedProduct];
}
AND THE MOST IMPORTANT: I refused to use the Storyboard and instead made a old good .xib file for my PricelistViewController view and it worked right away!

Resources