Don't mix Any and AnyObject. Currently compiler doesn't complain on mixing them but it causes this runtime error. (luckily!)
fatal error: can't unsafeBitCast between types of different sizes
Yep. This is show-stopper. If you're not sure, just use Any
. Some primitive types such as Int64
doesn't support castring from AnyObject
.
instance method seems to be a syntactic sugar for a free function with self binding.
If you're subclassing an Objective-C class, you must be aware of that OBJC object instance can be CHANGED
after calling super.init
. So, instance variables set before calling the super.init
possibly be lost after
the super.init
executed if the super.init
changes the instance to a new one.
class AAA: SomeOBJCClass {
var bbb = "X"
init() {
bbb = "Y"
super.init()
// What is value of `bbb` at here?
}
}
You may expect bbb
to be "Y"
, but in practice, it possibly be "X"
because OBJC runtime can replace instance object in its initialiser. If super.init
replaces its instance, then bbb
will stay as "X"
in a new instance. Beware. This is just my guess, and not something proven.
The only way to deal with this is setting all instance variable AFTER calling super.init
. Do not set any
instance variable before calling super.init
. Just treat any variable set before calling super.init
will be
lost.
Effectively, you need to make all object references as optional (or lazy
) because it must have some initial value, and
the only value can be set at first is nil
.
I am not sure that this is same on pure Swift classes. But I don't think so.
func scanLine() -> String {
struct Statics {
static let NL = UInt8(UnicodeScalar("\n"))
static var input_buffer = NSMutableData()
}
while true {
let stdin = NSFileHandle.fileHandleWithStandardInput()
let d1 = stdin.readDataOfLength(1)
let ptr1 = UnsafePointer<UInt8>(d1.bytes)
let v1 = ptr1.memory
if v1 == Statics.NL {
let s2 = NSString(data: Statics.input_buffer, encoding: NSUTF8StringEncoding)
Statics.input_buffer.length = 0
if let s3 = s2 {
return s3
} else {
fatalError("Input is not UTF8 encoded.")
}
} else {
Statics.input_buffer.appendData(d1)
}
}
}
func scanInt() -> Int {
if let i1 = scanLine().toInt() {
return i1
} else {
fatalError("The input is not a valid `Int` expression.")
}
}
func scanMultipleInts() -> [Int] {
let s = scanLine()
let ps = s.componentsSeparatedByString(" ")
let vs = ps.map { (s1:String) -> Int in
if let v1 = s1.toInt() {
return v1
} else {
fatalError("Input has one or more invalid `Int` expression.")
}
}
return vs
}
- If you make a private
@objc
class, compiler will generate a unique name for it to prevent name conflict. So private@objc
classes with same name will not conflict.
There're many reasons to cause compiler segfaults. Here're worksarounds that you can try when you see it.
- Restart Xcode.
- Erase all compilation temp directory and restart Xcode.
- See the log and duplicate the problematic file with another name and content. And erase old file. Rebuild.