54

I'm writing a property list to be in the resources bundle of my application. An NSString object in the plist needs to have line-breaks in it. I tried \n, but that doesn't work. What do I do to have newlines in my string in the plist?

Thanks.

Jonathan Sterling
  • 18,320
  • 12
  • 67
  • 79

5 Answers5

122

If you're editing the plist in Xcode's inbuild plist editor, you can press option-return to enter a line break within a string value.

Dave Addey
  • 1,356
  • 1
  • 8
  • 3
  • adding line breaks manually may work if the files are static and few. But not really a "true" (code based) solution. The only code based solutions are those from Mihai Damian and justAfix. – aloha Feb 24 '12 at 10:25
  • This seems to work just fine for me in iOS 7 with a UILabel, however it doesn't seem to be working with iOS 6. I'm using `option+return` in the plist, but my UILabel in iOS 6 doesn't have the line break. Is anyone else seeing this behavior? – njkremer Dec 09 '13 at 22:23
  • I didn't find option-return key in my keyboard. I clicked the row in plist file and pressed the Option+Enter key on my keyboard but nothing appears to change. What should i do ? – Nuibb Oct 27 '16 at 12:19
  • Great answer. Saved me a lot of time. Thanks !! – Sushree Swagatika Aug 23 '17 at 07:50
37

I found a simpler solution:

NSString *newString = [oldString stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"];

It seems the string reader escapes all characters that need to be escaped such that the text from the plist is rendered verbatim. This code effectively drops the extra escape.

Mihai Damian
  • 11,193
  • 11
  • 59
  • 81
23

Edit your plist using a text editor instead of Xcode's plist editor. Then you simply put line breaks in your strings directly:

<string>foo
bar</string>
Jon Reid
  • 20,545
  • 2
  • 64
  • 95
4

a little late, but i discovered the same issue and i also discovered a fix or workaround. so for anyone who stumbles on this will get an answer :)

so the problem is when you read a string from a file, \n will be 2 characters unlike in xcode the compiler will recognize \n as one.

so i extended the NSString class like this:

"NSString+newLineToString.h":

@interface NSString(newLineToString)    
-(NSString*)newLineToString;   
@end

"NSString+newLineToString.m":

#import "NSString+newLineToString.h"

@implementation NSString(newLineToString)

-(NSString*)newLineToString
{
    NSString *string = @"";
    NSArray *chunks = [self componentsSeparatedByString: @"\\n"];

    for(id str in chunks){
        if([string isEqualToString:@""]){
            string = [NSString stringWithFormat:@"%@",str];
        }else{
            string = [NSString stringWithFormat:@"%@\n%@",string,str];
        }

    }
    return string;
} 
@end

How to use it:

rootDict = [[NSDictionary alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"yourFile" ofType:@"plist"]];

NSString *string = [[rootDict objectForKey:@"myString"] newLineToString];

its quick and dirty, be aware that \\n in your file will not be recognize as \n so if you need to write \n on text you have to modify the method :)

justAfix
  • 41
  • 1
  • superb fix. And interesting observation. Saved me days of effort. Its essentially same as Mihai Damian's solution but this one really explains the reason behind it. – aloha Feb 24 '12 at 10:17
0

This is how I do loading my plist in Swift 2.0:

plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>STRING_TEXT</key>
    <string>This string contains an emoji and a double underscore!__The double undescore is converted when the plist item is read.</string>
</dict>
</plist>

Swift 2.0:

import Foundation

var stringTextRaw = plistValueForString(keyname:"STRING_TEXT")
var stringText = stringTextRaw.stringByReplacingOccurrencesOfString("__", withString: "\r")



func plistValueForString(keyname keyname:String) -> String {

  let filePath = NSBundle.mainBundle().pathForResource("StringsToUse", ofType:"plist")
  let plist = NSDictionary(contentsOfFile:filePath!)

  let value:String = plist?.objectForKey(keyname) as! String
  return value
}

So I first get the stored plist value into the xxRaw variable and then search for __ "double undescore" and replace that with "\r" ie carriage return for a newline and this is placed into the final variable.

sakumatto
  • 157
  • 1
  • 9