Using a negative number or an index equal to or greater than count triggers a runtime error.
使用负数或大于等于count的索引会触发运行时错误。
1
print(emptyDoubles[0])
ClosedRange.swift
An equivalent range must be representable as a closed range. For example, passing an empty range as other triggers a runtime error, because an empty range cannot be represented by a closed range instance.
等效范围必须可以表示为闭合范围。例如,将空范围作为 other 传递会触发运行时错误,因为空范围不能由封闭范围实例表示。
1 2
let emptyRange =0..<0 ClosedRange(emptyRange)
Dictionary.swift
Passing a sequence with duplicate keys to this initializer results in a runtime error. If your sequence might have duplicate keys, use the Dictionary(_:uniquingKeysWith:) initializer instead.
When the additive inverse of a value is unrepresentable in a conforming type, the operation should either trap or return an exceptional value. For example, using the negation operator (prefix -) with Int.min results in a runtime error.
In debug builds (-Onone), the unsafelyUnwrapped property has the same behavior as using the postfix ! operator and triggers a runtime error if the instance is nil.
let optionalInt: Int? =nil optionalInt.unsafelyUnwrapped optionalInt!
Policy.swift
If you have prior knowledge that an AnyObject instance has a particular type, you can use the unconditional downcast operator (as!). Performing an invalid cast triggers a runtime error.
let message = s as!String print("Successful cast to String: \(message)") // Prints "Successful cast to String: This is a bridged string." let badCase = v as!String // Runtime error
Range.swift
An equivalent range must be representable as an instance of Range. For example, passing a closed range with an upper bound of Int.max triggers a runtime error, because the resulting half-open range would require an upper bound of Int.max + 1, which is not representable as
范围边界值越界会触发运行时错误,如设置最大值为Int.max时。
1
Range(0...Int.max)
Always use the slice’s startIndex property instead of assuming that its indices start at a particular value. Attempting to access an element by using an index outside the bounds of the slice’s indices may result in a runtime error, even if that index is valid for the original collection.
// * a single Unicode scalar value, under very limited circumstances: structMyStaticScalar: ExpressibleByUnicodeScalarLiteral { typealiasUnicodeScalarLiteralType=StaticString let value: StaticString init(unicodeScalarLiteralvalue: StaticString) { self.value = value } }
extensionTreeNodewhereT: Equatable { publicfuncsearch(_value: T) -> TreeNode? { var result: TreeNode? forEachDepthFirst { node in if node.value == value { result = node } } return result } }
Options: -V, --version output the version number -h, --help output usage information
Commands: build build the project in a local container create interactively create a Kitura project idt install IBM Cloud Developer Tools init scaffold a bare-bones Kitura project kit print Cocoapods boilerplate for KituraKit run run the project in a local container sdk generate a client SDK from an OpenAPI/Swagger spec help [cmd] display help for [cmd]
publicstructSong: Codable { var title: String var length: Int enumCodingKeys: String, CodingKey { case title ="songTitle" case length ="songLength" } }
publicstructAnimal: Codable { var name: String var age: Int? var isFriendly: Bool var birthday: Date var songs: [Song] }
// 2 嵌套 let baloo =Animal(name: "Baloo", age: 5, isFriendly: true, birthday: Date(), songs: [Song(title: "The Bare Necessities", length: 180)]) let bagheera =Animal(name: "Bagheera", age: nil, isFriendly: true, birthday: Date(), songs: [Song(title: "Jungle's No Place For A Boy", length: 95)])
let list: LinkedList<Int> = { var list =LinkedList<Int>() list.push(3) list.push(2) list.push(1) return list }()
funcprintInReverse<T>(_list: LinkedList<T>) { var current = list.head var stack =Stack<T>() whilelet node = current { stack.push(node.value) current = node.next } whilelet value = stack.pop() { print(value) } }
var testString1 ="h((e))llo(world)()" var testString2 ="(hello world"
funccheckParentheses(_string: String) -> Bool { var stack =Stack<Character>() for character in string { if character =="(" { stack.push(character) } elseif character ==")" { if stack.isEmpty { returnfalse } else { stack.pop() } } } return stack.isEmpty }
1 match found in /Users/derekselander/Library/Developer/Xcode/ DerivedData/Signals-atqcdyprrotlrvdanihoufkwzyqh/Build/Products/Debugiphonesimulator/Signals.app/Signals:
(lldb) help po Evaluate an expression on the current thread. Displays any returned value with formatting controlled by the type's author. Expects 'raw' input (see 'help raw-input'.)
(lldb) help p Evaluate an expression on the current thread. Displays any returned value with LLDB's default formatting. Expects 'raw' input (see 'help raw-input'.)
(lldb) help bt Show the current thread's call stack. Any numeric argument displays at most that many frames. The argument 'all' displays all threads. Expects 'raw' input (see 'help raw-input'.)
Syntax: bt [<digit> | all]
'bt' is an abbreviation for '_regexp-bt' (lldb) help thread backtrace Show thread call stacks. Defaults to the current thread, thread indexes can be specified as arguments. Use the thread-index "all" to see all threads. Use the thread-index "unique" to see threads grouped by unique call stacks.
(lldb) image list (lldb) image list Foundation [ 0] FD4BF3C6-63C9-3A30-BEEA-D39F6F8EEB13 0x0000000107d70000 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/System/Library/Frameworks/Foundation.framework/Foundation
(lldb) frame info frame #0: 0x00000001048e1250 Commons`__34+[UnixSignalHandler sharedHandler]_block_invoke(.block_descriptor=0x00000001048e8230) at UnixSignalHandler.m:72:28
(lldb) image lookup -t __block_literal_5 Best match found in /Users/will/Library/Developer/Xcode/DerivedData/Signals-bgjklehkjddsnxcexztwhrufpsbn/Build/Products/Debug-iphonesimulator/Signals.app/Frameworks/Commons.framework/Commons: id = {0x100000be1}, name = "__block_literal_5", byte-size = 52, decl = UnixSignalHandler.m:127, compiler_type = "struct __block_literal_5 { void *__isa; int __flags; int __reserved; void (*__FuncPtr)(); __block_descriptor_withcopydispose *__descriptor; UnixSignalHandler *const self; siginfo_t *siginfo; int sig; }"
Anyway, we’ll get onto exactly how SwiftUI works soon. For now, the least you need to know is that SwiftUI fixes many problems people had with the old Swift + Interface Builder approach:
We no longer have to argue about programmatic or storyboard-based design, because SwiftUI gives us both at the same time.
We no longer have to worry about creating source control problems when committing user interface work, because code is much easier to read and manage than storyboard XML.
We no longer need to worry so much about stringly typed APIs – there are still some, but significantly fewer.
We no longer need to worry about calling functions that don’t exist, because our user interface gets checked by the Swift compiler.
So, I hope you’ll agree there are lots of benefits to be had from moving to SwiftUI!
Frequently asked questions about SwiftUI
Does SwiftUI replace UIKit?
No. Many parts of SwiftUI directly build on top of existing UIKit components, such as UITableView. Of course, many other parts don’t – they are new controls rendered by SwiftUI and not UIKit.
But the point isn’t to what extent UIKit is involved. Instead, the point is that we don’t care. SwiftUI more or less completely masks UIKit’s behavior, so if you write your app for SwiftUI and Apple replaces UIKit with a singing elephant in two years you don’t have to care – as long as Apple makes the elephant compatible with the same methods and properties that UIKit exposed to SwiftUI, your code doesn’t change.
Is SwiftUI fast?
SwiftUI is screamingly fast – in all my tests so far it seems to outpace UIKit. Having spoken to the team who made it I’m starting to get an idea why: first, they aggressively flatten their layer hierarchy so the system has to do less drawing, but second many operations bypass Core Animation entirely and go straight to Metal for extra speed.
So, yes: SwiftUI is incredibly fast, and all without us having to do any extra work.
How to follow this quick start guide
最好顺序阅读该教程
Migrating from UIKit to SwiftUI
如果你用过UIKit,不难发现SwiftUI就是把UI前缀去掉既是对应的组件。
Here’s a list to get you started, with UIKit class names followed by SwiftUI names:
UITableView: List
UICollectionView: No SwiftUI equivalent
UILabel: Text
UITextField: TextField
UITextField with isSecureTextEntry set to true: SecureField
UITextView: No SwiftUI equivalent
UISwitch: Toggle
UISlider: Slider
UIButton: Button
UINavigationController: NavigationView
UIAlertController with style .alert: Alert
UIAlertController with style .actionSheet: ActionSheet
UIStackView with horizontal axis: HStack
UIStackView with vertical axis: VStack
UIImageView: Image
UISegmentedControl: SegmentedControl
UIStepper: Stepper
UIDatePicker: DatePicker
NSAttributedString: Incompatible with SwiftUI; use Text instead.
Text("This is an extremely long string that will never fit even the widest of Phones") .truncationMode(.middle) .font(Font.body) .foregroundColor(Color.green) .background(Color.gray) .lineLimit(nil) .lineSpacing(30)
var body: someView { Group { ifBool.random() { Image("example-image") } else { Text("Better luck next time") } } }
第二种方案
If you haven’t heard of this concept, it effectively forces Swift to forget about what specific type is inside the AnyView, allowing them to look like they are the same thing. This has a performance cost, though, so don’t use it often.
1 2 3 4 5 6 7
var body: AnyView { ifBool.random() { returnAnyView(Image("example-image")) } else { returnAnyView(Text("Better luck next time")) } }
SwiftUI solves this problem by removing state from our control. When we add properties to our views they are effectively inert – they have values, sure, but changing them doesn’t do anything. But if we added the special @State attribute before them, SwiftUI will automatically watch for changes and update any parts of our views that use that state.
In order to handle dynamic items, you must first tell SwiftUI how it can identify which item is which. This is done using the Identifiable protocol, which has only one requirement: some sort of id value that SwiftUI can use to see which item is which.
structRestaurant: Identifiable { var id =UUID() var name: String }
structRestaurantRow: View { var restaurant: Restaurant
var body: someView { Text("Come and eat at \(restaurant.name)") } }
structContentView: View { var body: someView { let first =Restaurant(name: "Joe's Original") let second =Restaurant(name: "The Real Joe's Original") let third =Restaurant(name: "Original Joe's") let restaurants = [first, second, third]
What happens if you create a dynamic list and put more than one thing in each row? SwiftUI’s solution is simple, flexible, and gives us great behavior by default: it creates an implicit HStack to hold your items, so they automatically get laid out horizontally.
SwiftUI’s declarative approach to programming means that we don’t create and present alert and action sheets in the same way as we did in UIKit. Instead, we define the conditions in which they should be shown, tell it what they should look like, then leave it to figure the rest out for itself.
SwiftUI doesn’t have a direct equivalent of the didSelectRowAt method of UITableView, but it doesn’t need one because we can combine NavigationButtonwith a list row and get the behavior for free.
Explicit animations are often helpful because they cause every affected view to animation, not just those that have implicit animations attached. For example, if view A has to make room for view B as part of the animation, but only view B has an animation attached, then view A will jump to its new position without animating unless you use explicit animations.
var body: someView { VStack { Button(action: { withAnimation { self.showDetails.toggle() } }) { Text("Tap to show details") }
if showDetails { Text("Details go here.") } } } }
By default, SwiftUI uses a fade animation to insert or remove views, but you can change that if you want by attaching a transition() modifier to a view.
1 2
Text("Details go here.") .transition(.move(edge: .bottom))
structContentView : View { let title =Text("Paul Hudson") .font(.largeTitle) let subtitle =Text("Author") .foregroundColor(.secondary) var body: someView { VStack { title .color(.red) subtitle } } }
desc "Deploy a new version to the App Store" lane :releasedo remove86framework gym add86framework deliver(force:true) # frameit end
desc "Remove x86 framework" lane :remove86frameworkdo sh(%( cd ../Pods/HyphenateLite/iOS_Pods_IMSDK* pwd if [ ! -d "./bak" ]; then mkdir ./bak fi if [ -d "./bak/HyphenateLite.framework" ]; then rm -rf ./bak/HyphenateLite.framework fi cp -r HyphenateLite.framework ./bak lipo HyphenateLite.framework/HyphenateLite -thin armv7 -output HyphenateLite_armv7 lipo HyphenateLite.framework/HyphenateLite -thin arm64 -output HyphenateLite_arm64 lipo -create HyphenateLite_armv7 HyphenateLite_arm64 -output HyphenateLite mv HyphenateLite HyphenateLite.framework/ )) end
desc "Add x86 framework back" lane :add86frameworkdo sh(%( cd ../Pods/HyphenateLite/iOS_Pods_IMSDK* pwd if [ -d "./HyphenateLite.framework" ]; then rm -rf ./HyphenateLite.framework fi cp -r ./bak/HyphenateLite.framework HyphenateLite.framework )) end