有时我将变量定义为NSArray/String/URL
时会出错,通常可以通过将其更改为NSMutableArray/String/URL
来解决。
他们之间有什么区别?人们说你不能改变NSString
的价值,但为什么不改变,因为我把它定义为var
的变量?
请使用Swift 2代码进行说明。
这里的代码示例:
enum Router: URLRequestConvertible {
static let baseURLString = "https://api.500px.com/v1"
static let consumerKey = "My_Key"
case PopularPhotos(Int)
case PhotoInfo(Int, ImageSize)
case Comments(Int, Int)
var URLRequest: NSURLRequest {
//Error: Type does not conform to protocol 'URLRequestConvertible' with Alamofire.
//I solved this problem by changing it to NSMutableRequest.
let (path, parameters) : (String, [String: AnyObject]) = {
switch self {
//3 cases.
}
}()
let URL = NSURL(string: Router.baseURLString)
let URLRequest = NSURLRequest(URL: URL!.URLByAppendingPathComponent(path))
let encoding = Alamofire.ParameterEncoding.URL
return encoding.encode(URLRequest, parameters: parameters).0
}
}
答案 0 :(得分:3)
NS类型来自Cocoa(有些人会说Objective-c,但实际上它们并不存在于Objective-C中,所以它们是在NextStep库中创建的,然后Apple在购买NextStep之后在Cocoa中使用 - >因此NS前缀)
NSArray / String / URL类似于let myVar =“aString”
和
NSMutableArray / String / URL类似于var myVar =“aString”
第一个不能改变后,它设置第二个即可。为什么使用Cocoa / Objective-C类型而不是本机Swift类型?
编辑(见评论)
在Swift中你可以定义一个字符串:var anEmtpyString = String()
或
var anEmtpyString = ""
在第二种情况下,Swift非常聪明,可以推断出类型是String。如果使用'var',则字符串为Mutable,这意味着您可以在之后更改它。所以我可以这样做:
var myString = "first text"
myString = "another text"
如果您使用'let',则会创建对字符串的引用,也称为Immutable
let myString = "first text"
myString = "another text" // <- the compiler won't accept this !
在这些例子中,我使用了Swift中的原生String类型,它存在于Swift 1.2和2中
我也可以使用Cocoa / Objective类型NSString,NSMutableString,但大部分时间都不需要它。如果您使用的是用Objective-C编写的框架,那么它会很方便。因为你不必从String转换为NSString / NSMutableString,因此对你来说更容易。 (当然可以)
在Objective-C中没有let或var关键字,所以你使用了NSString(for let)和NSMutableString(for var)。
NSArray / NSMutableArray也是如此
PS来自gnasher729的答案更具技术性,并告诉你它是如何在幕后进行的。它与指针有关,指针在Objective-C中非常存在,但在Swift中更加隐藏。如果你来自一个学习指针的背景,它会使事情更清晰,如果不是,我不确定它是否会对你有所帮助。如果您希望我对此进行扩展,请告诉我们。
答案 1 :(得分:1)
一个。
在Objective-C中,许多类型的日常例程都不是内置类型。这意味着它们不是编程语言的一部分。
因此,框架Foundation将类型定义为类,与任何其他类一样。与NSImage
,NSManagedObject
,NSWhatever
等类没有区别。您没有语言级文档。它们被记录为框架的一部分。您可以将它们视为每个其他类,包括子类,类别等等。他们根本没什么特别的。 (你可以完全取代它们,但没有理由这样做。)
乙
在Objective-C中,每个实例对象都在堆上分配(“动态”)。由于NSString
的实例是常见的实例对象,因此您也可以使用它们。此类构造的返回值不是实例对象,而是对实例对象的引用。这意味着包含NSString
实例的所有实例对象都被“引用”处理。
使用“字符串类型”定义变量时,不要定义字符串实例,而是定义字符串的引用:
NSString *referenceToString;
这个引用总是一个变量。在Swift中它看起来像这样:
var string : String;
使用关键字const
定义Objective-C中const的类比。
NSString * const referenceToString;
但是有一个很大的区别:因为你声明的变量是一个引用,所以constness可以与引用或对象相关。在第一种情况下,您无法更改引用,在后一种情况下,您无法更改对象。上述语法表示:对NSString
实例的常量引用。因此,您不能为该引用分配值。 (例如,引用另一个字符串对象。)
这些常量引用在Objective-C中不是很流行,因为在大多数情况下,引用的常量是没有意义的。
字符串 object 本身的常量由字符串对象的类型建模。 NSString
表示常量字符串对象,NSMutableString
表示变量字符串 object 。
因此,如果您想要一个可以变异的刺痛,请使用NSMutableString
而不是NSString
。
NSMutableString *referenceToAMutableString;
NSString *referenceToAnImmutableString;
答案 2 :(得分:0)
有值对象和引用对象。例如,Int和String是值对象,NSNumber和NSString是引用对象。 Swift struct实例是值对象,Swift类实例是引用对象。
对于参考对象,变量不对象。它是对象的引用。因此,“let”变量不能更改,这意味着它引用一个对象而不能使其引用另一个对象。可以更改“var”变量,这意味着可以使其引用不同的对象。但两者都没有对物体本身说什么。无法修改NSArray对象,可以修改NSMutableArray。使用let或var变量来引用对象只意味着变量不能或不能引用不同的变量,它没有说明是否可以修改对象本身。