Using Swift Package Manager

About Swift Package Manager

The Swift Package Manager is the tool used to build Applications and Libraries. it streamlines the process of managing multiple Modules & Packages. Before we go ahead and learn to use Swift Package Manager we need to get familiar with some basic terminology.

Modules

Modules are used to specify a namespace and used to control access to that particular piece of code. Everything in Swift is organised as a module. An entire app can fit into a module or an app can be made using multiple modules. The fact that we can build modules using other modules means that reusing code becomes a lot easier. So, when we make an iOS App with Xcode and Swift. The entire app is considered a single module.

Targets

Targets are the end product that we want to make. So an app for iOS is a separate target. A library is a target. An app for macOS is a separate target. You can have many targets. Some can be for testing purposes only.

Packages

Packages group the necessary source files together. A package can contain more than one target. Normally one would create a package for a family of products. For example: you want to make a photo editing app that runs on macOS & iOS. You would create one package for it. That package would have 2 targets: an iOS App & a macOS App.

Products

This is a categorisation of your packages. There are 2 types of products. Executables or Libraries. A library contains the module which can be reused elsewhere. Executables are application that run & may make use of other modules.

Dependencies

Dependencies are the modules or the pieces of code that are required to make the different targets within the package. These are normally provided as URLs.

End Products

*NOTE: Before you get started you must be familiar with Setting up Swift on Linux. If you haven’t done that then please go through the updated article: UPDATE: Swift on Linux. This also makes use of Swift Package Manager.

Example

So let us get started with an example. We are going to learn how to create:

  • a library package called ErrorTypes
  • a library package, called MathOperations, that uses the ErrorTypes library package
  • an executable package called Calc that makes use of the MathOperations package.

We will see how to create all three elements. Also I have uploaded the ErrorTypes & MathOperations packages to the http://www.github.com repository to demonstrate the use of dependencies. You can also create your own local git repositories if you wish.

To illustrate the folder hierarchy: I have created a folder called “Developer” in my Ubuntu linux home folder. Within that I have created a folder called “SPMDEMO“. All the paths that I will be using will be with reference to these folders. You should see a structure like this:

/home/admin/Developer/SPMDEMO/ErrorTypes
/home/admin/Developer/SPMDEMO/MathOperations
/home/admin/Developer/SPMDEMO/Calc

You are free to follow this exercise using your own folder locations. Just modify the paths accordingly.

swift package init
swift package init --type executable
swift build

If you need help with the commands run:

swift package --help
swift --help

