oc swift 字符串报错

2016-07-05 14:47:43 CodingFire 阅读数 459

字符串不管是Object-C还是Swift还是Java等等其他的语言,都可以说是重点,虽然不难,但是用到的地方却非常多,几乎都是字符串的处理,这一篇我们就来好好说说字符串:

创建一个可变字符串:

var stringA = "Hello, World!"

创建一个不可变字符串:

let stringB = "Hello, World!"

这里引入一个名词:字面量,上面的两个都是根据字面量创建的字符串,下面用初始化方法来创建。
创建一个初始化字符串:

var stringC = String("Hello, World!")

创建空字符串:

// 使用字符串字面量创建空字符串
var stringD = ""
//""和nil是两码事,前面说过,但是他俩都属于empty,切记
if stringD.isEmpty {
   print( "stringD 是空的" )
} else {
   print( "stringD 不是空的" )
}

// 实例化 String 类来创建空字符串
let stringE = String()

if stringE.isEmpty {
   print( "stringE 是空的" )
} else {
   print( "stringE 不是空的" )
}

//以上,创建的字符串,var为可变(可修改),let为不可变(不可修改),跟前面变量说的是一致的,不论类型,都符合这一特性。

字符串插入:

var varA   = 1
let constA = 2
var varC:Float = 3
//解释下\(varA),不管什么类型,要是插入到前后可以用+或者append(),但是插入到中间就不好插入了,而要把一个变量或者常量插入到字符串,肯定也要转化为字符串,\()的意思就是把括号内的参数转化为字符串,而且这么来拼接字符串更为方便
var stringA = "\(varA) 加 \(constA) 等于 \(varC )"
print( stringA )

字符串拼接:

let strA = "Hello"
let strB = "World"
//拼接用“+”,还可用append
var strC = strA + strB
//var strC = strA.append(strB)

print( strC )

字符串长度:

var str = "Hello World"
获取str长度:str.characters.count

字符串比较:
用“==”表示相等,“!=”表示不等,Object-C用isEqual

检查前缀和后缀:

hasPrefix(prefix: String)
检查字符串是否拥有特定前缀
hasSuffix(suffix: String)
检查字符串是否拥有特定后缀。

//用法如下
var firstStr:String = "Hello,World!"
if firstStr.hasPrefix("Hello") {

}

类型转化:

let string1: String = "100"
let stringForInt: Int? = Int(string1)

最后再说一点:

 var 你好 = "你好世界"
 var 能用汉字 = "z和不算错么"
 print(你好)
 print(能用汉字)
 是的,你没看错,Swift支持使用汉语的命名

到最后,你可能看到还有一些方法没有列出来,对,实在太多了,用法和OC差不多,博主去看了几个方法,去年的方法,在新的Xcode中是报错的,已经被废弃了,Swift的稳定性还是有待提高。不知道往后再更新还会不会再替换,先不写了。

2015-07-30 00:34:06 abc649395594 阅读数 3338

Swift字符

定义

Swift中的字符,与OC有些不同,每一个字符代表了一个可拓展的字母集,可拓展的字母集由若干个(大于等于一个)Unicode标量值表示,这些标量构成了一个可拓展的字母集,也就是一个人类可读的字符。

Unicode标量

一个Unicode标量占据21个比特位,一般格式为“U+xxxx”,这个解释有点抽象,其实我们通常理解的一个字母,也可以用一个Unicode标量来表示,比如字母’a’可以表示为”U+0061”。

刚刚说到,一个字符由若干个Unicode标量表示,比如以下这个例子:

let combine1 = "\u{1112}"
let combine2 = "\u{1112}\u{1161}"
let combine3 = "\u{1112}\u{1161}\u{11AB}"

println("combine1 = \(combine1)")
println("combine2 = \(combine2)")
println("combine3 = \(combine3)")

输出结果是

combine1 = ᄒ
combine2 = 하
combine3 = 한

可见,对于一个字符,并不一定是由一个Unicode标量构成的。比如“한”。

字符类型推导

