ObjC: Update *label when turning back from Editing-View - objective-c

sorry for my bad english, if you don't understand me, please ask! :)
I have a problem with Objective-C.
I try to explain my problem as easy as possible:
I made two interfaces 'profile' and 'editProfile' in 'profile.m".
I'd like to have a table (or for the beginning a *label) in profile, then I can click at 'edit' and fill in a TextField a string. With a 'save' button i save this string in a database (or an extern variable). Thats no problem, of course..
Now my problem: With clicking on 'save' i want to get back to the 'profile' page, my code:
[self.navigationController popViewControllerAnimated:YES];
But I want to have the IBOutlet UILabel *label (or table) updated. This *label should show the text, which I entered in the TextField in 'editprofile'.
But it doesn't update! Parts of my code 'profile':
#implementation Profil
#synthesize label;
// ....
-(void) method{
Database* db = [[Database alloc] init];
if([db getadresse]!=nil){
NSString *s=[db getadresse];
label.text=s;
[data addObject:s];
[datadetail addObject:#"Adresse"];}
//...
and 'editprofil':
-(IBAction)save:(id)sender{
Database* db = [[Database alloc] init];
[db setadresse:TextField.text];
[self.navigationController popViewControllerAnimated:YES];
Profile* p= [[Profile alloc] init];
[p method];}
What can I do to get *label updated immediately?
Thanks!
And what about a table in 'profile'? I want to get it refreshed.
I put the following lines in 'ViewWillApear':
data = [[NSMutableArray alloc] init]; //NSMutableArrays
datadetail = [[NSMutableArray alloc] init];
database* db = [[database alloc] init];
if([db getadresse]!=nil){
NSString *s=[db getadresse];
[data addObject:s];
[datadetail addObject:#"Adresse"];}
if([data count]>0){
UITableView *table = [[UITableView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]
style:UITableViewStylePlain];
table.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
table.delegate = self;
table.dataSource = self;
[table reloadData];
self.view = table;
}
So the table (created in ViewWillAppear) should show the one entry of the Array ('[db.getadresse]'). But i get the Exception:
-[Profile tableView:numberOfRowsInSection:]: unrecognized selector sent to instance 0x688d290
NumberOfRowsInSection is just: return [data count]
Can u tell me what goes wrong?
Thank you!

UIKit will sends the viewWillAppear: message to a view controller when its view appears. Your first ("profile") view controller can update the label when it receives that message:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.label.text = code to get the text from the database;
}

Related

Empty Table View in UIPopover

I am having some hard time with TableView insite UIPopover, the table is simply empty, even though it is a static table view.
code:
- (IBAction)settingsBtnPressed:(id)sender {
if(self.pop.isPopoverVisible) {
[self.pop dismissPopoverAnimated:YES];
} else {
//SettingsViewController *s = [[SettingsViewController alloc] init];
SettingsViewController *s = [self.storyboard instantiateViewControllerWithIdentifier:#"settings"];
s.brain = self.brain;
self.pop = [[UIPopoverController alloc] initWithContentViewController:s];
[self.pop setPopoverContentSize:CGSizeMake(400, 500)];
[self.pop presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
}
}
Attaching screenshots:
Have you implemented methods like cellForRow:atIndex:, numberOfSections:inTableView: and numberOfRows:inSection ?
Maybe you are not using UITableViewController but rather UIViewController in your header file.

SplitView-Based App: Display an independant view

I have a splitview-based app, that has a popover menu containing 3 views. I would like to add another view, that doesn't appear in the popover menu, and is displayed when a different button is clicked.
Here is a screenshot, with the popover menu, and the 'Log' button which I want to use to display my new view.
All of the other views are configured something like this:
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (row == 0) {
FirstDetailViewController *newDetailViewController = [[FirstDetailViewController alloc] initWithNibName:#"FirstDetailView" bundle:nil];
detailViewController = newDetailViewController;
}
...
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
I tried to replicate this code for my new view:
-(void)displayLogView{
UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
LogDetailViewController *newDetailViewController = [[LogDetailViewController alloc] initWithNibName:#"LogDetailViewController" bundle:nil];
detailViewController = newDetailViewController;
// Update the split view controller's view controllers array.
NSArray *viewControllers = [[NSArray alloc] initWithObjects:self.navigationController, detailViewController, nil];
splitViewController.viewControllers = viewControllers;
[viewControllers release];
[detailViewController release];
}
But nothing happens. I think that I am missing the code to actually display the view. I tried to find how the other views were displayed, but could not find anything (I got the code from the apple sample code).
Any help would be appreciated!
If you just want a slide-over view try using presentModalViewController to show it and dismissModalViewController to get rid of it.

NSMutableArray to NSString and Passing NSString to Another View IOS5.1

I have an NSMutableArray of names. I want the pass the data (selected name) inside of NSMutableArray as text to another view's label.
FriendsController.m:
- (void)viewDidLoad {
[super viewDidLoad];
arrayOfNames=[[NSMutableArray alloc] init];
arrayOfIDs=[[NSMutableArray alloc] init];
userName=[[NSString alloc] init];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
long long fbid = [[arrayOfIDs objectAtIndex:indexPath.row]longLongValue];
NSString *user=[NSString stringWithFormat:#"%llu/picture",fbid];
[facebook requestWithGraphPath:user andDelegate:self];
userName=[NSString stringWithFormat:#"%#",[arrayOfNames objectAtIndex:indexPath.row]];
FriendDetail *profileDetailName = [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
profileDetailName.nameString=userName;
[profileDetailName release];
}
- (void)request:(FBRequest *)request didLoad:(id)result {
if ([result isKindOfClass:[NSData class]]) {
transferImage = [[UIImage alloc] initWithData: result];
FriendDetail *profileDetailPicture = [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
[profileDetailPicture view];
profileDetailPicture.profileImage.image= transferImage;
profileDetailPicture.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:profileDetailPicture animated:YES];
[profileDetailPicture release];
}
}
In FriendDetail.h
NSString nameString;
IBOutlet UILabel *profileName;
#property (nonatomic, retain) UILabel *profileName;
#property (nonatomic, retain) NSString *nameString;
In FriendDetail.m
- (void)viewDidLoad
{
[super viewDidLoad];
profileName.text=nameString;
}
nameString in second controller(FriendDetail) returns nil. When i set a breakpoint in firstcontroller I see the string inside of nameString is correct but after that it returns to nil somehow.
-----------------------EDIT----------------------------------------
According to answers I have improved my code little bit
FriendsController.h
FriendDetail *friendController;
#property (strong, nonatomic) FriendDetail *friendController;
FriendsController.m
- (void)viewDidLoad
{
[super viewDidLoad];
arrayOfNames=[[NSMutableArray alloc] init];
arrayOfIDs=[[NSMutableArray alloc] init];
arrayOfThumbnails=[[NSMutableArray alloc] init];
userName=[[NSString alloc] init];
friendController= [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
}
-(void)request:(FBRequest *)request didLoad:(id)result{
if ([result isKindOfClass:[NSData class]])
{
transferImage = [[UIImage alloc] initWithData: result];
friendController.nameString=userName;
[friendController view];
friendController.profileImage.image= transferImage;
friendController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:friendController animated:YES];
}
//this is how i take facebook friends list
if ([result isKindOfClass:[NSDictionary class]]){
items = [[(NSDictionary *)result objectForKey:#"data"]retain];
for (int i=0; i<[items count]; i++) {
NSDictionary *friend = [items objectAtIndex:i];
long long fbid = [[friend objectForKey:#"id"]longLongValue];
NSString *name = [friend objectForKey:#"name"];
NSLog(#"id: %lld - Name: %#", fbid, name);
[arrayOfNames addObject:[NSString stringWithFormat:#"%#", name]];
[arrayOfIDs addObject:[NSNumber numberWithLongLong:fbid]];
}
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
long long fbid = [[arrayOfIDs objectAtIndex:indexPath.row]longLongValue];
NSString *user=[NSString stringWithFormat:#"%llu/picture",fbid];
userName=[NSString stringWithFormat:#"%#",[arrayOfNames objectAtIndex:indexPath.row]];
[facebook requestWithGraphPath:user andDelegate:self];
[username retain]
}
Now when i select row first time it sends name. When i come back to tableview and select another name it shows the old name.
If I delete [username retain] in didSelectRowAtIndexPath: it still sends nil to nameString
when I set break point at didSelectRowAtIndexPath: at line `
userName=[NSString stringWithFormat:#"%#",[arrayOfNames objectAtIndex:indexPath.row]]`
I can see userName = #"Adam Dart" which is correct
in my second breakpoint at line friendController.nameString=userName; I see that nameString =nil and userName = Variable is not CFString
ARC is set to NO
The value is nil because you did not pass the value in request:didLoad: function.
In function didSelectRowAtIndexPath, You create a local instance of another ViewController and set the value of nameString, but you did not present the view and release the ViewController immediately. You actually do nothing in these few lines of code:
FriendDetail *profileDetailName = [[FriendDetail alloc] initWithNibName: #"FriendDetail" bundle: nil];
profileDetailName.nameString = userName;
[profileDetailName release];
In function request:didLoad:, again you create a local instance of another ViewController with image. But this instance is only local to this function, which means no relation to the one created in didSelectRowAtIndexPath.
What you need to do is, remember the name of clicked row first in didSelectRowAtIndexPath, here you dont have to create the ViewController instance. When the request finish, set both the image and name to the controller and then present it. But you should avoid user from clicking different rows at the same time, because you don't know when the request finish.
You have two instances of FriendDetail called profileDetailPicture. Both of theses profileDetailPicture are not the same. So in your didSelectRowAtIndexPath method, the value that you assigned to the nameString will not be visible/available to the nameString of the profileDetailPicture In the request:(FBRequest *)request didLoad method.
Edit for solution:
Create an iVar or property (profileDetailPicture) in the FriendController.
Only do one allocation in the request:(...) method.
Remove the allocation statement in the didSelectRowAtIndexPath.
Any chance it has to do with the fact that you assign to profileDetailName and then immediately release it?
profileDetailName.nameString=userName;
[profileDetailName release];
You have to allocate the "first_controller" in your "second_controller"
to pass objects such as your string. and you would call the nameString differently.
example:
second_controller.h
#import "first_controller.h"
...
#interface second_controller : UIViewController{
first_controller* firstController;
}
second_controller.m
- (void)viewDidLoad {
[super viewDidLoad];
firstController = [[first_controller alloc] init];
profileName.text = firstController.nameString;
}
Which you'll have to init it correctly, because its two views sharing information.

How can i push a TableView on clicking a button and initialize the TableViewCell with NSDictionary?

Can anyone please help me about how to push a table view on clicking a button.
I want to load the messages from NSMutableArray to the table view cells and NSMutableArray is loaded with the data parsed from a URL..
-(IBAction)readMessages:(id)sender
{
// i want to push the tableview when clicking the button in relation with this method
// WHAT MUST I DO HERE?
}
Instead of asking a new question i liked to edit this one, since the matter is in the same aspect..
I now can create the tableview programatically, but i cant initialize its cells with the data i get from Json array. Here is my code:
NSString *str1=[#"?username=" stringByAppendingString:userNameField.text];
NSString *str2=[#"&password=" stringByAppendingString:passwordField.text];
NSString *str3=[str1 stringByAppendingString:str2];
NSString *str4 =[#"http://" stringByAppendingString:serverField.text];
NSURL *url=[NSURL URLWithString:[str4 stringByAppendingString:[#"/ipad/login.php" stringByAppendingString:str3]]];
//get the url to jsondata
NSData *jSonData=[NSData dataWithContentsOfURL:url];
if (jSonData!=nil) {
NSError *error=nil;
id result=[NSJSONSerialization JSONObjectWithData:jSonData options:
NSJSONReadingMutableContainers error:&error];
if (error==nil) {
NSDictionary *mess=[result objectForKey:#"message"];
NSDictionary *messContent=[mess valueForKeyPath:#"message"];
NSDictionary *messID=[mess valueForKeyPath:#"ID"];
NSString*key1=[ result objectForKey:#"key" ];
NSString *s1=[#"http://" stringByAppendingString:serverField.text];
NSString *s2=[s1 stringByAppendingString:#"/ipad/button.php"];
NSURL *url2=[NSURL URLWithString:[s2 stringByAppendingString:[#"?key=" stringByAppendingString:key1]]];
NSData *data2=[NSData dataWithContentsOfURL:url2];
id result2=[NSJSONSerialization JSONObjectWithData:data2 options:NSJSONReadingMutableContainers error:nil];
mesID = [NSMutableArray array];//saving meesage ID s to NSMutableArray
content = [NSMutableArray array];
// i logged here and it saves the data, now i want to display my data in table view
for (NSDictionary *data in mess) {
[mesID addObject:[data objectForKey:#"ID"]];
[content addObject:[data objectForKey:#"message"]];
[[NSUserDefaults standardUserDefaults] setObject:messID forKey:#"message"];
[[NSUserDefaults standardUserDefaults] setObject:messContent forKey:#"messContent"];
//messID will be saved as the Title of the cells and messContent will be displayed as the text area of that cell, opening in a new view
And this is the output, i want to set the titles of cells as ID and their content as text:
2012-01-17 16:26:59.873 ipad_Teslim[940:f803] MessID: (
1,
3
)
2012-01-17 16:26:59.875 ipad_Teslim[940:f803] Content: (
asdf,
"this is a test"
)
As i have mentioned in my code too, messID will be saved as the Title of the cells and messContent will be displayed as the text area of that cell, opening in a new view.. How can i do it now? Please Help me, there are a lot of tutorials there, i looked a lot too but couldn't break this problem.
Try this :
-(IBAction)readMessages:(id)sender {
SecondView *secondView =[[SecondView alloc] initWithNibName:#"SecondView" bundle:nil];
[self presentModalViewController:secondView animated:YES];
}
SecondView is your UIViewController subclass which hold a UITableView.
Q1: U no need to add a navigation to return back to ur main page.
When ever u use
[self.navigationController pushViewController:next animated:YES];
by defaults it will creates back navigation in the next view to push return back.
in case it doesn't created yet, Try the following code in next view:
- (void)viewDidLoad
{
[super viewDidLoad];
//To set the back buttin on leftside of Navigation bar
UIBarButtonItem *backButton = [[[UIBarButtonItem alloc] initWithTitle:#"Back" style:UIBarButtonItemStyleDone target:self action:#selector(backclick:)] autorelease];
self.navigationItem.leftBarButtonItem = backButton;
}
- (IBAction)backclick:(id)sender //first declrared in .h file
{
// To goback to the previous view
[self.navigationController popViewControllerAnimated:YES];
}
If u have a navigation control and if u want to pushed by navigation try the following:
-(IBAction)readMessages:(id)sender {
NextView *next = [[NextView alloc]initWithNibName:#"NextView" bundle:nil];
[self.navigationController pushViewController:next animated:YES];
[next release];
}
if u dont have a navigation control and if u want to just display the next view, try the following:
-(IBAction)readMessages:(id)sender {
NextView *next =[[NextView alloc] initWithNibName:#"NextView" bundle:nil];
[self presentModalViewController:next animated:YES];
[next release];
}
if u are having sub view in the same class try the following:
-(IBAction)readMessages:(id)sender {
[self.view addsubview nextView];
}
Yes U can,
try this to create xib programitically in viewDidload:
UIView *view1 = [[UIView alloc]initWithFrame:CGRectMake(10, 10,300,460)];
view1.backgroundColor = [UIColor redColor];
[self.view addSubview:view1];
But better to create by using
following path in xcode menu:
File-> New -> NewFile -> UIViewControllerSubClass -> Next -> Next -> Create
Or simply Drag & drop an view from ur Interface Builder
Q2: U can initialize ur tableView cells with JSONArray:
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [JSONarray count]; //***********
}
- (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] autorelease];
cell.textLabel.text = [JSONarray objectAtIndexIndexPath.row]; //***********
}

Error: unrecognized selector sent to instance

I have a custom object, Spaces:
#import "Spaces.h"
#implementation Spaces
#synthesize spaceName;
#synthesize spaceUsers;
#synthesize spaceIcon;
#synthesize spaceID;
#synthesize imageURLString;
- (void)dealloc
{
[spaceName release];
[spaceUsers release];
[spaceIcon release];
[imageURLString release];
[super dealloc];
}
#end
My root view controller implements a cellForRowAtIndexPath: and grabs from an NSArray of Spaces:
[[cell spaceName] setText:aSpace.spaceName];
[[cell spaceChatType] setText:#"People"];
[[cell spaceActiveUsers] setText:aSpace.spaceUsers];
This works fine and I can click to go into the detail view and back to the list, but after maybe 5-6 clicks back and forth between the table view and detail view, I get an error at [[cell spaceName] setText:aSpace.spaceName]; which is
'-[__NSCFSet spaceName]: unrecognized selector sent to instance 0x6047b90'"
Please help! Any insight will be very appreciated!
UPDATE:
I'm still getting the same error but I've narrowed it down to the this:
-I'm creating a detail view controller on didSelectRowAtIndexPath...
-The detail view is being pushed to the viewcontroller and displays fine, I have a back button added as well.
-The detail view loads information and refreshes on a timer
-Pressing the back button goes back to the table list view
This is the problem my detail view is not being released from memory so the more I go back and forth between the views the more timers were going off simultaneously. I added a check to viewWillDisappear that stops the timer by setting a bool value.
I noticed that the detail view is not unloading...
From the RootViewController:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//no longer on initial view
isinit = NO;
//hide keyboard
[spacesSearch resignFirstResponder];
if (spaces != nil && spaces.count > 0)
{
//set back button reference
UIBarButtonItem *backButton = [[UIBarButtonItem alloc] initWithTitle:#"Spaces" style:UIBarButtonItemStylePlain target:self action:#selector(returnSpacesList:)];
self.navigationItem.backBarButtonItem = backButton;
[backButton release];
DetailViewController *details = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
//Grab Data from selected Space object and pass to DetailViewController
Spaces *aSpace = nil;
if (tableView == self.searchDisplayController.searchResultsTableView)
{
if ([self.filteredListContent count] == 0)
{
//self.lastSearchText
NSLog(#"Create new space code!");
}
else
{
aSpace = [self.filteredListContent objectAtIndex:indexPath.row];
}
}
else
{
aSpace = [spaces objectAtIndex:[indexPath row]];
}
//set title and display
self.navigationController.title = [NSString stringWithFormat:#"/%#/",aSpace.spaceName];
//pass data
[details passedValue:aSpace.spaceID :aSpace.spaceName];
[self.navigationController pushViewController:details animated:YES];
[aSpace release];
[details release];
}
}
How can I force the detail view to be released from memory?
Thank you
It sounds like [cell spaceName] has been autoReleased. I cannot see how you have defined that, but take a look at that part of your code.
If you need more help, you need to provide more code.
Perhaps your aSpace = [spaces objectAtIndex:[indexPath row]];
is not returning a Space object. Perhaps before you try and use it you test to make sure with something like if ([aSpace class] == [Spaces class])