Creating a Package

  1. First let us start off by creating the ErrorTypes package.
    mkdir ErrorTypes
  2. Navigate to the folder and create the package:
  3. cd ErrorTypes
    swift package init
    

    By default init will create a library package type.

  4. Navigate to the folder containing the source files:
    cd ./Sources/ErrorTypes/
  5. Open the ErrorTypes.swift file and write the following code
    public enum ErrorCodes : Error
    {
         case FileNotFound(String)
         case DivideByZero(String)
         case UnknownError(String)
    }
    
    public struct MathConstants
    {
         static let pi : Float = 3.14159
         static let e  : Float = 2.68791
    }
    

    Feel free to add some code of your own. The above is just an example.

  6. Run the command to build to make sure that there aren’t any issues. You shouldn’t have any as there are no dependencies of any kind. Its a simple straightforward piece of code.
    swift build
  7. If everything is fine check your code into a git repository. This can be local or on the web. Remember that we will need the URL to this repository.
  8. Navigate back to the SPMDEMO folder.
    cd ~/Developer/SPMDEMO/
  9. Create a folder called MathOperations.
    mkdir MathOperations
  10. Navigate to the newly created folder and run the command to create a library package.
    cd MathOperations
    swift package init
    
  11. Navigate to the sources folder:
    cd ./Sources/MathOperations/
  12. Open the MathOperations.swift file and write the following code.
    import ErrorTypes
    
    public struct MathOperations
    {
         public static func add(Number num1 : Int, with num2 : Int) -> Int
         {
              return num1 + num2
         }
    
         public static func mult(Number num1 : Int, with num2 : Int) -> Int
         {
              return num1 * num2
         }
    
         public static func div(Number num1 : Int, by num2 : Int) throws -> Int
         {
              guard num2 > 0
              else
              {
              throw ErrorCodes.DivideByZero("You are dividing by zero. The second argument is incorrect.")
              }
    
              return num1 / num2
         }
    
         public static func sub(_ num1 : Int, from num2 : Int) -> Int
         {
              return num2 - num1
         }
    }
    
  13. Before we build we need to modify the Packages.swift file to indicate there is a dependency.
    Notice that in the MathOperations.swift file we are importing a module called ErrorTypes. We just created it. But just because we created it doesn’t mean it will be added automatically. We need to pull that module into our own

    Also notice that I have provided access specifiers “public” everywhere. This ensures that the code written in one module is accessible in the other.

    Navigate to the MathOperations parent folder.

    cd ~/Developer/SPMDEMO/MathOperations/
  14. Open the Packages.swift file and make the changes as shown below:
    // swift-tools-version:4.0
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(name: "MathOperations",
         products: [
              // Products define the executables and libraries produced by a package, and make them visible to other packages.
              .library(name: "MathOperations", targets: ["MathOperations"]),
         ],
    
         dependencies: [
              // Dependencies declare other packages that this package depends on.
              .package(url:"https://github.com/AmaranthineTech/ErrorTypes.git", from:"1.0.0"),
         ],
    
         targets: [
              // Targets are the basic building blocks of a package. A target can define a module or a test suite.
              // Targets can depend on other targets in this package, and on products in packages which this package depends on.
              .target(name: "MathOperations", dependencies: ["ErrorTypes"]),
              .testTarget(name: "MathOperationsTests", dependencies:   ["MathOperations"]),]
    )
    
  15. Once these changes are made save the file and run the command
    swift build

    If you typed everything correctly then you should see the source code for the ErrorTypes module being pulled in and the build being successful.Here are some common mistakes:
    – Forgetting to write the import ErrorTypes statement
    – Error in the URL
    – The from tag not matching the tag in the repository
    – Access specifiers are incorrect or missing
    – Not mentioning the dependencies in the target

  16. Just like with the ErrorTypes module create a git repository for the MathOperations module.
  17. Now let us make the Calc executable that will use the MathOperations library. First navigate back to the SPMDEMO folder and create a folder called Calc.
    cd ~/Developer/SPMDEMO/
    mkdir Calc
    
  18. This time we are going to create an executable package. Run the command:
    swift package init --type executable

    This also creates a similar folder structure as in the case of the library.

  19. Navigate to the folder containing the main.swift file.
    cd ./Sources/Calc/
  20. Modify the main.swift file as shown below:
    import MathOperations
    
    //testing addition
    var result : Int = MathOperations.add(Number: 33, with: 29)
    print("Result of adding 33 with 29 is: \(result)")
    
    //testing multiplication
    result = MathOperations.mult(Number: 33, with: 29)
    print("Result of multiplying 33 with 29 is: \(result)")
    
    //testing division
    do
    {
         result = try MathOperations.div(Number: 33, by: 0)
         print("Result of dividing 33 by 29 is: \(result)")
    }
    catch let error
    {
         print("ERROR: \(error)")
    }
    
    //testing subtraction
    result = MathOperations.sub(3, from: 29)print("Result of subtracting 3 from 29 is: \(result)")
    
  21. Navigate back to the main Calc folder.
    cd ~/Developer/SPMDEMO/Calc/
  22. Modify the Packages.swift file as shown below:
    // swift-tools-version:4.0
    // The swift-tools-version declares the minimum version of Swift required to build this package.
    
    import PackageDescription
    
    let package = Package(name: "Calc",
    dependencies: [
         // Dependencies declare other packages that this package depends on.
         .package(url: "https://github.com/AmaranthineTech/MathOperations.git", from: "1.0.1"),
    ],
    targets: [
         // Targets are the basic building blocks of a package. A target can define a module or a test suite.
         // Targets can depend on other targets in this package, and on products in packages which this package depends on.
         .target(name: "Calc", dependencies: ["MathOperations"]),
    ]
    )
    
  23. Save the file and run the build command:
    swift build
  24. Like before you should see both the MathOperationsErrorType module being pulled in. We are ready to run the executable. Navigate to the debug folder which contains the executable. Make sure you are in the main Calc folder when you run this command.
    cd ./build/debug/
  25. You should see an executable file called Calc. Run it.
    ./Calc
  26. If everything went okay then you should see the output on the console.

As you can see it is pretty straightforward to develop Applications written in Swift on Linux.

Adding System Modules

In the previous example we saw how to import our own custom made modules. However, there are some modules provided by the system which offers functionality we may wish to use. For example if we wanted to use the random number generator in our application we would need to use the random() method. This is in the glib module.

  1. Quickly create a package called SystemLibs. This is an executable.
  2. Write the following code in the main.swift.
    #if os(Linux)
    import Glibc
    #else
    import Darwin.C
    #endif
    extension Int
    {
         func toString() -> String
         {
              return "\(self)"
         }
    }
    
    var luckyNumber : Int = Int(random())
    
    var luckyNumberStr : String = luckyNumber.toString()
    
    print("The lucky number is \(luckyNumberStr)")
    
  3. Build the code and run the executable.

Adding system modules is direct and simple. The glibc module contains aspects of the standard library. The condition check is to make sure that we are importing the correct module based on the system that we are developing the application on.

Handling Sub-dependencies

As we saw in the earlier example, sub dependencies are handled automatically. So when our Calc application marked the MathOperations module as a dependency it was pulled during the build. However, the MathOperations module itself marked ErrorTypes module as a dependency. We did not have to modify the Packages.swift file belonging to Calc to indicate that ErrorTypes module also needs to be pulled. This was handled automatically by Swift Package Manager.

