Strange behavior of Swift
The '!' indicates forced unwrapping of an optional. However it's type is still optional and therefore can be nil.
(You're just telling the compiler that you guarantee it won't become nil.)
A line like...
let v: Int = myVar
...at the end of your code will get you the crash you expect.
Another example is the way outlets are handled. They are typically defined such as:
@IBOutlet weak var detailDescriptionLabel: UILabel!
Before viewDidLoad
is called, it is nil. Again, the '!' is just a promise to the compiler that it won't be used until it contains a valid reference.
Swift / Xcode strange behaviour: Use of undeclared type error shown in case of struct used before declaration
In screen 1 settingsDb
variable is declared in global namespace, in this case order of declaration matters, so all types of top-level declarations must be declared before usage.
If one needs more details, look for "swift top-level", official developer.apple.com blog on this is here
Strange Behaviour in Swift: constant defined with LET but behaving like a variable defined with VAR
This looks like a compiler optimization bug. In the swift language guide it says:
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.
I dug around a little and found that it's possible to get the memory address of a string via str._core._baseAddress
(Note: that's probably supposed to be a private
var in swift's core lib, but it seems to have been overlooked).
If I modify the original code to print the address of str
and match0
/match1
, this is what I get:
+ str address: 0x0000000100006130; match0 address: 0x0000000100006130
+ str address: 0x0000000100511f70; match0 address: 0x0000000100006130
+ str address: 0x0000000100511f70; match0 address: 0x0000000100006130
+ str address: 0x0000000100511f70; match1 address: 0x0000000100511f70
z str address: 0x0000000100511f70; match1 address: 0x0000000100511f70
Notice how the first one prints the same address since no copy needed to be made yet but, once the first str.removeRange(range0)
is called, the addresses change because it copies str
to a new location.
That last one is the problem. From what I can tell, the compiler should have copied str
to a new memory location when str.removeRange(range1)
was called, but it didn't (bug). Since it didn't, str
and match1
still have the same base address so match1
ends up printing "z".
Sounds like it might be bug report time.
Update: Workaround
It looks like an easy workaround to this is to force the compiler to trigger a string copy by calling stringByAppendingString("")
before the second rangeOfString
call:
var str = "+y+z*1.0*sum(A1:A3)"
if let range0 = str.rangeOfString("^\\+|^\\-|^\\*|^\\/", options: NSStringCompareOptions.RegularExpressionSearch){
// ...
}
// Force a string copy by appending an empty string to get around optimization bug
str = str.stringByAppendingString("")
if let range1 = str.rangeOfString("^\\+|^\\-|^\\*|^\\/", options: NSStringCompareOptions.RegularExpressionSearch){
// ...
}
Data ranged subscribe strange behavior
d[5..<8]
returns Data.Slice
– which happens to be Data
. Generally, slices share the indices with their base collection, as documented in Slice
.
One possible reason for this design decision is that it guarantees that subscripting a slice is a O(1) operation (adding an offset for accessing the base collection is not necessarily O(1), e.g. not for strings.)
It is also convenient, as in this example to locate the text after the second occurrence of a character in a string:
let string = "abcdefgabcdefg"
// Find first occurrence of "d":
if let r1 = string.range(of: "d") {
// Find second occurrence of "d":
if let r2 = string[r1.upperBound...].range(of: "d") {
print(string[r2.upperBound...]) // efg
}
}
As a consequence, you must never assume that the indices of a collection are zero-based (unless documented, as for Array.startIndex
). Use startIndex
to get the first index, or first
to get the first element.
Related Topics
In App Purchase on MAC Catalyst Not Working
Hide Header While Collection View Is Loading
Swift Selector with Default Argument
Pause Spritekit Scene When Iad Is Clicked in Swift
Using UIdropinteractiondelegate and Movies
Convenience Failable Initializers Assign Self
Swift: Urlsession.Shared.Datatask Says Status Code 304 = 200
Dynamic Dispatching Protocol Extension Doesn't Work Multiple Targets
Cannot Decode Object of Class (Ampathpopupbutton)'
Navigationlink Doesn't Work with New .Searchable Modifier on Swiftui 3.0
Binary to Hexadecimal in Swift
Custom Radix Columns (+Special Characters)
How to Print Http Request to Console
How to Initialize UIbezierpath to Draw a Circle in Swift