Format not a string literal and no format args?

Discussion in 'iOS Programming' started by larswik, Nov 15, 2011.

  1. larswik macrumors 68000

    Joined:
    Sep 8, 2006
    #1
    I have this code
    Code:
     
        theClientName = clientNameTextField.text;
    
        nameCombind = [nameCombind stringByAppendingFormat:theClientName];//warning on this line of code
        nameCombind = [nameCombind stringByAppendingFormat:@" - "];
    It gives me a warning but the code still works. The bottom line works just fine but the one above it gives me the warning on. The top line of code I am retrieving the string in a TextField and assigning it to an NSString that I set up and an instance variable in the header file.

    stringByAppendingFormat excepts an NSString as an argument. Both lines of code are of NSString?
     
  2. kainjow Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #2
  3. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #3
    You know how you can do something like this?
    Code:
    int a = 1;
    nameCombind = [nameCombind stringByAppendingFormat:"number %d", a];
    
    And it will append "number 1" to the end of nameCombind?

    So what you think would happen if I enter "number %d" into your client name text field? What is your code going to try to do?

    For this reason, you want to be very careful with how you deal with strings entered by a user. You never want to use a string entered by a user as a format string (well may be never, but very rarely).

    In this case, you're not specifying a format string at all, so don't use a method that expects one. Use stringByAppendingString: instead.
     
  4. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #4
    In Cocoa, NSString is a fairly important class, at this point in your progress, it might be a good idea to take a few minutes to examine the available methods and familiarize yourself with them. You do not need to memorize them, the docs will always be close at hand, but read through and understand what the methods do. Also look over NSMutableString, and perhaps NSScanner, because those can come in handy.
     
  5. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #5
    I thought a String was a String like a Char is a Char. Getting text from a textfield and storing it in an NSString object seemed the right way? I am not familiar with 'formal string', I will read up on it. All I am trying to do is ask the user for the Client name, job name and then concatenate it together with the current date and add that as text in a UITableView Cell.

    Jim - I do see what you are saying with the %d if that is added by the user. I am guessing I need to verify that the user inputs valid characters. or maybe there is a different way of concatenating the user entries that I don;t know of yet?

    Code:
    -(void)newBlankTextFields{
        theClientName = clientNameTextField.text;
        theJobName = jobNameTextField.text;
        NSString *nameCombind = @"";
        
        NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
        [dateFormatter setDateFormat:@"MM-dd-yy"];
    
        
        nameCombind = [nameCombind stringByAppendingFormat:[dateFormatter stringFromDate:[NSDate date]]];
        nameCombind = [nameCombind stringByAppendingFormat:@" - "];
        nameCombind = [nameCombind stringByAppendingFormat:theClientName];
        nameCombind = [nameCombind stringByAppendingFormat:@" - "];
        nameCombind = [nameCombind stringByAppendingFormat:theJobName];
        
        NSLog(@"%@", nameCombind); //test ouput
        
        [clientListForTable addObject:nameCombind];
        NSLog(@"the array has %@", clientListForTable);
        [self.tableView reloadData];
        
        //ClientListViewController * clientViewController = [[ClientViewController alloc]init];
       // clientViewController.title=@"Job";
       // [self.navigationController pushViewController:clientViewController animated:YES];
       // [clientViewController release];
        self.tableView.tableHeaderView = NO; //removes the Header file when exiting to hide it
        [dateFormatter release]; // release the date object
    }
    
    Thanks for the help and knowledge!
     
  6. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #6
    NSStrings are not chars or even arrays of chars. It's an object. You cannot make any assumption about the internal structure of the object.
     
  7. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #7
    A format string. Also known as a format specifier. String Format Specifiers

    Format specifiers (I'll use Apple's terminology) are just NSString objects. But they're strings of a particular format.


    Yes, you probably should validate any user input.

    But no, you don't need to validate that the user hasn't entered something like %d. Why? Because you are going to replace all references to stringByAppendingFormat: with what? With stringByAppendingString: so it doesn't matter if a user enters a %.

    Or better yet, in this particularly instance, you might find it is easier and get better performance if you create a NSMutableString and using that class's appendString:. Which method of NSMutableString won't you use? You won't use appendFormat:.
     
  8. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #8
    robbieduncan - I am aware that a Char is not a string. It was a simplification that I thought a char could not be more then a char, thanks.

    Jim - Thanks for the link, I now know what they mean, FORMAT for format specifiers, I get it. A while back I said something like Objective C was so big how do you remember it all. You replied and said you don't but you look it up because you know what you are looking for. I concatenated strings before and did a quick web search and copied the code. "stringByAppendingFormat:". I saw the word 'appending' and new that was what I needed. I did not even think to look at the the word Format and think it should be string. That is my Duhhh moment for the day. Thanks for that clarification!!!

    My teacher just covered strings in Java and said strings are NOT mutable. But if you use the same instance variable name it just creates a new string object. Is there any benefit to using a mutable NSString vs. immutable since it creates a new object anyways?
     
  9. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #9
    OK. I was clarifying as in plain-old C strings are, of course, \0 terminated arrays of characters.

    If you create NSMutableStrings you can append to them (as an example) without creating a new object.
     
  10. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #10
    What do you mean "since it creates a new object anyways"? If you use an NSMutableString, you can modify it without creating a new object. That is the whole point.
     
  11. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #11

    I guess I just don't see the point of the NSMutableString. Since I don't alloc or init I don't worry about about over writing it without releasing it first for a memory leak. It's a local variable so it will be destroyed at the end of the method. If objective c wants to create a couple extra objects for a few milli seconds, that's ok with me :)

    That being said I will start to use the Mutable version since half of my battle in learning is using proper programming techniques.

    Thanks!
     
  12. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #12
    You will care when you notice the performance overhead of creating the objects. If you are in a performance critical loop you'll try and avoid creating temporary objects.
     
  13. admanimal macrumors 68040

    Joined:
    Apr 22, 2005
    #13
    There could also be a scenario where many objects need to have a reference to a single string. If you use an NSString, you will have to update all of the references every time you change the string. With an NSMutableString, you can just modify the string and all of the existing references to it will still be valid.

    I'm not sure how common of a scenario this is, but it is something to consider.
     
  14. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #14
    I converted the the NSString to an NSMutableString and opened up a new problems. They are not the same thing and now I am getting an "Incompatable pointer type init NSMutableString with an expression of type NSString". NSMutableString has a method called appendString.

    I will read through the Doc's more as I adapt to this correct way of doing it.

    Thanks!
     
  15. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #15
    Show us your code.
     
  16. lefooey macrumors member

    Joined:
    Dec 26, 2009
    Location:
    Spokane, WA
    #16
    Seems to me this would be a lot easier:

    Code:
    NSString *nameCombind = [NSString
        stringWithFormat:@"%@ - %@ - %@",
        [dateFormatter stringFromDate:[NSDate date]],
        theClientName,
        theJobName];
    
    The returned string will be autoreleased unless you retain it or are using ARC.
     
  17. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #17
    Jim - The code is above. I just changed this line
    Code:
    NSString *nameCombind = @"";
    to this line
    Code:
    NSMutableString *nameCombind = @"";
    
    lefooey - That looks much easier then mine :) Always learning new things. Still wondering why my NSMutableString is now giving me warning messages?

    Thanks guy!
     
  18. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #18
    Go with lefooey's idea. This is just for your information.

    You need to create an NSMutableString. You cannot use @"" constants, because they're NSString objects, not NSMutableString objects.

    Code:
    NSMutableString *nameCombined = [NSMutableString string];
    
    and then this:
    Code:
    nameCombind = [nameCombind stringByAppendingFormat:[dateFormatter stringFromDate:[NSDate date]]];
    nameCombind = [nameCombind stringByAppendingFormat:@" - "];
    nameCombind = [nameCombind stringByAppendingFormat:theClientName];
    nameCombind = [nameCombind stringByAppendingFormat:@" - "];
    nameCombind = [nameCombind stringByAppendingFormat:theJobName];
    
    becomes this:
    Code:
    [nameCombind appendString:[dateFormatter stringFromDate:[NSDate date]]];
    [nameCombind appendString:@" - "];
    [nameCombind appendString:theClientName];
    [nameCombind appendString:@" - "];
    [nameCombind appendString:theJobName];
    
     
  19. larswik thread starter macrumors 68000

    Joined:
    Sep 8, 2006
    #19
    Thank you for the description. I knew that a local variable needs to be initialized, which is why I did that. I see from your code what is happening and how they are different. I would have never got that some since I thought a string is a string.

    Thanks for taking the time to explain it!
     

Share This Page