Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

Discover millions of ebooks, audiobooks, and so much more with a free trial

Only $11.99/month after trial. Cancel anytime.

Creating iOS apps with Xcode: Learn how to develop your own app (English Edition)
Creating iOS apps with Xcode: Learn how to develop your own app (English Edition)
Creating iOS apps with Xcode: Learn how to develop your own app (English Edition)
Ebook648 pages3 hours

Creating iOS apps with Xcode: Learn how to develop your own app (English Edition)

Rating: 0 out of 5 stars

()

Read preview

About this ebook

“Creating iOS apps with Xcode” introduces you to the premier programming language of Swift and presents SwiftUI. It is an easy way of creating user interfaces on Apple products like iPhone, iPad, and Vision Pro.

This book teaches iOS app development using Swift and SwiftUI. You will begin by setting up Xcode, Apple's development tool, and learning Swift basics. Then, you will explore SwiftUI to create user interfaces with text, image, and buttons. Next, you will build reusable SwiftUI views and design a "Household Chores" app interface. Simultaneously, this book educates you on data management which includes data models, user defaults, and Swift Data databases. You will organize code with Swift Package Manager, and visualize data with Swift Charts. Further, you will also understand how to create a second app using SwiftUI and MVVM design, ensure app quality with testing and debugging, and prepare for App Store release with web service connections and asset management.

Once you finish this detailed guide, you will have the know-how to craft impressive iOS apps. You will have learned how to organize code, manage data, and test apps effectively, enabling you to bring your ideas to life.
LanguageEnglish
Release dateApr 28, 2024
ISBN9789355519443
Creating iOS apps with Xcode: Learn how to develop your own app (English Edition)

Related to Creating iOS apps with Xcode

Related ebooks

Operating Systems For You

View More

Related articles

Reviews for Creating iOS apps with Xcode

Rating: 0 out of 5 stars
0 ratings