刚刚的例子中,我们定义了三个常量,combine0,,combine1,combine2,他们被推导为什么类型呢?答案是String类型而不是Character类型,个人猜测是Swfit的宽类型优先导致的。这里通过简单的代码验证一下:

var combine0 = "\u{1112}"
var combine1:Character = "\u{1112}"

combine0 += "abc" //正确
combine1 += "abc" //编译错误:无法将String类型与Character类型变量拼接

字符拼接

在初始化字符类型常量或变量时,Swift会自动把能够拼接的Unicode标量拼接成一个人类可读字符,如果不能拼接,将生成一个由多个字符所组成的字符串。把这个值赋给一个已经标注为Character类型的变量会导致编译错误。

var string = "\u{1112}\u{10FFFF}" //正确,string变量被推导为String类型
var c:Character = "\u{1112}\u{10FFFF}" //错误,无法赋值给Character类型变量

Swift字符串

定义

Swift中的字符串由若干个字符构成。

字符串初始化

一共有两种方式可以进行字符串初始化,代码如下:

var emptyString1 = ""
var emptyString2 = String()

这样就创建了一个空字符串,可以用字符串的isEmpty属性来检验:

if emptyString1.isEmpty{
    println("emptyString1 is empty")
}
if emptyString2.isEmpty{
    println("emptyString2 is empty")
}

输出结果是:

emptyString1 is empty
emptyString2 is empty

字符串拼接

字符串之间可以相加,等号左侧必须是变量,不能是常量。
字符串变量还可以调用append方法连接其他字符。需要注意的是,append方法只能连接字符,不能连接字符串。

var combine1 = "\u{1112}"
let combine2 = "\u{1112}\u{1161}"

combine1 += combine2 //正确
combine2 += combine1 //错误

var char:Character = "a"
combine1.append(char) //正确
combine1.append("a") //即使写成这样也会报错,原因不明,可能是推导为String类型了

字符串计数

由于一个字符由若干个Unicode标量组成,所以无法使用字符串大小除以单个字符串大小来计算字符串长度。可以利用count方法来计算字符串长度:

let stringValue1 = "Hello, world"
let stringValue2 = "\u{65}\u{301}"
println("string1 length = \(count(stringValue1))")
println("string2 length = \(count(stringValue2))")
println("string2 = \(stringValue2)")

之前说过字符的自动拼接,所以运行结果如下:

string1 length = 12
string2 length = 1
string2 = é

字符串内插

这个类似于OC中的NSString stringWithFormat方法。可以通过已有字符串或数字等其他变量构建一个新的字符串,通过一个例子演示一下:

var number = 3
var time = 2
var setence = "\(number)的 \(time)倍是 \(number * time)"
println("setence = \(setence)")

对应到OC的方法,就相当于用”\()”替换了”%@”。
需要注意的是,内插的表达式中不能直接包含双引号、单引号或者反斜杠。

字符串比较

通过 == 和 != 运算符来比较字符串是否相等

比较特殊的一点是,swift在比较两个字符串时,并不会逐一比较每个Unicode标量是否相等,而是会根据字符串的实际语义来比较。所以在下面的例子中,比较结果需要特别留心一下:

var compare1 = "caf\u{E9}" //\u{E9}是带声调的e,形如é
var compare2 = "caf\u{65}\u{301}" //这是字母e加上声调合成的é
if compare1 == compare2{
    //它们依然是相等的
    println("\(compare1) is equal to \(compare2)")
}

var compare3 = "\u{41}" //拉丁字母A
var compare4 = "\u{0410}" //斯拉夫字母A
if compare3 != compare4{
    //虽然表现相同,但实际语义不同,所以字符串依然不同
    println("\(compare3) is not equal to \(compare4)")
}

运行结果如下:

café is equal to café
A is not equal to А

字符串前后缀

字符串有hasPrefix和hasSuffix方法,用于判断这个字符串是否包含某个前(后)缀,返回一个Bool类型值。注意这两个方法是区分大小写的

