I have a strange problem with trying to pass a string from one viewcontroller to another view controller if the string originates from a UITextview instead of UITextfield. Both UITextview.text and UITextfield.text are of type NSString.
The following code takes either Textfield.text or Textview.text depending on the fieldType and puts it into a string called aString.
NSString *aString = [[NSString alloc] init];
if (fieldType == 3) {
aString = textView.text;
} else {
aString = textField.text;
}
When I examine aString on either cases, I can see that it has successfully assigned the text into aString.
I then pass the string to the other view controller using this code.
[delegate updateSite:aString :editedFieldKey :fieldType];
[self.navigationController popViewControllerAnimated:YES];
This works fine if aString originated from textfield.text but nothing happens except the view controller is popped if aString was from textview.text
This is the code that takes aString and does stuff with it, however it doesn't even execute the first line of code "NSLog(#"Returned object: %#, field type:%#", aString,editedFieldKey);" if aString was from textview.text Any help will be appreciated.
-(void)updateSite:(NSString *)aString :(NSString *)editedFieldKey :(int)fieldType {
NSLog(#"Returned object: %#, field type:%#", aString,editedFieldKey);
switch (fieldType) {
case 0: //string
[aDiveSite setValue:aString forKey:editedFieldKey] ;
NSLog(#"String set %#",[aDiveSite valueForKey:editedFieldKey] );
break;
case 1: //int
[aDiveSite setValue:[NSNumber numberWithInt:aString.intValue] forKey:editedFieldKey];
NSLog(#"Integer set");
break;
case 2: //float
NSLog(#"Saving floating value");
[aDiveSite setValue:[NSNumber numberWithFloat:aString.floatValue] forKey:editedFieldKey];
NSLog(#"Float set");
break;
case 3: //Text view
[aDiveSite setValue:aString forKey:editedFieldKey];
NSLog(#"Textview text saved");
default:
break;
}
[self.tableView reloadData];
}
Uhm, sounds strange but I think your syntax is wrong:
[delegate updateSite:aString :editedFieldKey :fieldType];
should be
[delegate updateSite:aString editedFieldKey:fieldType];
and the method name:
-(void)updateSite:(NSString *)aString :(NSString *)editedFieldKey :(int)fieldType;
should be:
-(void)updateSite:(NSString *)aString (NSString *)editedFieldKey :(int)fieldType;
Can you try it?
This is what I've changed it to for editing textfield
[self.delegate editingViewController:self didTypeText:aString forKey:editedFieldKey forFieldType:fieldType];
and for textview I've created a separate controller that deals with it (and it works)
[self.delegate editTextViewController:self didEditText:textView.text forKey:editedFieldKey];
Related
I am declaring an instance of NSString named *strKey and #synthesize and i pass one string value to it.
But when I want to send that string to another class. it is giving me error of
Here is my code
Assigning one value to the strKey here
-(IBAction)getLocal:(UIButton *)sender
{
[self startDeckDownload];
GroupDeckExpandableViewObject *objConfiguration=[[GroupDeckExpandableViewObject alloc] init];
GroupListCell *celltest=(GroupListCell *)sender.superview.superview.superview;
if(celltest != nil){
celltest.viewDownload.hidden =NO;
celltest.viewGetLocal.hidden=YES;
//objConfiguration.vwWelcome=celltest.viewWelcome;
objConfiguration.vwGetLocal=celltest.viewGetLocal;
objConfiguration.vwDownLoad=celltest.viewDownload;
strKey=[NSString stringWithFormat:#"%d",[sender tag]]; // i am assign one value to the string here.
[delegate setGroupViewConfiguration:objConfiguration withtag:[NSString stringWithFormat:#"%d",[sender tag]]];
}
}
passing to another class(using protocol).
-(void)setDownloadProgress:(float)progress
{
[delegate setDownloadProgress:progress withkey:strKey];
}
Here is the definition to the protocol method.
#protocol groupListCellDelegate<NSObject>
#optional
- (void) setGroupViewConfiguration:(id)objConfiguration withtag:(NSString *)key;
-(void)setDownloadProgress:(float)progress withkey:(NSString *)key;
#end
I use this method in my GroupView.m
#pragma mark - delegate method
-(void)setGroupViewConfiguration:(id)objConfiguration withtag:(NSString *)key
{
[arrGroupViewConfiguration setValue:objConfiguration forKey:key];
GroupDeckExpandableViewObject *objgetviews=[arrGroupViewConfiguration valueForKey:key];
[tblData reloadRowsAtIndexPaths:[NSArray arrayWithObjects:objgetviews.cellIndexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
// [tblData reloadData];
}
-(void)setDownloadProgress:(float)progress withkey:(NSString *)key
{
NSLog(#"Reloaded...");
progress_percent = progress;
GroupDeckExpandableViewObject *objgetviews=[arrGroupViewConfiguration valueForKey:key];
NSLog(#"%d",objgetviews.cellIndexPath.section);
[tblData reloadRowsAtIndexPaths:[NSArray arrayWithObjects:objgetviews.cellIndexPath, nil] withRowAnimation:UITableViewRowAnimationNone];
// [tblData reloadData];
}
What am I missing here?
You own the object returned from initWithFormat which you are responsible for releasing, but you don't own the object returned from stringWithFormat which returns an autoreleased string and so do not need to release it (if you do want to have ownership of it, you must retain it).
So for resolving your issue try to assign your value like this,
strKey=[[NSString alloc] initWithFormat:#"%d",[sender tag]];
I am facing trouble in JSON parsing. When I have completed the code and run this, then the problem is occurred:
no known class method for selector 'show alert:with message'.
Following is my code:
if (!isValid) {
[AppDelegate showAlert:#"Alert!" withMessage:strMessage];
}
return isValid;
}
-(void)registerUser{
[Loading startLoading:YES];
NSString *urlString = [NSString stringWithFormat:#"URL=//%#",Access_Token];
//username, password, name, email, country
NSString *parameter = [NSString stringWithFormat:#"firstname=%#&lastname=%#email=%#&username=%#&password=%#&confirmpassword=#",fnameField.text,lnameField.text,eamilField.text,unameField.text,passField.text,cpassField];
NSConnection *conn = [[NSConnection alloc] initWithDelegate:self];
[conn sendRequest:urlString withParaMeter:parameter withMethod:#"POST" withTag:1];
[conn startAsynchronousRequest];
}
-(void)NSConnection:(NSConnection*)conn didFailWithError:(NSError*)error withTag:(int)tag{
NSLog(#"error is:- %#",[error description]);
}
-(void)NSConnection:(NSConnection*)request didSuccessWithItems:(NSDictionary*)dicData withData:(NSData*)data withTag:(int)tag{
NSLog(#"all data is:- %#",dicData);
int returnCode = [[dicData valueForKeyPath:#"process.returncode"] intValue];
NSString *strMessage = #"";
returnCode = 0;
switch (returnCode) {
case 0:
break;
case 1:
strMessage = #"User not logged in/process Id not available.";
break;
case 2:
strMessage = #"Invalid parameters passed.";
break;
case 3:
strMessage = #"Access token doesn't exist.";
break;
default:
strMessage = #"User name allready exist.";
break;
}
[AppDelegate showAlert:#"Alert!" withMessage:strMessage];
[Loading stopLoading];
[self.navigationController popViewControllerAnimated:YES];
Please help me out.
Thats because you are trying to call that method on object AppDelegate
However the AppDelegate class does not implement it.
Hence the error. Make sure it is implemented.
Two chances for this issue
You are not declared the showAlert: withMessage: method signature in your #interface
You may be declared it as a instance method, you are calling it using the Class name.
Fixes:
Declare the method signature in your #interface
Either define your method as Class method else call it using your app delegate's instance
My code does a calculation upon a button press in "IBAction" and returns the result in a string as the "message" in "UIAlertView".
else{
NSString *str = [[NSString alloc] initWithFormat:#"You require an average GPA of at least %.2f to achieve your Goal of %#", gpagoal, (NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker selectedRowInComponent:0]]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Nothing is Impossible"
message:str
delegate:self
cancelButtonTitle:#"Good Luck"
otherButtonTitles:#"Tweet",nil];
//show alert
[alert show];
[alert release];
NSLog(#"All Valid");
}
i have a problem of how to pull the "gpagoal" value from the calculation's "IBAction" method.
below is the code for the standalone button for tweeting, which works if i am able to port over the gpagoal value from the other method.
- (IBAction)sendEasyTweet:(id)sender {
// Set up the built-in twitter composition view controller.
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
// i have problem trying to pull the result "gpagoal" from the calculation's "IBAction" method as i dunno how to pull out variable from a method to another method.
NSString *str2 = [[NSString alloc] initWithFormat:#"I need an average GPA of at least %.2f this semester to achieve my Goal of %#", gpagoal, (NSString *)[myPickerDelegate.myGoal objectAtIndex: [myPicker selectedRowInComponent:0]]];
// Set the initial tweet text. See the framework for additional properties that can be set.
[tweetViewController setInitialText:str2];
// Create the completion handler block.
[tweetViewController setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
//NSString *output;
switch (result) {
case TWTweetComposeViewControllerResultCancelled:
// The cancel button was tapped.
//output = #"Tweet cancelled.";
NSLog(#"Tweet cancelled");
break;
case TWTweetComposeViewControllerResultDone:
// The tweet was sent.
//output = #"Tweet done.";
NSLog(#"Tweet done");
break;
default:
break;
}
// Dismiss the tweet composition view controller.
[self dismissModalViewControllerAnimated:YES];
}];
// Present the tweet composition view controller modally.
[self presentModalViewController:tweetViewController animated:YES];
}
You simply need a variable that is available throughout your class
// ViewController.h
...
#interface ViewController : UIViewController {
double gpagoal;
}
Make sure it is properly initialized and updated as needed.
I've got a problem with an UITextView and one of its delegate methods in my navigation based app:
- (BOOL)textView:aView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
I managed to limit the max length of text the user can input using the above method. But I'm using a leaky array for that matter I think.
The problem is:
I want to save the amount of typed characters right in the very moment the user enters the last line of my textview. I then use that value to calculate the string length - which I compare to the textview's content size to set a limit. The code works fine - but since the method it's inside of is updating with every text input, I'm having trouble releasing the array in the right moment.
Here's some code:
if (numLines == 9)
{
if (!numCharsArray)
{
numCharsArray = [[NSMutableArray alloc] initWithCapacity:1]; // Stack trace gives this line 3,3% of the leak.
}
numChars = tView.text.length;
NSNumber *number = [[NSNumber alloc] initWithInteger:numChars]; // This line gets 77,3%.
[numCharsArray addObject:number]; // This line gets the rest, 24,3%.
[number release];
startChars = [[numCharsArray objectAtIndex:0] integerValue];
NSString *lastLine = [[NSString alloc]initWithString:[[tView text] substringFromIndex:startChars]];
CGSize lineSize = [lastLine sizeWithFont:tView.font forWidth:tView.contentSize.width lineBreakMode:UILineBreakModeWordWrap];
[lastLine release];
if (range.length > text.length)
{
return YES;
}
else if (numLines == 9 && lineSize.width >= tView.contentSize.width - 45)
{
return NO;
}
}
else
{
numCharsArray = nil;
/*
if(numCharsArray)
{
[numCharsArray release];
}
*/
}
I tried the out-commented statement above, but that gives me an app crash once I leave the last line of the textview. And as you can see in the code comments - without releasing the array I get a leak.
So how and where do I release that array correctly - keeping it safe while the user is on the last line?
Just replace with
first one
numCharsArray = [NSMutableArray array]; // you do not need to release
//explicitly as its autorelease numberWithInt
second one
NSNumber *number = [NSNumber numberWithInt:numChars]; //autorelease
NSString *lastLine = [[tView text] substringFromIndex:startChars];
This problem is probably not specific to MFMailComposeViewController, but that is where I am having the problem...
I am building the NSString
"myEmailString" for the messageBody of
the MFMailComposeViewController and
storing it in an iVar before
displaying the
MFMailComposeViewController as a
modal view controller.
I pass the string into the MFMailComposeViewController, then present it as a modal view controller.
When the modal view controller is dismissed, my iVar becomes invalid,
and the app crashes when I release the emailString iVar in dealloc
Code below, what am I doing wrong?
-(void)buildEmailMessage {
int mySection;
int myRow;
NSString *buildString = [NSString stringWithFormat:#"<b><p>Ten Essentials Check List</b><br />%#</p>", [myList valueForKey:#"listName"]];
for (mySection = 0; mySection < [[fetchedResultsController sections] count]; mySection ++) {
NSString *sectionName = [NSString stringWithFormat:#"<p><b>%# Group</b></p><ul>", [[[fetchedResultsController sections] objectAtIndex:mySection] name]];
buildString = [buildString stringByAppendingString:sectionName];
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:mySection];
for (myRow = 0; myRow < [sectionInfo numberOfObjects]; myRow ++) {
// Get the managedObject
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:myRow inSection:mySection];
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
//Get the related Item object
Item *item = [managedObject valueForKey:#"item"];
NSString *itemName = [NSString stringWithFormat:#"<li>%#</li>", item.itemName];
buildString = [buildString stringByAppendingString:itemName];
}
buildString = [buildString stringByAppendingString:#"</ul>"];
}
myEmailString = [NSString stringWithString:buildString];
NSLog(#"email string = :\n%#", myEmailString);
[self showPicker];
}
#pragma mark -
#pragma mark Send Mail
-(void)showPicker {
// This code can run on devices running iPhone OS 2.0 or later
// The MFMailComposeViewController class is only available in iPhone OS 3.0 or later.
// So, we must verify the existence of the above class and provide a workaround for devices running
// earlier versions of the iPhone OS.
// We display an email composition interface if MFMailComposeViewController exists and the device can send emails.
// We launch the Mail application on the device, otherwise.
NSLog(#"Checking OS for MFMailComposeViewController");
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
// We must always check whether the current device is configured for sending emails
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
// Displays an email composition interface inside the application. Populates all the Mail fields.
-(void)displayComposerSheet {
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
picker.navigationBar.barStyle = UIBarStyleBlack;
[picker setSubject:#"Here is your gear check list!"];
// Attach an image to the email
NSString *path = [[NSBundle mainBundle] pathForResource:#"Checkmark_icon" ofType:#"png"];
NSData *myData = [NSData dataWithContentsOfFile:path];
[picker addAttachmentData:myData mimeType:#"image/png" fileName:#"Checkmark_icon"];
// Fill out the email body text
//***** NOTE: This is where I pass the value from my iVar *****
// into the MFMailComposeViewController
//
NSString *emailBody = [NSString stringWithString:myEmailString];
[picker setMessageBody:emailBody isHTML:YES];
NSLog (#"DIsplaying Composer Sheet");
[self presentModalViewController:picker animated:YES];
[picker release];
}
// Dismisses the email composition interface when users tap Cancel or Send. Proceeds to update the message field with the result of the operation.
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
//message.hidden = NO;
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
NSLog (#"Result: canceled");
break;
case MFMailComposeResultSaved:
NSLog (#"Result: saved");
break;
case MFMailComposeResultSent:
NSLog (#"Result: sent");
break;
case MFMailComposeResultFailed:
NSLog (#"Result: failed");
break;
default:
NSLog (#"Result: not sent");
break;
}
[self dismissModalViewControllerAnimated:YES];
// ***** NOTE: Line below was added to fix the invalid iVar problem *****
myEmailString = #"";
}
#pragma mark -
#pragma mark Workaround
// Launches the Mail application on the device.
-(void)launchMailAppOnDevice {
NSString *recipients = #"mailto:first#example.com?cc=second#example.com,third#example.com&subject=Here is your gear check list!";
NSString *body = myEmailString;
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}
- (void)dealloc {
[managedObjectContext release];
[fetchedResultsController release];
[tableview release];
[myList release];
[myEmailString release];
[super dealloc];
}
how is your ivar declared? is it declared as a property? in any case, it is not automatically retained for you.
Either you need to do
myEmailString = [[NSString stringWithString:buildString] retain];
or
self.myEmailString = [NSString stringWithString:buildString];
if you have myEmailString declared as
#property (nonatomic, retain) NSString *myEmailString
Think about it: if all ivars were automatically retained for you, then how would you have a variable that you didn't want to retain? That's why it doesn't work that way.
when you are creating the myEmail string in buildEmailMessage you are never retaining the string. Thus after leaving the function it is autoreleased. Your retain count then when dealloc is called will be 0, which will cause the crash. If you want to keep the variable you will need to have the line as follows
myEmailString = [[NSString stringWithString:buildString] retain];
then you can call [myEmailString release] safely
stringWithString: creates a new string and autoreleases it before returning it to you. Unless you retain the returned string, you don't need to release it in your dealloc method.
You should be retaining your string before storing it in your iVar:
myEmailString = [[NSString stringWithString:buildString] retain];
It becomes invalid without this due to it being autoreleased later during the execution of your program. This will also ensure it's still allocated when your destructor is called, preventing release crashing.