Conclusion

In this article we have seen:

  • How to create a library package
  • How to create a library package that depends on another library package
  • How to create an executable that depends on a library package
  • How to import the system Glibc module into our executables.

The Swift Package Manager simplifies many aspects of the development process for us. Many of the things we have discussed also work on macOS. Going forward reusing code and planning for the same should be done keeping Swift Package Manager in mind.

Advertisement

UPDATE: Swift on Linux

This article is an UPDATE for Writing Swift Programs on Linux

This article uses Command Line Interface(CLI) to write Swift Programs. If you are new to CLI then you should read the following articles: Terminal Commands for OS X – BasicTerminal Commands for OS X – Part 2.

This article has been written using Ubuntu version 16.04 LTS

For the best part the process is still the same.

  1. Download the Swift tools for Linux from: Swift Download Page
  2. Untar the downloaded files
  3. Copy them to a folder of your choice. I have created a folder called “Developer” in my home folder. So I copied the untarred contents there. This is important because we will be needing the location later.
  4. Switch to Terminal on your Ubuntu System.
  5. First we will install clang. Run the command
    sudo apt-get install clang
  6. Next we will make sure we set the PATH to the path where we copied the Swift tools. For example if the Untarred swift folder is called “swift-4.0-DEVELOPMENT-SNAPSHOT-2017-12-04-a-ubuntu16.04/usr/bin:”${PATH}” and it is in the Developer folder I created earlier then the command would be:
    export PATH=/home/admin/Developer/swift-4.0-DEVELOPMENT-SNAPSHOT-2017-12-04-a-ubuntu16.04/

    The folder name will vary from system to system. The path above is just an example.

  7. Let us check to make sure that everything installed okay. We can do this with 2 commands:
    which swift

    This should show you the path to the folder.
    or

    swift --version

    This should print out the swift version.

  8. Next let us test the REPL. Run the command:
    swift

    This will result in a prompt that looks like:

    Welcome to Swift version 4.0.3-dev (2dedb62a0b, Clang ab7472e733, Swift 64ab6903b2). Type :help for assistance.
     1>
    
  9. Type some of the commands mentioned below:
    12 * 8
    let hello = "Welcome to Swift in Linux"
    print(hello)
    
  10. Now that we know that the REPL is working well, let us move on to the next stage. Let us quit from the REPL:
    :q

Creating Single File Projects

  1. Next let us use Swift Package Manager to create a single file project. I will be creating the project in the Developer folder. So I will navigate to it:cd ~/Developer/
  2. Create a folder of your choice, lets call it Hello World:
    HelloWorld
  3. Enter the folder:
    cd HelloWorld
  4. Create a manifest file for the Package with the command:
    swift package init

    This will create some content for you. The structure should look as shown below.Screen Shot 2018-03-27 at 10.24.02 AM

  5. If we run the command to build it will simply create a module for us. To do that type and run:
    swift build
  6. But we would like to create an executable application. In the sources folder create a file called main.swift. You can use the command:
    touch main.swift

    to quickly create a new swift file.

  7. Open the main.swift file. Write the following code in there:
    let object : HelloWorld = HelloWorld()
    print(object.text)
    print("End of program...!")
    
  8. To create the executable we will first build our code:
    swift build
  9. Now we will run the executable, assuming that you are still in the HelloWorld folder within the sources folder navigate to a hidden build folder. To do that first we will navigate to our main HelloWorld package folder.
    cd ../..
  10. To view all the folders including the hidden folders run the list command:
    ls -la
  11. Navigate to the hidden folder and the debug folder inside it to locate the executable:
    cd .build/debug/
  12. To run the executable:
    ./HelloWorld
  13. If you want to build and directly run & avoid doing steps 9-13 repeatedly the command is:
    swift run

Next we will see how to create multi file projects