var preFixAndSuffix = "Hello World"
if preFixAndSuffix.hasPrefix("H"){
    println("\(preFixAndSuffix) has prefix \"H\"")
}
if preFixAndSuffix.hasPrefix("h"){
    println("\(preFixAndSuffix) has prefix \"h\"")
}
if preFixAndSuffix.hasSuffix("rld"){
    println("\(preFixAndSuffix) has suffix \"rld\"")
}
if preFixAndSuffix.hasSuffix("rldd"){
    println("\(preFixAndSuffix) has suffix \"rldd\"")
}

输出结果:

Hello World has prefix "H"
Hello World has suffix "rld"

附录

查看完整专栏——《Swift轻松入门》

【Swift入门(一)——基本语法】
【Swift入门(二)——字符与字符串】
【Swift入门(三)——元组(Tuple)】
【Swift入门(四)——可选类型(Optionals)与断言(Assert)】
【Swift入门(五)——数组(Array)】
【Swift入门(六)——字典(Dictionary)】
【Swift入门(七)——结构体(Struct)】
【Swift入门(八)——功能强大的求余运算符】
【Swift入门(九)——String与Int、Double、Float等数字相互转换】
【Swift入门(十)——循环引用、弱引用和无主引用】
【Swift入门(十一)——类型转换与is、as操作】
【Swift入门(十二)——利用Extension添加逆序输出字符串方法】

2016-10-30 21:51:07 andanlan 阅读数 762

一、OC中的字符串

  1. 引用类型

    在Object-C中,使用NSString和NSMutableString这两个类对字符串进行操作,一个字符串对象会被指针所引用。

    一般情况下,使用一个旧的字符串对象对一个新声明的字符串对象进行赋值,其实就是新的指针指向同一个字符串对象,也就是指针的拷贝,并没有生成新的字符串。只有对一个可变字符串对象进行拷贝,或者对任意字符串对象进行可变拷贝时才会生成一个新对象。

    同样的在函数、方法传值时,也是指针的传递,操作的都是同一份对象。

  2. 可变与不可变字符串

    NSString类型的对象是不可变字符串,NSString一旦被实例化,就不能再改变内容和长度。

    NSMutableString类型的对象是可变字符串,它可以进行拼接、移除、插入等操作。

  3. 常用字符串操作

  • 新建字符串
// 创建一个空字符串
NSString *str1 = [NSString string];
NSString *str2 = @"";
    
// 创建一个非空串
NSString *str3 = @"我是一个字符串";
  • 是否空串
NSString *name = @"";
if (name.length == 0) {
    NSLog(@"名字是个空字符串");
} else {
    NSLog(@"名字不是个空字符串");
}
  • 长度
name = @"Alean";
NSInteger nameLength = name.length;
NSLog(@"姓名长度:%zd个字符", nameLength);
  • 是否相同
NSString *name2 = @"Alean";
if ([name isEqualToString:name2]) {
    NSLog(@"姓名相同");
} else {
    NSLog(@"姓名不同");
}
  • 大小写转换
NSString *upperName = name.uppercaseString;
NSString *lowerName = name.lowercaseString;
NSLog(@"姓名大写:%@ \n姓名小写:%@", upperName, lowerName);
  • 开头
NSString *prefix = @"Ale";
if ([name hasPrefix:prefix]) {
    NSLog(@"%@是以%@开头的", name, prefix);
} else {
    NSLog(@"%@不是以%@开头的", name, prefix);
}
  • 结尾
NSString *suffix = @"na";
if ([name hasSuffix:suffix]) {
    NSLog(@"%@是以%@结尾的", name, suffix);
} else {
    NSLog(@"%@不是以%@结尾的", name, suffix);
}
  • 从头截取子串
NSInteger indexTo = 2;
NSString *subNameTo = [name substringToIndex:indexTo];
NSLog(@"%@从开头截取%@个字符的子串%@", name, @(indexTo), subNameTo);
  • 从指定位置截取子串