0 ratings0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Creating iOS apps with Xcode - Aaron L Bratcher

    C

    HAPTER

    1

    Introduction to Swift

    Introduction

    In 2014, at the Worldwide Developers Conference, Apple introduced the world to the new Swift programming language with great fanfare. Since then, the language has been adopted as the premier language for creating apps not only for Apple products, but for servers and other platforms too. The future and direction of this language is publicly presented and debated. See https://swift.org for more information.

    Structure

    This chapter contains the following topics:

    Download Xcode

    Time to play

    Variables

    Custom types

    Closures

    Flow control

    Order of operation

    Objectives

    By the end of this chapter, the reader should know the basic syntax of the Swift language, some commonly used types, how to create custom types, and how to manage the flow of how code runs.

    Download Xcode

    The App Store is the best place to securely download and install applications to your computer. After installation, launch the app. Because Xcode is used to develop apps for all Apple platforms, an initial set of devices to develop for must be specified. Make sure iOS is selected and click the Download & Install button, as shown in Figure 1.1 below:

    Figure 1.1: Platform selection dialogue

    Time to play

    From the File menu, select New and then Playground. Select the iOS template at the top and the Blank Playground, then click the Next button on the bottom. Specify the location to save the playground and, if desired, change the name. Then click the Create button. In moments a screen that looks like Figure 1.2 will be shown:

    Figure 1.2: New Blank Playground

    The playground is a great way to try some quick code without creating a full project. The bulk of the display is the editor. To the right, is the Live View. In the editor, two lines of code have been provided. For now, we will ignore the import statement at the top.

    Below the import we see: var greeting = Hello, playground

    Variables

    A significant goal of programming is to manipulate the environment on the device or react to a change in the environment. To achieve this, the app needs to store and manipulate data using values and types. For instance, the value Hello, playground shown above is a string type. The var keyword declares a mutable variable called greeting. When an object is created and assigned to a variable, it is said to be instantiated.

    On the bottom-left of the window is the execute button. Picture 1 Click and hold it to see a pop-up menu. Select Automatically Run and the screen will change. In the live view, to the right, the same string that was assigned, Hello, playground is displayed with a small square next to it.

    Picture 1 - this square is the results toggle button. Clicking it will toggle the results display in the editor.

    On a blank line at the bottom, enter the following lines of code:

    greeting = Swift is easy

    var now = Date()

    let isRunning = true

    let maxLength = 256

    let avgNumberOfChildren = 2.2

    It may be necessary to disable the automatic running of code while typing this in. After all the lines of code are entered, make sure to re-enable Automatically Run or click on the Run button to the left of the last line of code. Picture 1 When entering a lot of code, the second option may be best. In the live view, values that are assigned to the variables will be displayed. Notice how the greeting shows two values? The initial value and then the new one. If you hover the pointer over any of the values, the line of code responsible for it will be highlighted in the editor. On the right side of the value is a preview icon. Click the results toggle or the preview icon. For now, a repeat of the value is shown. As Swift is explored, this will give more information.

    In the code entered, the value type was not specified. Swift will implicitly assign the type based on the value initially given to it. To see the type, hold down the option key ( ) and click on the variable name to see a more formal declaration as shown in Figure 1.3. Explicitly specifying the type will be shown later in the chapter.

    Figure 1.3: Variable definition popover

    The keyword let was used instead of var for three of the lines above. What does this mean? On a blank line, at the bottom of the variable declarations, try adding a line to change the value of isRunning to I am now running.

    What happens? Figure 1.4 illustrates the error:

    Figure 1.4: (Immutable variable error)

    A variable defined using the let syntax makes it immutable, or constant, after a value has been assigned. When a variable’s value does not need to change, use let. To allow isRunning’s value to change, go to the declaration and change it to var.

    What happens? Figure 1.5 shows an additional error:

    Figure 1.5: (Variable type error)

    Some languages allow the value type of a variable to be changed after it has been set. However, Swift is a strongly typed language, which means the value type cannot change. The variable isRunning is a Bool type so it can only hold the values of true or false. Remove the errant line of code.

    When the first error was displayed, a debug area was shown to give additional information. To show or hide this area, click the Debug area toggle button below the Live View panel.

    The names used for the variables are arbitrary. Swift convention says variable names start with a lowercase letter and an uppercase for concatenated words in the variable name. This is called camel case. In Swift, variable names can be any combination of letters, numbers, and even emojis. Names have these primary restrictions: They cannot begin with a number and must not contain mathematical symbols or white space characters, that is, spaces, tabs, newlines, and so on. Try it now. Change the names of the variables and introduce numbers in the middle or at the end of the names or try an emoji character. What works and what does not?

    So far, we have been assigning values to variables at the time of declaration. While this may work in limited cases, the value is usually not known until a later time. On a blank link, enter these lines of code and run by either setting the playground to run automatically or clicking the Run button to the left of the last line of code:

    let maxToppings: Int

    var useBox: Bool

    maxToppings = 10

    useBox = false

    When a value is not immediately assigned to the variable, the type must be specified at the time of declaration. But wait, there is more.

    Collections

    When deciding on the name of a variable, it is important to describe the type of value and what the value represents. For instance, if the name maxLength were changed to dogNames how would your expectations of the value change?

    The first expectation is for the variable to hold String values. The second is to hold multiple values because of the plurality in the name. When a variable holds multiple values, it is called a collection. The three principal collection types in Swift are array, dictionary and set. Type in the following line of code on a blank line and run:

    var dogNames = [Daisy, Caesar, Luna]

    var dogAges = [2, 5,  7]

    See how the Live View shows array of 3 elements?

    Now, click on the results toggle to see the values. Try different values inside the square brackets. Notice how there is always a comma between each value and how the types must match. Use Boolean, string, integer, or floating-point numbers. Some languages would call these primitive types, however in Swift they are treated just like any other object type we will learn about later.

    There are different ways of accessing the data in an array. The easiest is to use the ordinal position. On the line after the dogAges variable, type in: let firstDog = dogNames[0]. Notice that array index starts at zero.

    Like any other variable, a collection can have values assigned after the declaration. Remove the values between the square brackets and watch what happens. An error is displayed. Swift does not know what type of values the variable will store. It needs to be specified either by the developer or by the compiler. Here, the compiler does not know what type to assign so you need to.

    Change the line of code to look like this:

    var dogNames: [String] = []

    Now we have an empty array for strings. Let us explore different ways of assigning and removing values to this variable. Type in these lines of code and run:

    dogNames = [Daisy, Caesar, Luna]

    dogNames.append(Ralph)

    dogNames.insert(Sparky, at: 0)

    dogNames.remove(at: 1)

    let sortedNames = dogNames.sorted()

    Before looking at the results, what do you think each line of code does? The first and last lines are probably obvious, but what about the others? After giving it some thought, click on the results toggle button next to each entry in the Live View. Are the results what you expected?

    Something that may be surprising is the value shown for the remove statement because it shows the value affected by the statement instead of the changed variable. The returned value is being ignored. It can be captured by changing the line to something like this: let removedDog = dogNames.remove(at: 1).You may have been surprised that Daisy was removed and not Ralph. Remember, arrays start at index zero.

    In the code above for inserting, change the 0 to 5 and see what happens. We will explore debugging in a later chapter.

    The next collection to discuss is the dictionary. It uses a unique identifier, or key, and associates it with a value. On a blank line, enter the following lines of code and run:

    let stations = [2: Shell, 16: BP, 32: Chevron]

    print(stations[2])

    Like arrays, each entry is separated by a comma. Each entry consists of the key, a colon, then the value. The type for all provided values must match. If you are wondering why the print statement said Optional, then you are in for a treat. That will be discussed soon. To get a preview, try changing the 2 to 5.

    The type used for this dictionary’s key is Int, however AnyHashable type can be used. In fact, when declaring the dictionary variable, AnyHashable can be specified as the type. Change the let statement to the following and run:

    var stations: [AnyHashable: String]

    stations = [2:Shell, 16:BP, 32:Chevron]

    The declaration specifies the key type and the value type. Later, we will look at using other types for the values. Notice how the keys used on the second line are now Int and String. Print the BP value by changing the key used in the print statement to 16. In Swift, Int and String are hashable types. As it is possible to make custom types hashable, they can also serve as keys, if desired. Most often Int and String are used as the key type.

    Like arrays, dictionaries are not always populated at declaration and instantiation. Enter the following lines of code and run:

    1. stations[55] = Phillips 66

    2. stations[55] = PetroChina

    3. stations.removeValue(forKey: 2)

    4. let stationCount = stations.count

    5. print(stations.keys)

    6. print(stations.values)

    7. stations = [:]

    There is a lot happening here, so let us dissect it one line at a time. The first line assigns the value Phillips 66 to the dictionary with the key 55. The second line assigns the value PetroChina to the dictionary with the key 55. However, we must wonder, how is that that possible? Keys are supposed to be unique.

    The second line replaces the value associated with the key 55. This is confirmed with the last print statement. Line three completely removes the key, 2, and the value associated with it.

    The fourth line assigns the number of dictionary entries to the variable stationCount. All collections have the count property. In Swift, properties are variables associated with an object. Other helpful properties for collections are: isEmpty, first, and last.

    The print statements on lines five and six above print out the keys and values properties respectively. Note that they are arrays. The keys and values printed may or may not be in the order entered because, unlike an array, a dictionary is an unordered collection. The last statement instantiates an empty dictionary and assigns it to the variable.

    The final collection type we will cover is the Set. With the dictionary, any object type that is hashable can be used as the key that is associated with some data. What if we do not have any associated data? A situation where the key is the data, and we need a unique collection of these objects. This is the perfect time to use a Set. Let us try it.

    Type in the following lines and run:

    var partyGuests: Set = []

    partyGuests.insert(Aaron L Bratcher)

    partyGuests.insert(Anne McCaffrey)

    partyGuests.insert(Douglas Adams)

    partyGuests.insert(Richard Castle)

    print(partyGuests)

    partyGuests.remove(Douglas Adams)

    print(partyGuests)

    let insertResults = partyGuests.insert(Richard Castle)

    print(insertResults)

    To limit the output in the Debug area, remove all code entered before or create a new playground. Again, we see something new in the declaration and initialization of the variable. A Set can hold any hashable type. Like the dictionary, the type must be specified. The type to be stored, in this case a String, is specified in the angle brackets. Set utilizes generics, a feature covered later in this book. The square brackets initialize the variable with an empty set.

    As a Set is not ordered, the concept of appending is not logical. Instead, an object is inserted into the set and conversely, a known object can be removed. When an object is inserted, the response can be ignored, as was shown the first several times or captured. One could initially think the returned value of an insert would be a Bool type to indicate the success of the insert, however upon inspection you will find something new. Option-click on the variable and you will see this definition:

    let insertResults: (inserted: Bool, memberAfterInsert: String)

    The parenthesis around two element definitions is a Tuple. Tuples can have one or multiple elements with, or without, a name. If a name is included, each element is like a variable definition. Here are two examples:

    Example 1:

        let someData: (String, String, String)

        someData = (first element, second object, third)

    Example 2:

      var moreData: (name: String, city: String)

      moreData = (Thomas, New York City)

      moreData = (name: Roger, city: Los Angeles)

    It can be easy to forget what each value represents without a name, so names are recommended. However, when a name is not available, the ordinal index can be used. Like arrays, the index of tuple elements is zero based.

    print(someData.1)

    print(moreData.0)

    print(moreData.city)

    Optionals

    An optional starts with a question. Does a value exist? Remember when stations [2] was printed earlier? The output was Optional(Shell)\n and when stations [5] was printed, the output was nil\n. Why? Because when an attempt to retrieve a value from a dictionary is performed, the key or the value associated with it may not exist. It is only appropriate that a question mark is used to define when a variable or property is optional. Here is a declaration of a variable/property that may or may not have a String value:

    let crust: String?

    An attempt to print the value of crust, will generate an error. An immutable optional needs to be initialized. In this case either with a string or nil. Nil indicates no value exists. If the let was to be changed to a var, then it would compile and run properly as it starts with nil assigned.

    To properly retrieve the value, the optional must be unwrapped or coalesced to a non-optional value. Here are a few accepted ways of doing this:

    let crust: String?

    crust = thin

    if let crust {

      print(crust)

    }

    if var crust {

      crust = altered crust

      print(crust)

    }

    let crustType = crust ??

    The first option is to use the if let syntax. This checks if a value exists and, if one does, assigns it to a variable of the same name. This new variable is limited to the scope of the if statement, that is, between the curly braces. The variable can now be used safely. Outside of the scope, the original optional variable still exists.

    The second option uses the if var syntax. It is like the first option, but it gives a mutable variable that can be used within the scope of the if statement. Also, while the value of the new variable may be changed within the scope, it does not affect the original variable or property.

    The last option shown here is to coalesce. When the original variable has no value, the option after the coalesce operator is used instead. Multiple coalesce operators can be used in the same expression to chain multiple optionals together. Add a print statement to see what the value of crustType is. There is also the use of a guard statement, but it will be shown in a later segment because of how it is used.

    Something not shown, because it is frowned on, however sometimes it is needed, is the force-unwrap operator. This will attempt to unwrap the variable and assign the value. However, if it fails, the app will crash. Remove the assignment of thin to the variable and then run the statement below and an error will appear.

    let crustType = crust!

    A lot has been covered for how a variable is defined and used with some built-in types. We have also looked at collections and optionals. These basics are used in all aspects of Swift development and needs to be completely understood. Try to do the following on your own (answers are at the end of the chapter):

    Create a variable that holds an array of optional strings.

    Create a variable that holds a dictionary with an integer key and an optional tuple of two strings.

    Custom types

    When designing an app, it is a common task to structure the data into logical units for storage and manipulation. In this section, the most common ways of creating custom types will be explored.

    Structs

    A struct is a way to organize naturally related data elements together and, optionally, provide ways of manipulating them. They are very efficient for this task. For instance, a pizza representation may have a struct like this:

    struct Pizza {

      let crust: String?

      Let sauce: String

      let toppings: [String]

    }

    The key word struct specifies what kind of custom type we are creating. Notice the name, Pizza, is capitalized. When creating a new type, Swift convention is to capitalize the name of the type. When creating an instance object of the type, the variable or property starts with a lowercase letter.

    Some properties were created to describe a typical pizza. What kind of crust? Thin, hand-tossed, cheese filled, or, maybe, none. Some sauce and toppings.

    Like a string or dictionary, Pizza is now a type that can be created and assigned to a variable or property. The struct elements are properties that must be initialized with values. Swift helps us out by automatically creating an initializer for the struct so we can simply do this to instantiate the object:

    let pizza = Pizza(crust: nil, sauce: tomato, toppings: [onion, green pepper, mushroom, black olive])

    print(pizza.toppings)

    This creates a Pizza object and assigns it to our variable, pizza. This could be a pizza bowl, where no crust exists. Like many programming languages, Swift is case-sensitive. It is very common to have a variable name that closely matches the type name.

    There are times a coded initializer is needed. An initializer provides a point where parameters may be passed to make a valid object. It consists of the keyword, init, followed by an open parenthesis, maybe some parameters, then the closing parenthesis.

    The first case, shown below, is a one-to-one mapping of the init parameters to the properties that need a value. Swift implicitly provides this case for simple structs. The parameters provided to the init can also have default values assigned. Add the init code so the struct looks like this:

    struct Pizza {

      let crust: String?

      let sauce: String

      let toppings: [String]

      init(crust: String? = nil, sauce: String = tomato,

    toppings: [String]) {

          self.crust = crust

          self.sauce = sauce

          self.toppings = toppings

      }

    }

    What is the first thing you notice? That the parameter declarations look remarkably like the variable work done earlier. The first parameter, crust, is an optional string. A default value of nil is given. This would be helpful for pizza bowls where a crust does not exist. The default value for sauce is tomato and toppings does not have a default value so it must be specified when creating the object. Using this initializer, the creation of the pizza bowl can now look like this:

    let pizza = Pizza(toppings: [onion, green pepper, mushroom,

    black olive])

    The default values are for convenience but do not keep the developer from using the parameters. Any or all the parameters may be used for the instantiation of the pizza:

    let pizza = Pizza(crust: thin, sauce: tomato,

    toppings: [onion, green pepper, mushroom, black olive])

    The second thing to be noticed, may be the use of self. This is a reference to the one specific object and the items inside it. Remember when the dictionary keys were printed? The code referenced the keys property of the single dictionary object. The initializer is assigning values to the properties of self. When there is a need to reference something within the object itself, self is used when there is ambiguity. Otherwise, it is implied, (there is another use for it that will be looked at later in the book). For instance, what if the first parameter in init had been called base instead of crust?

    Enjoying the preview?
    Page 1 of 1