Create Multi File Projects

    1. In the previous project go back to the HelloWorld folder within the Sources folder. Create a file called converter.swift:
      touch converter.swift
    2. Write the following code in that file:
      //note the code below is for demonstrating multi file projects & may not necessarily be accurate or correct
      
      //note the code below is for demonstrating multi file projects & may not necessarily be accurate or correct
      func centigrade_to_fahrenheit(temperatureInCentigrade : Float) -> Float
      {
           return ((temperatureInCentigrade*9.0/5.0)+32.0)
      }
      
      func string_to_float(input : String) -> Float
      {
           var number : Float = 0.0;
           var result : Float = 0.0
           var decimalFound : Bool = false
           var numberOfDigitsAfterDecimal : UInt8 = 0
      
           for charac in input
           {
                switch charac
                {
                     case "0":
                          number = 0.0;
                          result = (result * 10.0) + number;
                     case "1":
                          number = 1.0;
                          result = (result * 10.0) + number;
                     case "2":
                          number = 2.0;
                          result = (result * 10.0) + number;
                     case "3":
                          number = 3.0;
                          result = (result * 10.0) + number;
                     case "4":
                          number = 4.0;
                          result = (result * 10.0) + number;
                     case "5":
                          number = 5.0;
                          result = (result * 10.0) + number;
                     case "6":
                          number = 6.0;
                          result = (result * 10.0) + number;
                     case "7":
                          number = 7.0;
                          result = (result * 10.0) + number;
                     case "8":
                          number = 8.0;
                          result = (result * 10.0) + number;
                     case "9":
                          number = 9.0;
                          result = (result * 10.0) + number;
                     default:
                          decimalFound = true
                          break
                }
                if decimalFound
                {
                     numberOfDigitsAfterDecimal += 1
                }
           }
      
           for _ in 0..<numberOfDigitsAfterDecimal-1
           {
                result = result / 10.0
           }
           return result
      }

 

  1. Write the following code in the main.swift file:
    let object : HelloWorld = HelloWorld()
    if CommandLine.arguments.count != 2
    {
            print("USAGE: centigradeToFahrenheit 33.4")
            print("You are missing an argument")
    }
    else
    {
            let temperatureInCentigrade = string_to_float(input: CommandLine.arguments[1]) 
    
            print("\(temperatureInCentigrade) is equal to \(centigrade_to_fahrenheit(temperatureInCentigrade: temperatureInCentigrade))")
    }
    print(object.text)
    print("End....!")
    
  2. Build and run the code. To run it while passing arguments in:
    ./HelloWorld 33.4

So that is how you can build single file & multi file Swift applications on Linux.

Programming Style Guide: Documentation

Now we will shift our attention to that part of programming which is often ignored. Documentation.

Documentation is a key part of programming. In fact, some might go as far as saying that Documentation is the most important aspect of Programming. Let us understand what we mean by documentation by looking at some key points. Later we will look at different ways of documenting our code.

We document our code so that:

  1. Anyone who is reading our code can understand what we are trying to achieve.
  2. Anyone who wishes to make changes to our code knows where to make the changes.
  3. Anyone who issuing our code can easily find out its capabilities and limitations.
  4. Other programmers can figure out how to use our code.
  5. Developers can find out when and where changes were made to a code. This is useful to understand the evolution of our code.
  6. We can easily recollect what, why, when, where & how something was done by us. This is necessary if we are revisiting code that we have written a long time back.
  7. We can add warnings and disclaimers

There may be some other reasons why we may want to document our code, but the list above summaries the most common reasons. This can easily be seen from a simple example.

func fahr_to_cent(Centigrade temp : Float) -&amp;gt; Float
{
return (32 + (temp * 1.8))
}

It is clear to use what the function does simply from its name. However, there is a lot more information that we can provide. Let us modify the implementation a little bit to make it more informative and readable.

/**
This function takes temperature in Centigrade and converts it to Fahrenheit.
- important: This function does not do data validation
- parameter temp: This is the temperature in Centigrade. It can be a negative value too.
- returns: This is the temperature in Fahrenheit.
- requires: `temp > -273.0 && temp < 1000.0`
- Note: The requirement mentioned is not enforced.
- Since: iOS 11
- author: Arun Patwardhan
- copyright: Copyright (c) Amaranthine 2015
- version: 1.0
*/
func convert_to_fahrenheit_from(Centigrade temp : Float) -&amp;gt; Float
{
     return ((temp * 9.0 / 5.0) + 32.0)
}

The code above looks a lot better now. We made the function name better, but more importantly we have added documentation that better describes the function. This includes range of permitted values, version number, important notes. The comments haven’t been written randomly. They have been formatted in a way that will make them appear in quick help. So now if we have to use the function we know what to watch out for.

Now that we know why we need to document our code let us look at some of the ways this can be done.

Comments

The most common form of documentation is by using comments. Most programming languages support comments. Comments are text which is ignored by the compiler. As such they are not used to build the actual software. The sole reason why they exist is because there has to be some mechanism to write notes.

Single Line Comments

// This is a comment

A single line comment as the name says is a piece of text that can fit in one line.

Good when a short description is required. Normally this is placed before or after a variable as most variables would need a short description.

You can have multiple lines using the Single comment mechanism too.

// This is a comment
// This is a comment on the next line

Multi Line Comments

There is a better way to implement multi line comments. We can enclose the text in a /* */ range.

/* This is a comment
   This is a comment on the next line
   Useful when we have to write really large pieces of comments&amp;amp;amp;lt;span 				data-mce-type="bookmark" 				id="mce_SELREST_start" 				data-mce-style="overflow:hidden;line-height:0" 				style="overflow:hidden;line-height:0" 			&amp;amp;amp;gt;&amp;amp;amp;lt;/span&amp;amp;amp;gt;
*/

Use Case

Here are some examples of when comments can or should be used.