NSInteger indexFrom = 3;
NSString *subNameFrom = [name substringFromIndex:indexFrom];
NSLog(@"%@从第%@个字符到结束的子串%@", name, @(indexFrom), subNameFrom);
  • 指定区间子串
NSRange range = NSMakeRange(1, 2);
NSString *subNameRange = [name substringWithRange:range];
NSLog(@"%@从第%zd个字符截取长度为%zd的子串为%@", name, range.location, range.length, subNameRange);
  • 拼接
NSString *all = [name stringByAppendingString:name2];
NSLog(@"%@拼接%@的结果是:%@", name, name2, all);

二、swift中的字符串

  1. 引用类型

    Swift中,String类型对象一个实际的值,使用旧的String对象对新定义的String赋值,实际创建了一个相等的新值。

    同样,函数传参时,也是传递的实际值,并且创建了一个新的字符串,函数内的操作不会改变原有的String对象。

  2. 可变与不可变字符串

    Swift中可变字符串使用var修饰,let用来修饰不可变字符串。

  3. 常用字符串操作

  • 创建一个空字符串
let emptyStr1 = ""
let emptyStr2 = String()
  • 创建字符串常量
let nameConst = "Jack"
  • 创建字符串变量
var nameVariable = "xiaoming"
nameVariable = "xiaogang"
  • 是否空串
var name = ""
if name.isEmpty {
    print("名字是个空字符串")
} else {
    print("名字叫:\(name)")
}

// 长度
name = “Alean”
let nameLength = name.characters.count
print(“姓名长度:(nameLength)个字符”)

  • 是否相同
let name2 = "Alean"
if name == name2 {
    print("姓名相同")
} else {
    print("姓名不同")
}
  • 大小写转换
let upperName = name.uppercased()
let lowerName = name.lowercased()
print("姓名大写:\(upperName) \n姓名小写:\(lowerName)")
  • 开头
let prefix = "Ale"
if name.hasPrefix(prefix) {
    print("\(name)是以\(prefix)开头的")
} else {
    print("\(name)不是以\(prefix)开头的")
}
  • 结尾
let suffix = "na"
if name.hasSuffix(suffix) {
    print("\(name)是以\(suffix)结尾的")
} else {
    print("\(name)不是以\(suffix)结尾的")
}
  • 从头截取子串
let indexTo = 2
let subIndexTo = name.index(name.startIndex, offsetBy: indexTo)
let subNameTo = name.substring(to: subIndexTo)
print("\(name)从开头截取\(indexTo)个字符的子串\(subNameTo)")
  • 从指定位置截取子串
let indexFrom = -2
let fromIndexFrom = name.characters.count + indexFrom
let subIndexFrom = name.index(name.endIndex, offsetBy: indexFrom)
let subNameFrom = name.substring(from: subIndexFrom)
print("\(name)从第\(fromIndexFrom)个字符到结束的子串\(subNameFrom)")
  • 指定区间子串
let subFormIndex = 1
let subLength = 2
let rangeStartIndex = name.index(name.startIndex, offsetBy: subFormIndex)
let rangeLengthIndex = name.index(name.startIndex, offsetBy: subFormIndex + subLength)
let range = Range(uncheckedBounds: (lower: rangeStartIndex, upper: rangeLengthIndex))
let subNameRange = name.substring(with: range)
print("\(name)从第\(subFormIndex)个字符截取长度为\(subLength)的子串为\(subNameRange)")
  • 拼接
let all = name + name2
print("\(name)拼接\(name2)的结果是:\(all)")
2016-07-30 22:41:09 chendehao001 阅读数 1598

字符

  • 对比 OC 与 Swift 中字符的区别
char charValue = 'a';//OC当中的字符:
var charValue1:Character = "a" //swift当中的字符:
  • Swift和OC字符不一样
    • 1.Swift是用双引号
    • 2.Swift中的字符类型和OC中的也不一样
      • OC中的字符占一个字节,因为它只包含ASCII表中的字符
      • Swift中的字符除了可以存储ASCII表中的字符还可以存储unicode字符.
      • OC的字符是遵守ASCII标准的,
      • Swift的字符是遵守unicode标准, 所以可以存放世界上所有国家语言的字符(大部分)
