7. IOS Development in Swift – Some Advance Concepts¶
1 TestFlight¶
- Two accounts must be made with Apple Developer Program and App Store Connect.
- The app must be archived (Product > Archive) and uploaded to App Store Connect.
- The process of archiving requires signing the app with a certificate and provisioning profile.
- Types of Testers:
- Internal Testers: Members of the development team (up to 100 users). Managed from App Store Connect.
- External Testers: Users outside the development team (up to 10,000 users).
- Head to App Store Connect > My Apps > [App] > TestFlight > iOS > Test Information > External Testers > Add New Tester.
2 Persistent Storage¶
- Persistent storage is used to store data locally on the device, and sync it with a remote server when the device is online or periodically.
- Databases:
- SQLite: lightweight file, does not load data to memory, does not require a separate server process.
- Core Data: Native to IOS, default support for migrations and filters/search. nice interface. can be graph based or multithreaded. It is not compatible with Android stores and consumes memory.
- Firebase: NoSQL. Realtime database with automatic syncing. Data stored as JSON. Compatible with all ios/android/web. All clients are notified when data changes.
- Realm: Document based, can be shared between platforms. Compatible with all platforms. Relationships are not supported.
- Configuration Stores:
- NSUserDefaults: Not secure, Native, easy to use. save data as key-value pairs (text).
- Plist (Property List): save data as XML or binary.
- NsCoder: A protocol that enables an object to be encoded and decoded for archiving and distribution.
3 Running the App on a Device or Simulator¶
- Simulators reflects the performance of the device running on and not the actual device (the user’s device).
- Select the Build Scheme and Device from the top left corner of Xcode.
- You can connect supported devices to your Mac using a cable or through a network (Wifi)
4 Core Data¶
- Core Data is a framework that you use to manage the model layer objects in your application.
NsPersistentContainer
is a container that encapsulates the Core Data stack in your application, and it has three members:NsManagedObjectModel
: The data model that you define for your app.NsPersistentStoreCoordinator
: The object that you use to interact with the underlying file system.NsManagedObjectContext
: The object that you use to manipulate and track changes to managed objects.
5 Networking¶
- Building a url:
// Construct a URL by assigning its parts to a URLComponents value
var components = URLComponents()
components.scheme = "https"
components.host = "api.github.com"
components.path = "/users/johnsundell"
// This will give us the constructed URL as an optional
let url = components.url
- Use that url to build a data task:
// Create a data task, which will handle downloading and
// managing the lifetime of any temporary data that's
// downloaded as part of the request
let task = URLSession.shared.dataTask(with: url) { data, response, error in
// Check for any errors
guard error == nil else {
print("Error: \(error!)")
return
}
// Convert the data to a string (for display purposes)
let dataString = String(data: data!, encoding: .utf8)
print(dataString ?? "No data")
// The data comes back in a raw, unprocessed form,
// which we can turn into JSON quite easily
let json = try! JSONSerialization.jsonObject(with: data!, options: [])
print(json)
}
- As Networking is an asynchronous operation, we don’t want to block the main thread. So we use a data task to perform the networking operation in the background, then we use Grand Central Dispatch to get back to the main thread when we’re done.
let task = URLSession.shared.dataTask(with: url) { data, response, error in
DispatchQueue.main.async {
// Update the UI
if let data = data {
label.text = String(decoding: data, as: UTF8.self)
} else {
label.text = error?.localizedDescription
}
}
}
- then the task must be started:
task.resume()
6 Swift¶
Error Handling¶
- Custom Errors must conform to the
Error
protocol. - Use
throw
to throw an error andthrows
to mark a function that can throw an error.
enum LoginError: Error {
case invalidUsername
case invalidPassword
}
enum MyError: Error {
case error1
case error2
}
func login(username: String, password: String) throws {
guard username == "john" else {
throw LoginError.invalidUsername
}
guard password == "password" else {
throw LoginError.invalidPassword
}
print("Successfully logged in!")
}
do {
try login(username: "john", password: "password")
} catch is LoginError {
print("Login failed: \(error)")
} catch MyError.error1, MyError.error2 {
print("Error 1")
} catch {
print("Unexpected error: \(error)")
}
Generics¶
- Generics allow us to write code that can work with any type, rather than just a single, specific type.
- Generic swap function:
func swapTwoValues<T>(_ a: inout T, _ b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
- Generic Stack:
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}
// extending the generic stack with isEmpty(),and access to the `top` element
extension Stack {
var isEmpty: Bool {
return items.isEmpty
}
var top: Element? { // Element is available from the parent struct
return items.last
}
}
Protocols¶
- A protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality.
- Protocol is an interface in other languages that can be adopted (implemented) by a class, struct or enum.
- A class/struct/enum conforms to a protocol by implementing all of its requirements.
- Multiple protocols can be adopted by a class/struct/enum by separating them with a comma.
protocol SomeProtocol {
// protocol definition goes here
}
struct SomeStructure: FirstProtocol, AnotherProtocol {
// structure definition goes here
}
References¶
-
Katz, M. (2020, August 19). TestFlight tutorial: iOS beta testing. raywenderlich.com. https://www.raywenderlich.com/10868372-testflight-tutorial-ios-beta-testing ↩
-
Muramshetty, D. (2019, May 7). Persistent storage options in iOS. Innominds. https://www.innominds.com/blog/persistent-storage-options-in-ios ↩
-
Running your app in the simulator or on a device. (n.d.). Apple Developer. https://developer.apple.com/documentation/xcode/running-your-app-in-simulator-or-on-a-device/ ↩
-
Setting up a core data stack. (n.d.). Apple Developer. https://developer.apple.com/documentation/coredata/setting_up_a_core_data_stack ↩
-
Sundell, J. (2019, January 14). Networking. SwiftbySundell. https://www.swiftbysundell.com/basics/networking/ ↩
-
The swift programming language swift 5.7. (n.d.). Apple Inc. https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html ↩