/*
        File Name.   : main.cpp
        Date Created : 13th February 2017
        Created By   : Arun Patwardhan
        Project Name : String Parser
        File Contents:
                - Command Line Option selector
                - Different entry points for the remaining code
        Contact      : arun@amaranthine.co.in
*/

This is a classic example of a multi line comment. This comment provides useful information about the name of the file, when it was created, who created it, contact information, the code that is found in this file.

/*
    Exception Possibilities while Reading/Writing from/to Database
    write_error : This is thrown when there is duplicate data that is being
                  written into the database.
    db_empty.   : This is thrown when you attempt to read from an empty data
                  base.
                  Use the func is_empty() method.
    invalid_data: This is thrown when the data to be written is not valid.
    data_missing: This is thrown when insufficient data is passed. If the write
                  operation requires mandatory data an exception is thrown
                  instead of writing default values.
*/
enum DBExceptions : Error
{
    case write_error(String)
    case db_empty(String)
    case invalid_data(String)
    case data_missing(String)
}

This example shows the necessary documentation while declaring a new type. In short its purpose and situations when different values might be used.

Here is an example of code for functions.

@interface Converter : NSObject
/*!
    @brief This is a temperature conversion function

    @discussion This functions takes floating point values and does a floating point conversion to make sure that we get a precise conversion.

    @param temperature This is the value in centigrade that is passed in. Note, negative values can also be passed in. Values whose results exceed the range supported by float will produce un predictable results.

    @return float Returns a floating point value
*/
-(float) convert_to_fahrenheit_from_centigrade:(float) temperature;
@end

The comment gives information about different aspects of the function. Including the rage of values supported. Note that it also uses special markup to allow for the code description to show up in the Help menu bar or when you option click the method.

Comments

This is how the comments with markup look like. They appear in the ⌥ click menu as well as the help menu on the right hand side.

Read Me Files

Another thing one can do along with comments is to create Read Me files. Read Me files are plain text files that are bundled as a part of the project. Unlike comments which give information about a specific piece of code or an entire file, Read Me files give information about the entire project as a whole. Since they are text files we actually treat them as text.

Here is some typical information that is found in a Read Me file:


Project Name : String Parser
Project Request/Ticket Code: 13788
Orignal Project Author : Arun Patwardhan
Contact Details :
– arun@amaranthine.co.in
http://www.amaranthine.in

Platforms on which Application Can Run
– macOS 10.10 or later
– Windows 7 or later
– Linux (Ubuntu 14 or later)

Compiler Supported – g++

Building the Application

make

Testing

strParser -f Test1 -o myOutput1
strParser -f Test2 -o myOutput2

Files
– makefile
This is the file used to build the Application.

– main.cpp
This is the entry point file. The selection of execution path on the basis of command line options is done here.

– Parser.h
This file contains the declaration for the Parser class as well as its internal structure.

– Parser.cpp
This file contains the implementation of the Parser class

– DataStructure.h
This file contains the declaration of the internal structure of the data structure.

– DataStructure.cpp
This file contains the implementation of the internal structure of the data structure.

– Validator.h
This file contains the declaration of the internal structure of the data structure.

– Validator.cpp
This file contains the implementation of the internal structure of the data structure.

– Test1
Runs a basic set of strings as input.

– Output1
Expected output after running Test1. Compare your results with the results of this file.

Libraries Required – Standard Template Library


The above is just a sample Read Me file. In real world implementations these can get a lot bigger with references to links and future developments. Some of the other things that can be mentioned are:

  • Future additions
  • Bugs fixed (potentially with the bug fix request ticket)
  • Limitations
  • Tools that are required to make this code
  • Additional tools that need to be installed
  • Project Status

Naming Conventions

Documentation becomes a lot easier if we follow good naming conventions. Variables, functions, types, files… which are well named in itself become self explanatory and at the very least reduce the amount of documentation required.

Additional Tools Documentation in C++, Objective-C

Doxygen

HeaderDocretired You may come across some projects that use this.

Additional References for Documentation for Swift

Here is an article on Markups for Swift.

 

macOS & iOS IT Tool List

This list is based on questions that I have been asked by various IT admins.

It is more of a collection of tools (mainly software, but a few hardware tools too) that Enterprise IT Teams might find useful while supporting/managing Macs & iPhones in the enterprise. Some of the tools are free, while others are paid. Also, it is not necessary that all the tools will be required. Of course, some tools are not meant for troubleshooting but provide a service themselves.

The below list is not an endorsement or recommendation of any of the products mentioned. These are just some of the products I have come across. You may have to do your own research to see which tool fits your organisation’s needs. The author is not responsible for any damages or loss of data that might occur from usage of these tools.

*This list is not a complete list but an ongoing project. Feel free to share your comments on tools that you may have used & I will add them to this list.

DEPLOYMENT

DeployStudio

Munki

macOS Server – NetInstall Service. To be used along with System image Utility

PACKAGE MANAGEMENT

Iceberg

pkgbuild

Suspicious Package