char charValue = '豪'; //OC当中:错误
var charValue2:Character = "豪" //swift当中: 正确
  • 注意: 双引号中只能放一个字符, 如下是错误写法
var charValue3:Character = "ab" // 直接报错

字符串

  • C OC Swift三种语法的对比较
//C: 
char *stringValue = "ab";
char stringArr = "ab";
//OC:
NSString *stringValue = "ab";
//Swift
var stringValue1 = "ab"
  • C语言中的字符串是以\0结尾的, 例如:
char *stringValue = "abc\0bcd";
printf("%s", stringValue);
//输出结果: abc
  • OC语言中的字符串也是以\0结尾的, 例如:
NSString *stringValue = @"abc\0bcd";
NSLog(@"%@", stringValue);
  • swift当中的字符串和C语言/OC语言中的字符串是不一样的
var stringValue = "abc\0bcd"
print(stringValue)
//输入结果: abcbcd
字符串常用方法
  • 计算字符串长度:
//C:
char *stringValue = "CD豪";
printf("%tu", strlen(stringValue));
//输出结果:5
//OC:
NSString *stringValue = @"CD豪";
NSLog(@"%tu", stringValue.length);
//输出结果:3    以UTF16计算
//swift:
var stringValue1 = "CD豪"
print(stringValue1.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
//输出结果:5  和C语言一样计算字节数
  • 字符串拼接
//C:
char str1[] = "abc";
char *str2 = "bcd";
char *str = strcat(str1, str2);
printf("%s",str);
//输出结果: abcbcd
//OC:
NSMutableString *str1 = [NSMutableString stringWithString:@"abc"];
NSString *str2 = @"bcd";
[str1 appendString:str2];
NSLog(@"%@", str1);
//输出结果: abcbcd
//swift:
var str1 = "chen";
var str2 = "dehao";
var str = str1 + str2;
print(str)
//输出结果:chendehao
  • 格式化字符串
//OC:
NSString *str =
[NSMutableString
stringWithFormat:@"http://blog.csdn.net/chendehao001/pic/%tu.png", @10];
NSLog(@"%@", str);
//输入结果: http://blog.csdn.net/chendehao001/pic/10.png
//swift:
var index = 10
var str3 = "http://blog.csdn.net/chendehao001/pic/\(index).png"
print(str3)
//输入结果: http://blog.csdn.net/chendehao001/pic/10.png
  • 字符串比较:
//oc:
NSString *str1 = @"abc";
NSString *str2 = @"abc";
if ([str1 compare:str2] == NSOrderedSame){
    NSLog(@"相等");
}else{
    NSLog(@"不相等");
}
//输出结果:相等
// oc
NSString *str1 = @"abc";
NSString *str2 = @"abc";
if ([str1 isEqualToString:str2]){
    NSLog(@"相等");
}else{
    NSLog(@"不相等");
}
//输出结果:相等
//Swift:(== / != / >= / <=), 和C语言的strcmp一样是逐个比较
var str4 = "abc";
var str5 = "abc";
if str4 == str5{
    print("相等");
}else{
    print("不相等");
}
//输出结果:相等
var str6 = "abd";
var str7 = "abc";
if str6 >= str7{
    print("大于等于");
}else{
    print("不大于等于");
}
//输出结果: 大于等于
  • 判断前后缀
//OC:
NSString *str = @"http://blog.csdn.net/chendehao001";
if ([str hasPrefix:@"http"]) {
    NSLog(@"是url");
}
if ([str hasSuffix:@"chendehao001"]) {
    NSLog(@"是顶级域名");
}
//输出结果: 
//是url
//是顶级域名
//Swift:
var str8 = "http://blog.csdn.net/chendehao001"
if str8.hasPrefix("http") {
    print("是url");
}
if str8.hasSuffix("chendehao001") {
print("是顶级域名");
}
//输出结果: 
//是url
//是顶级域名
  • 大小写转换
//OC:
NSString *str = @"abc.txt";
NSLog(@"%@", [str uppercaseString]);
NSLog(@"%@", [str lowercaseString]);
//输出结果: ABC.TXT
//abc.txt
//Swift:
var str9 = "abc.txt";
print(str9.uppercaseString)
print(str9.lowercaseString)
//输出结果: ABC.TXT
//abc.txt
  • 转换为基本数据类型
//OC:
NSString *str = @"250";
NSInteger number = [str integerValue];
NSLog(@"%tu", number);
//输出结果: 250
// swift
//如果str不能转换为整数, 那么可选类型返回nil
var str10 = "250"
//str10 = "250sb" 不能转换所以可能为nil
var number:Int? = Int(str10)
if number != nil{
    //以前的版本println会自动拆包, 现在的不会
    print(number!)
}

2019-05-14 09:26:45 u014599371 阅读数 2154

Swift的字符串类型与Foundation的NSString类连接。Foundation还扩展了字符串来公开由NSString定义的方法。这意味着,如果您导入Foundation,您可以在字符串中访问这些NSString方法,而不需要进行强制转换。

单行字符串

let someString = "Some stirng"

多行文本

多行文本使用 """ 内容 """ 没错,就是三个引号开头,三个引号结尾。
多行字符串文字包含了它的起始引号和结束引号之间的所有行


let lyric = """
那是你的眼神,明亮又美丽
啊啊啊~~~
"""
print(lyric)

结果:
那是你的眼神,明亮又美丽
啊啊啊~~~

好吧,这个我一开始以为只是在格式上可以写成多行,没想到结果就是多行,效果等同于\n,而且这样写法更加方便。
还有就是当我们想在多行文本中想控制某行不换行,可以选择在某行的末尾写上 \ 那么下一行就不会换行了

let lyric = """
那是你的眼神,明亮又美丽\
啊啊啊~~~
"""

结果:
那是你的眼神,明亮又美丽啊啊啊~~~

在多行文本中,我们可以在结束引号的前面设定空格,来限定整段文本的缩进:

let lyric = """
  那是你的眼神,明亮又美丽
  啊啊啊~~~

  """

上面例子中,我们在最后"""前设定了2个空格,那么之前的文本必须都是缩进2个空格如果你这样写:

let lyric = """
那是你的眼神,明亮又美丽
啊啊啊~~~

  """

你会发现会报错Insufficient indentation of line in multi-line string literal 多行字符串文字的行缩不足

字符串中特殊字符

\(反斜杠)

let test = "====\\===="
结果:
====\====

\t(水平选项卡)

let test = "\t1\t2\t3"
结果:
    1   2   3

\n(换行符)

let test = "\n1\n2\n3"
结果:

1
2
3

\r(回车)

let test = "\r1\r2\r3"
结果:

1
2
3

从结果来看,\r和\n似乎没有区别,但既然存在即表示肯定是有区别的

'\r'是回车,\r 使光标到行首. '\n'是换行,\n 使光标下移一格,通常敲一个回车键,即是回车,又是换行(\r\n)。Unix中每行结尾只有“<换行>”,即“\n”;Windows中每行结尾是“<换行><回车>”,即“\n\r”;Mac中每行结尾是“<回车>”

一般遇到的情况是在解析Json字符串,网页数据,文件信息的时候会出现不同的应对.

"(双引号)

let test = "\"认识自己的无知是认识世界的最可靠的方法。——《随笔集》\""
结果:
"认识自己的无知是认识世界的最可靠的方法。——《随笔集》"

'(单引号)

let test = "\'曦\'"
结果:
'曦'

Unicode 字符就直接采用官网的了

let dollarSign = "\u{24}"        // $,  Unicode scalar U+0024
let blackHeart = "\u{2665}"      // ♥,  Unicode scalar U+2665
let sparklingHeart = "\u{1F496}" // ?, Unicode scalar U+1F496

结果:
$ ♥ ?

空字符串

我们来看一下如果定义一个空字符串:

var emptyString = ""
或者
var emptyString = String()

判断字符串是否为空:

isEmpty 方法

var emptyString = ""

if emptyString.isEmpty {
  print("emptyStirng is empty")
}

字符串可变性

var variableString = "Horse"
variableString += " and carriage"

结果:
variableStrin:Horse and carriage
let constantString = "Highlander"
constantString += " and another Highlander"
发生错误。
Left side of mutating operator isn't mutable: 'constantString' is a 'let' constant
变异操作符的左侧是不可改变的:“常量字符串”是一个“let”常量

简单来说就是variableString 是变量,可以通过+操作符来追加字符串, constantString 为常量,不可修改。

这个我不得不吐槽一下,官网的这个解释,不就是常量不可修改嘛,说什么可变性。

字符串是值类型

If you create a new String value, that String value is copied when it’s passed to a function or method, or when it’s assigned to a constant or variable. In each case, a new copy of the existing String value is created, and the new copy is passed or assigned, not the original version.
如果您创建一个新的字符串值,那么当它传递给一个函数或方法时,或者当它被分配给一个常量或变量时,该字符串值将被复制。
在不同情况下,都会创建一个现有字符串值的新副本,并分配新副本,而不是原始版本。

Swift’s copy-by-default String behavior ensures that when a function or method passes you a String value, it’s clear that you own that exact String value, regardless of where it came from. You can be confident that the string you are passed won’t be modified unless you modify it yourself.
Swift的 copy-by-default 行为可以确保当函数或方法传递给你一个字符串值时,不管它是从哪里来的,你都能清楚地知道你的值是什么。您可以确信,您所传递的字符串不会被修改,除非您自己修改它。

Behind the scenes, Swift’s compiler optimizes string usage so that actual copying takes place only when absolutely necessary. This means you always get great performance when working with strings as value types.
在后台,Swift的编译器优化了字符串的使用,所以只有在绝对必要的情况下才会进行实际的复制。这意味着在使用字符串作为值类型时,您总是获得很好的性能。

这个就有别于OC了,OC中有明确的分为NSString(不可变)和NSMutableString(可变),swift中只有这么一种了,通过对此的优化更加确保了数据的安全。

字符

定义一个字符(Character)类型的常量charA

let charA:Character = "A"
print("charA:\(charA)")
结果:
charA:A

您可以通过使用for循环遍历字符串来访问字符串的单个字符值:

let character = ""
let str = "窗外的麻雀"
for character in str {
    print(character)
}
结果:
窗
外
的
麻
雀

创建一个字符值数组:

let catCharacters: [Character] = ["C", "a", "t", "!", "?"]
print(catCharacters)
结果:
["C", "a", "t", "!", "?"]

可以通过String(字符数组)来将字符数组转换成字符串

let catCharacters: [Character] = ["C", "a", "t", "!", "?"]
let catString = String(catCharacters)
print(catString)
结果:
Cat!?

字符串的连接:
我们可以用 + 操作符连接字符串

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2
print("welcome \(welcome)")
结果:
welcome hello there

除了+操作符之外,还有append方法

let string1 = "hello"
let string2 = " there"
var welcome = string1 + string2

let exclamationMark: Character = "!"
welcome.append(exclamationMark)
print("welcome \(welcome)")
结果:
welcome hello there!

append是将字符串追加到原本字符串的末尾

以上的添加方法是通过连接两个字符串的值形成一个新的值
而在有的时候我们其实只需要临时的展示而已,不需要去改变原有的值,那么这个时候其实只需要这样做就可以了:

let badStart = """
one
two
"""
let end = """
three
"""
print(badStart + end)
print(badStart)

结果:
one
twothree

one
two

可以看到我们在输出print中将其相加,虽然显示了,但其实badStart的结果并没有改变。

字符串的插值

在使用字符串的时候,我们可能需要利用其它的变量来改变我们目前的数据,而这个时候我们可以使用 \(value) 来将我们需要的值

let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"

结果:
3 times 2.5 is 7.5

当然了,这个也不是万能,它是不能将未转义的\直接放置于()中的:
错误的方式

let message = "\(\)"
print(message)

let message = "\(\')"
print(message)

正确的方式是这样的:

let message = "\("\'")"
print(message)
结果:
'

计算字符的个数

计算字符的个数是我们比较常用的方法count

let unusualMenagerie = "Koala ?, Snail ?, Penguin ?, Dromedary ?"
print("unusualMenagerie has \(unusualMenagerie.count) characters")
结果:
unusualMenagerie has 40 characters

当然了,count并不总是能够计算清楚我们的字符个数:

var word = "cafe"
print("the number of characters in \(word) is \(word.count)")
这个计算结果是4
word += "\u{301}"  
print("the number of characters in \(word) is \(word.count)")
当我们计算的会发现结果仍然是4

这是为什么呢?
因为swift中的字符串运用了扩展字元簇(Extended Grapheme Clusters)

扩展字元簇可以由多个Unicode标量组成。
这意味着不同的字符和相同字符的不同表示可以要求不同的内存数量来存储。
因此,Swift中的字符不会在字符串的表示中占用相同数量的内存。

结果,字符串中的字符数无法计算.
如果您使用的是特别长的字符串值,请注意,count属性必须遍历整个字符串中的Unicode标量,以便确定该字符串的字符。

比如:字母é可以是一个单独的Unicode scalar:U+00E9,也可以是多个纯量的组合:U+0065U+0301 (其中U+0065就是字母e)。在Swift中,这两种情况都认为是一个字符,因此获取字符串长度的时候(用全局函数count()),返回的值是相同的,这意味着字符串的改变并不一定意味着其长度发生变化。

count属性返回的字符数并不总是与包含相同字符的NSString的长度属性相同。
NSString的length是基于字符串的utf-16表示的16位代码单元的数量,而不是字符串中Unicode扩展的grapheme集群的数量

字符串索引

let greeting = "Guten Tag!"
//字符串中的开头字母
print(greeting[greeting.startIndex])
//index()表示获取字符串中某个下标的元素,before意味着获取最后一位的之前的下标
//endIndex表示字符串最后一位
print(greeting[greeting.index(before: greeting.endIndex)])
//after表示获取某个下标之后
print(greeting[greeting.index(after: greeting.startIndex)])
//这个方法表示以startIndex下标开始,偏移7位
let index = greeting.index(greeting.startIndex, offsetBy: 7)
print(greeting[index])
结果:
G
!
u
a

使用索引属性来访问字符串中各个字符的所有索引:

for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "")
}
结果:
G u t e n   T a g ! 

这里的terminator是print方法中参数,默认是添加换行符\n

let greeting = "Guten Tag!"

for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "\n")
}
G 
u 
t 
e 
n 
  
T 
a 
g 
! 

感觉跟print没有区别吧。

let greeting = "Guten Tag!"

for index in greeting.indices {
    print("\(greeting[index]) ", terminator: "1")
}
结果:
G 1u 1t 1e 1n 1  1T 1a 1g 1! 1

这个其实就是在每次获取单个字符之后添加一个字符。

字符串的插入和删除

插入

insert(value,at:index)

var welcome = "hello"
welcome.insert("!", at:welcome.endIndex)
print(welcome)
结果:
hello!

var welcome = "hello!"
welcome.insert(contentsOf: " world", at: welcome.index(before: welcome.endIndex))
print(welcome)
结果:
hello world!

移除

remove(at:index)
根据下标进行移除

removeSubrange
根据提供的范围进行移除

var welcome = "hello!"
welcome.remove(at: welcome.index(before: welcome.endIndex))
print(welcome)
结果:
hello

var welcome = "hello world"
//空格的位置 - 末尾
let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
welcome.removeSubrange(range)
print(welcome)
结果:
hello 

后续更新,敬请期待...



作者:如风如花不如你
链接:https://www.jianshu.com/p/87c29641db61
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。