REMOTE MANAGEMENT

RealVNC

TeamViewer

Apple Remote Desktop

LogMeIn

BACKUPS

macOS Server – Time Machine Service

Retrospect

Carbon Copy Cloner

Chronosync

Crash Plan

DEVICE MANAGEMENT

Centrify

JAMF Casper Suite

AirWatch

Mobile Iron

macOS Server – Profile Manager Service

Apple Configurator 2

Heat LANRev

Cisco Meraki

filewave

Absolute Software

BoxTone

Maas 360 – IBM

Tangoe

Lightspeed Systems

VIRTUALIZATION

Parallels Desktop

VMWare Fusion

Oracle VirtualBox

DISK MANAGEMENT

Tuxera

Disk Drill

APPLE APPLICATIONS FOR THIRD PARTY OS

iTunes

iCloud Control Panel

Move to iOS from Android

Migration Assistant

AUTOMATION

Workflow for iOS

Automator – Built in app for creating Workflows.

AppleScript

Command Line Script

NETWORK TROUBLESHOOTING

iNetTools

Network Diagnostics

Network Ping

Wireshark

DISPLAY

Air Squirrel

SYSTEM TROUBLESHOOTING

Install Disk – I will be talking about how to create a multi-OS install disk in a later article.

SOFTWARE MANAGEMENT

macOS Server – Caching Service

Reposado

AutoPKG

Munki

HARDWARE

Thunderbolt 1,2,3 Cables
Thunderbolt 1,2
USB-C Cable

FireWire 400/800 Cables

Portable disk with macOS installed on it. Not the same as install disk. Its an external bootable hard drive with the OS installed on it. You can plug this into any Mac & boot from the external HDD.

VGA to MiniDisplay adapter

HDMI to HDMI Cable

Thunderbolt Ethernet Bridge

USB Ethernet Bridge

Adapters for the different ports supported by Macs & iPhones

Lightning Cables

COLLECTION TYPE, SEQUENCE TYPE & INDEXABLE TYPE – Update

This is an update to the topic covered earlier. You can read about the Protocols in detail in the original article. Collection Type, Sequence Type & Indexable Type

Most of the things are the same here are some of the changes:

  1. The Indexable protocol is now not necessarily required. All the aspects of the indexable protocol now fall under the Collection Protocol
  2. The names of the protocols have changed from SequenceType & CollectionType to Sequence & Collection
  3. The keyword Generator has been renamed to Iterator. Accordingly the generate function has been renamed makeIterator function.
  4. The collection protocol now requires the implementation of the function index, this function returns the value of the next index.

The sample code below should clarify

class CustomStack
{
    var data : [Element] = [Element]()

    func push(Element newElement : Element)
    {
        data.append(newElement)
    }

    func pop() -> Element
    {
        return data.removeLast()
    }
}

//Additional Implementations - not strictly required
extension CustomStack
{
    typealias Index = Int

    var startIndex : Index
    {
        return 0
    }

    var endIndex: Index
    {
        return (data.count - 1)
    }

    subscript (position : Index) -> Element
    {
        return data[position]
    }
}

extension CustomStack : Sequence
{
    typealias Iterator = AnyIterator

    func makeIterator() -> Iterator
    {
        var index = 0
        return AnyIterator({() -> Element? in
            if index < self.data.count
            {
                let res =  self.data[index]
                index += 1
                return res
            }
            return nil
        })
    }
}

extension CustomStack : Collection
{
    typealias SubSequence = CustomStack

    subscript (bounds: Range) -> CustomStack.SubSequence
    {
        let newStack : CustomStack = CustomStack()

        for i in bounds.lowerBound...bounds.upperBound
        {
            newStack.push(Element: data[i])
        }
        return newStack
    }

    /// Returns the position immediately after the given index.
    /// - Parameter i: A valid index of the collection. `i` must be less than
    ///   `endIndex`.
    /// - Returns: The index value immediately after `i`.
    func index(after i: Int) -> Int
    {
        if i < endIndex
        {
            return i + 1
        }
        return i
    }
}

Writing Swift Programs on Linux

xc7-swiftlogo_2x1Swift Programming on Linux

The steps below walk you through the process of downloading, installing & using the Swift Programming language on Linux. For this I will be using Ubuntu Linux 14.04.3 LTS version.

Setup & Configuration

  1. Downloading Swift
    The first step is to download Swift from the link given below. Select the correct version of the OS.
    https://swift.org/download/#latest-development-snapshots
  2. Install clang
    The next step is to get hold of clang which is  a compiler front end for C,C++,Objective-C & Objective-C++. For more information on clang:
    https://en.wikipedia.org/wiki/Clang
    http://clang.llvm.org
    To install clang run the command:
    sudo apt-get install clang
  3. Extract the Swift files you downloaded and place them in a folder of your choice.
  4. Next we will add swift to our path. Do that by running the command:
    export PATH=/path to your swift folder/usr/bin/:”${PATH}”
  5. Verify whether it works by trying the following 2 commands
    which swift
    swift –version

Testing the REPL

  1. Next we try the REPL for swift. To invoke this just type the command:
    swift
  2. Write something like let myName : String = “Swift Code”
    and then hit enter.
  3. Follow it by print(myName) and then hit enter.
  4. You should see the output printed. This is a nice way to test individual Swift statements.

Creating a Single File Project

  1. To create a file based project:
    1. Create a folder of your choice, lets call it Hello World:mkdir HelloWorld
    2. Create a manifest file for the Package with the command: touch Package.swift
    3. The source files for all your projects must be in the Sources folder, let’s create that: mkdir Sources
    4. Create a file called main.swift using an editor of your choice. Place the statement print(“Hello, World”) in it.
    5. Step out of the sources folder and then run the command to build the project: swift build
    6. The executable will be inside a hidden folder called .build/debug
    7. The name of the executable will be the same as the name of the project folder.
    8. To run it simply type: .build/debug/HelloWorld

Creating a multi file project

  1. Create a folder of your choice, lets call it Hello World:mkdir CentigradeToFahrenheit
  2. Create a manifest file for the Package with the command: touch Package.swift
  3. The source files for all your projects must be in the Sources folder, let’s create that: mkdir Sources
  4. Create a file called converter.swift using an editor of your choice.
  5. Write the following code in it.:
    //note the code below is for demonstrating multi file projects & may not necessarily be accurate or correct
    func centigrade_to_fahrenheit(temperatureInCentigrade : Float) -> Float

    {
              return ((temperatureInCentigrade*9.0/5.0)+32.0)
    }
    func string_to_float(input : String) -> Float
    {
              var number : Float = 0.0;
              var result : Float = 0.0
              for charac in input.characters
              {
                        switch charac
                        {
                                  case “0”:
                                            number = 0.0;
                                  case “1”:
                                            number = 1.0;
                                  case “2”:
                                            number = 2.0;
                                  case “3”:
                                             number = 3.0;
                                  case “4”:
                                            number = 4.0;
                                  case “5”:
                                            number = 5.0;
                                  case “6”:
                                            number = 6.0;
                                  case “7”:
                                            number = 7.0;
                                  case “8”:
                                            number = 8.0;
                                  case “9”:
                                            number = 9.0;
                                  default:
                                            break
                        }
                        result = (result * 10.0) + number;
              }
              return result
    }
  6. Create a second file called main.swift
  7. Write the following code in it:
    if Process.arguments.count != 2
    {
              print(“USAGE: centigradeToFahrenheit 33.4”)
              print(“You are missing an argument”)
    }
    else
    {
              let temperatureInCentigrade = string_to_float(Process.arguments[1])
              print(“\(temperatureInCentigrade) is equal to \(centigrade_to_fahrenheit(temperatureInCentigrade))”)
    }
  8. Step out of the sources folder and then run the command to build the project: swift build
  9. The executable will be inside a hidden folder called .build/debug
  10. The name of the executable will be the same as the name of the project folder.
  11. To run it simply type: .build/debug/CentigradeToFahrenheit 100
    1. Try with different input values and no input value.
  12. That’s it. You are now ready to start typing code in Swift.

 

Making a case for OS X Server

Almost everyone is aware of the OS running on Apple Computers. Its called OS X & each version gets a name from a location in California (they used cat names earlier). But what is little know is about the Server that is also made available from Apple. Its called as OS X Server. Not only is it little know but it is also under utilised. I am going to make a case for using this product as compared to some of the other solutions that are available out there.

Installing

Firstly, lets talk about getting hold os OS X Server. Earlier there used to be a dedicated version of the OS which was made available for the server. But starting OS X 10.7 (Lion) that approach was discontinued. If you wanted an OS X Server, you would have to first upgrade your Mac to the consumer version of the OS & then install the Server.app. All you have to do This greatly simplified the whole process of setting your Mac up as a server.

The big advantage with this is that you no longer need to purchase a separate “server” version of the OS.  The other big advantage is that all the services being offered by the server are no located in a single application, in a nice collected manner.

Requirements

Typically most servers require an advanced hardware configuration to run. This is also the case for OS X Server. The recommended products for this would be the Mac Pro or the Mac Mini Server. The Mac Mini Server is a Mac Mini that comes with the Server App included as a part of the setup. This is a product configured to be used as a server. While the 2 products mentioned above are ones used most frequently as a server, you are not limited to them. Any Mac with a minimum of 10GB storage space & 2GB of RAM can run OS X Server. Though in reality you would need much larger specs than the ones mentioned above.

Services Offered

The OS X Server works best in an all Apple product environment. However, it also works well in mixed environments too. Especially when it comes to managing Macs & iOS Devices while taking advantage of other services being offered. In fact, a solution commonly used is the “Magic Triangle” which allows you to used an Active Directory Server along with OS X Server.

Basic Networking Services

Basics Networking Services such as DNS, DHCP, VPN are easily available & configured. Most of them don’t require a lot of configuring to do. Also the Caching Service & Software Update services can also be easily configured for managing the bandwidth usage in the organisation.

Collaboration & Communication

As a part of the collaboration & communication services provided you have the ability to host your own Mail service, Messages service, Website service, Wiki service, Calendar & Contacts Service.

Sharing

The file sharing service & ftp services are available for users to more easily share files & folders across the network.

Management

From a device management point of view there are plenty of services available. You have the Netinstall service which allows you to remote install OS X over the network or allow clients to boot using an image which is hosted on the server. Then there is the Open Directory Service which allows the management of various user accounts over the network. These users accounts then work along with the Time Machine service, which allows you to back up a Mac onto the server itself. Finally, the Profile Manager service works along with the domain users to provide device management for the different devices (OS X & iOS Devices).

Tools

Server App

LINK:https://itunes.apple.com/in/app/os-x-server/id714547929?mt=12
This is the main app that you will use to configure the different services that your server will be offering. The advantage with the app is it also allows you to remotely administer your server using the app itself.

Workgroup Manager

LINK:http://support.apple.com/kb/dl1698
The Workgroup Manager is a utility which can be downloaded from Apple’s support page. This application was used to create users & groups & apply managed preferences to them for earlier versions of the server. It is possible to create users & groups for the current version of the server using this app.

System Image Utility

This tool is required to create the different types of NetInstall images which are used for mass deployment. All OS X computers come with this application preinstalled.

Directory Utility

This utility also comes built into the OS & is used while binding your Mac to a Directory Service.

Apple Remote Desktop

LINK:https://itunes.apple.com/in/app/apple-remote-desktop/id409907375?mt=12
This is a very powerful tool. Available on the Mac App Store as a paid app. This tool allows you to remotely monitor & administer all the Macs within your organisation. It has many report generation tools to help in the management of your Macs.

Apple Configurator

LINK:https://itunes.apple.com/in/app/apple-configurator/id434433123?mt=12
This is another application available on the app store. This is a free app to configure different iOS Devices. It is used to perform a manual configuration of the devices.

Ticket Viewer

The Ticket Viewer Application is a built in application that is used to help in examining tickets used under kerberos.

Recovery Disk Assistant

LINK:http://support.apple.com/kb/dl1433
A free tool that is available online which allows an administrator to create an external bootable recovery drive to perform various troubleshooting tasks. OS X: About Recovery Disk Assistant

Disk Utility

This is a built in utility that is used to maintain different storage devices. It allows you to partition & format various drives.

Why to use the OS X Server

There are many reasons why an OS X Server would make a good option.

  • Cost: The cost of OS X Server itself is low. The hardware for running OS X Server would ideally be the Mac Mini which starts around $999 (including the Server App itself). If you already have a Mac with you, you just need to purchase the Server App for $20. This is ideal for organisations on a budget.
  • Simplicity: The Server is very easy to configure. Many of the services being provided are extremely easy to configure & maintain. From an administrators point of view, it involves providing basic information & a few clicks.
  • Features: The Server provides many basic services used everyday & many administrative options that combine the power of modern day servers with the simplicity needed.
  • Works well along with other Servers such Windows Server.

Ideal Situations to use OS X Server

The OS X Server is ideal for small organisations which use Mac or iOS Devices. The low cost & simplicity makes it an ideal choice for such organisations. Also if you are an organisation which uses a lot of Macs & iOS Devices then managing them is a lot easier with OS X Server, here again the cost & simplicity ensures that it is a viable option.

The server may not be a good choice for organisations with a very large user base or very few Mac/iOS devices. While other computers can easily work with OS X Server, other Servers may prove much better for such scenarios.

Here are some points to consider while deciding whether to use an OS X Server.

  • Does your organisation use a lot of Macs &/or iOS Devices?
  • Do you need to perform various administrative & configuration tasks on your Apple devices?
  • Is your user base small? Approximately 10 – 150 odd employees?
  • Do you need to provide very basic services without worrying too much about platforms being used? (Especially if directory services are not required).

If the answer to a combination of questions above is Yes, then the OS X Server might be the right choice for you.

Below are a list of some scenarios where the OS X Server might be ideal

  • Small Medium Enterprises
  • Schools & Educational Institutions
  • All Mac & iOS Environments
  • Home

Conclusion

The OS X Server is best if you are predominantly using Apple computers & mobile devices. The ability to manage them & configure them is best served by the Server app. However, for larger organisations this may not be the only criteria. The server can work along with windows server, however, most Apple computers & mobile devices can also work with other solutions.

If cost is a major consideration & simplicity is a must then the OS X Server is a good bet. If you are looking for a feature heavy server which offers a wide variety of services with lots of room for customisation then this might not be the right solution.

All in all the Server App is a very good app. It will definitely be something work considering when you are managing the IT infrastructure.