Shell scripting in macOS – Part 2: Managing information

This article is a continuation of the previous article. We will be taking the previous script and using it to build on the concepts we will learning in this article.

Using Variables to store information

First up we will look at variable. Variables are containers that can hold information. The biggest advantage of this is the fact that we can use information in our tasks simply by reusing the variable it is stored in. This means if there is any change at a later date, then we only have to change the value in the variable. 

So, in the future, if there is a need to modify the information, we only have a single point of change to make. This greatly aids  in the ease of maintenance of the code.

It also makes the script more readable.

NOTE: The value of a variable can be changed at a later point of time within the script. 

Creating variables is very easy. You simply declare a name and assign it a value using the = operator. For example, if we are going to be using the path to the logs folder then storing it in a variable called PATH_TO_LOGS makes sense. We would then follow it up with the = sign and follow that up with the path in quotes. 

PATH_TO_LOGS=“/Library/Logs/“

To use this variable in a command we would simple callout the name with the $ symbol prefixed before it. 

echo $PATH_TO_LOGS

The $ symbol is necessary to access the value being held by the container.

While declaring variables try to use names which explain the purpose of the variable.

Built in variables

We can see that it is very easy to define our own variables. However, we are not restricted to creating our own variables. The system provides us with predefined variables. These give us access to useful information such as:

  • Path to the current user’s home folder.
  • The shell interpreter being used.
  • The currently logged in user name. 

We can get the complete list of commands with the help of the printenv command.

printenv

How about using these variables? Well, we will use it the same way we would use our own variables. Just prefix the $ symbol before the variable name. 

echo "The path to the home folder is $HOME"

Let us update the script from the previous article.

#!/bin/zsh

echo "Running script to create folders."

TOOLS_FOLDER="Tools"
REPORTS_FOLDER="Reports"
HELP_FOLDER="Help"

TOOLS_FOLDER_CREATED=".$TOOLS_FOLDER-FolderCreated"
REPORTS_FOLDER_CREATED=".$REPORTS_FOLDER-FolderCreated"
HELP_FOLDER_CREATED=".$HELP_FOLDER-FolderCreated"

cd $HOME

echo "Creating folders: $TOOLS_FOLDER, $REPORTS_FOLDER, $HELP_FOLDER"
mkdir $TOOLS_FOLDER
mkdir $REPORTS_FOLDER
mkdir $HELP_FOLDER

echo "Creating hidden file for $TOOLS_FOLDER folder."
cd $TOOLS_FOLDER
touch $TOOLS_FOLDER_CREATED
cd ..

echo "Creating hidden file for $REPORTS_FOLDER folder."
cd $REPORTS_FOLDER
touch $REPORTS_FOLDER_CREATED
cd ..

echo "Creating hidden file for $HELP_FOLDER folder."
cd $HELP_FOLDER
touch $HELP_FOLDER_CREATED
cd ..

echo "Task completed. Have a nice day!"

Capturing command output

Now that we have seen how variables can be created and used, then next logical step is to use them to store the outcome of a command. Why would we need to do this? Let us suppose that a command returns the path to a folder and we would like to perform multiple tasks on this folder. We can simply save the path in a variable and then use the variable across the script. 

If storing the result of the command in a variable wasn’t possible then we would have to execute the command over and over again every time we needed the result.

But before we store the outcome of the command we first need to understand how we can capture the output of a command itself. This is done with the help of command substitution. The command to be executed is placed within the $ symbol followed by parentheses.

So to store it in a variable we would just place the command we would just place this on he right hand side of the = sign. For example, if we wanted to store today’s date we would use the date command placed within the $() on the right hand side of the = sign. On the left hand side of the = sign would be the name of our variable.

TODAY=$(date)

There is an older way of doing the same thing, instead of using the $() the command would be placed within 2 back ticks.

TODAY=`date`

Writing to files

While it is useful to store information within variables there are some limitation with this. Sometimes we would like to store our data outside the script for example on some other file. The advantage with this approach is that it allows us to access the information across multiple invocations of the script. 

The way we write to a file is by redirecting the output of the command from standard output to a file. There are 2 operators that help us with this.

The redirect operator with a single angle bracket will write the contents to a file. This will replace the existing content fo the file.

echo "Hello, World!" > /Users/Shared/message.txt

The redirect operator with 2 angle brackets will also write contents to a file. But this will append or add the existing content. 

echo "Hello, World!" >> /Users/Shared/message.txt

Depending on what you want you can use one of the 2 approaches. 

Logging events taking place in the script

A log file is used to note done certain events being performed by an app, script, process, or any task. It is a very useful troubleshooting tool. This would be a nice feature to add to our script. We can log the different events that are taking place. To do this we will use the same redirect operator to write to a file.

Log files are typically stored in one of two locations in macOS:

  • ~/Library/Logs/
  • /Library/Logs

For our demo we will store it in the ~/Library/Logs/ folder. This makes sense because our script will be making changes to a user’s home folder. So ideally, the log file should also stay in the user’s home folder.

The way we will generate our log file is by redirecting the output of the echo command to our file.

echo "Hello, World!" >> ~/Library/Logs/folderCreator_log_v1-1.log

So all the echo statements we have will be modified to redirect to the log. Additionally, we will use command substitution to include the date and time in out message. Let us modify the script above to reflect these new changes.

#!/bin/zsh

echo "$(date) Running script to create folders."

TOOLS_FOLDER="Tools"
REPORTS_FOLDER="Reports"
HELP_FOLDER="Help"

TOOLS_FOLDER_CREATED=".$TOOLS_FOLDER-FolderCreated"
REPORTS_FOLDER_CREATED=".$REPORTS_FOLDER-FolderCreated"
HELP_FOLDER_CREATED=".$HELP_FOLDER-FolderCreated"

TODAY=$(date)
PATH_TO_LOG="$HOME/Library/Logs/folderCreator_log_v1-1.log"

echo "$(date) Starting" >> $PATH_TO_LOG

cd $HOME

echo "$(date) Creating folders: $TOOLS_FOLDER, $REPORTS_FOLDER, $HELP_FOLDER" >> $PATH_TO_LOG
mkdir $TOOLS_FOLDER
mkdir $REPORTS_FOLDER
mkdir $HELP_FOLDER

echo "$(date) Creating hidden file for $TOOLS_FOLDER folder." >> $PATH_TO_LOG
cd $TOOLS_FOLDER
touch $TOOLS_FOLDER_CREATED
cd ..

echo "$(date) Creating hidden file for $REPORTS_FOLDER folder." >> $PATH_TO_LOG
cd $REPORTS_FOLDER
touch $REPORTS_FOLDER_CREATED
cd ..

echo "$(date) Creating hidden file for $HELP_FOLDER folder." >> $PATH_TO_LOG
cd $HELP_FOLDER
touch $HELP_FOLDER_CREATED
cd ..

echo "$(date) Task completed. Have a nice day!"

Passing information to a script

While storing information and capturing information within a script is useful. It is also useful to have the ability to give information to a script at the time of running the script. This allows the user of the script to have greater control over the end result or outcome. 

The information that is passed into the script is store in predefined variables known as positional variables. They are named $0, $1, $2 and onwards. Let us modify the script to use these variables.

#!/bin/zsh

echo "$(date) Running script $0 to create folders."

TOOLS_FOLDER=$1
REPORTS_FOLDER=$2
HELP_FOLDER=$3

TOOLS_FOLDER_CREATED=".$TOOLS_FOLDER-FolderCreated"
REPORTS_FOLDER_CREATED=".$REPORTS_FOLDER-FolderCreated"
HELP_FOLDER_CREATED=".$HELP_FOLDER-FolderCreated"

TODAY=$(date)
PATH_TO_LOG="$HOME/Library/Logs/folderCreator_log_v1-1.log"

echo "$(date) Starting" >> $PATH_TO_LOG

cd $HOME

echo "$(date) Creating folders: $TOOLS_FOLDER, $REPORTS_FOLDER, $HELP_FOLDER" >> $PATH_TO_LOG
mkdir $TOOLS_FOLDER
mkdir $REPORTS_FOLDER
mkdir $HELP_FOLDER

echo "$(date) Creating hidden file for $TOOLS_FOLDER folder." >> $PATH_TO_LOG
cd $TOOLS_FOLDER
touch $TOOLS_FOLDER_CREATED
cd ..

echo "$(date) Creating hidden file for $REPORTS_FOLDER folder." >> $PATH_TO_LOG
cd $REPORTS_FOLDER
touch $REPORTS_FOLDER_CREATED
cd ..

echo "$(date) Creating hidden file for $HELP_FOLDER folder." >> $PATH_TO_LOG
cd $HELP_FOLDER
touch $HELP_FOLDER_CREATED
cd ..

echo "$(date) Task completed. Have a nice day!"

The final script should look like:

#!/bin/zsh
echo "$(date) Running script $0 to create folders."
TOOLS_FOLDER=$1
REPORTS_FOLDER=$2
HELP_FOLDER=$3
TOOLS_FOLDER_CREATED=".$TOOLS_FOLDER-FolderCreated"
REPORTS_FOLDER_CREATED=".$REPORTS_FOLDER-FolderCreated"
HELP_FOLDER_CREATED=".$HELP_FOLDER-FolderCreated"
TODAY=$(date)
PATH_TO_LOG="$HOME/Library/Logs/folderCreator_log_v1-1.log"
echo "$(date) Starting" >> $PATH_TO_LOG
cd $HOME
echo "$(date) Creating folders: $TOOLS_FOLDER, $REPORTS_FOLDER, $HELP_FOLDER" >> $PATH_TO_LOG
mkdir $TOOLS_FOLDER
mkdir $REPORTS_FOLDER
mkdir $HELP_FOLDER
echo "$(date) Creating hidden file for $TOOLS_FOLDER folder." >> $PATH_TO_LOG
cd $TOOLS_FOLDER
touch $TOOLS_FOLDER_CREATED
cd ..
echo "$(date) Creating hidden file for $REPORTS_FOLDER folder." >> $PATH_TO_LOG
cd $REPORTS_FOLDER
touch $REPORTS_FOLDER_CREATED
cd ..
echo "$(date) Creating hidden file for $HELP_FOLDER folder." >> $PATH_TO_LOG
cd $HELP_FOLDER
touch $HELP_FOLDER_CREATED
cd ..
echo "$(date) Task completed. Have a nice day!"

Script locations

One last thing to talk about now is script locations. So far we have been placing our scripts where ever we wish and running them from there. But it may be a good idea to use a consistent location for the same. There are several candidates for this:

  • ~/Library/Scripts/
  • /Library/Scripts/

These are the more standard locations.

The only decision that needs to be made is whether it is the Library folder in the user’s home folder or the library folder located at root. This affects if the script is available only for a specific user or for all users on a computer.

There are other locations possible too. Developers often have a folder in the home folder called “Developer”. This needs to be manually created, but once created the system recognises it as the folder where files related to development are kept. You can create a scripts folder and place it in there.

Another popular location is the Application Support folder within the library folder. You can create a folder that represents items related to your scripts and then place the script in that folder. Note that these folders will have to be created by manually.

  • ~/Developer/Scripts/
  • ~/Library/Application Support/<your folder>/

These 2 locations would need to be created.

Scripts are not typically exposed to the end user. There is typically some kind of scheduling mechanism that triggers them. However, if a script is designed to be used by the end user you could even place them in:

  • /Applications/Scripts/
  • ~/Applications/Scripts/

Like the developer folder the applications folder in the home folder needs to be created. But once created the system recognises what it is intended for and gives it special privileges. The scripts folder within it will have to be created manually.

While this may not seem like a big deal. Placing your scripts in the correct location can lead to more consistent experiences, make troubleshooting easy, and also hide potential complexity.

Conclusion

The ability to store data within a script, pass data to a script or store data on an external file from within a script has several advantages. This makes the script more power and compact at the same time. It also makes the script less susceptible to errors and mistakes.

Video

Download

You can download the script from the same git repository as the previous one. The script is named folderCreator_v1-1.zsh.

Programming Style Guide: Naming Conventions

Today we are going to look at Naming conventions you can follow while writing code.

Naming conventions lay down the basic rules for naming different elements in your code. The objectives are simple:

  • Make the element easy to read
  • Should be self explanatory
  • Should contain information in a compact and concise manner.

Ideally a well named variable or function should not need a comment to explain what it is for.

With the above objectives in mind let us look at some of the naming conventions that can be followed. The examples are from the Swift & C++ programming languages.

Naming Conventions

Camel Case Names

In camel case naming convention the entire name of the element is constructed by forming a sentence joined into a single word. So for example if we have a variable for keeping track of the price of oil in US dollars then the variable name might be priceOfOilUSD.

Here are some examples of naming conventions with the camel case.

SWIFT

var priceOfOil : Float = 23.49

C++

float priceOfOil = 3.45;
class PersonInfo
{

};

Underscore Separated Names

In the underscore separated naming convention the entire name of the element is constructed by forming a sentence joined together with the help of underscores in-between them. So if we take the example of the variable keeping track of the price of oil in US dollars the the variable name might be price_of_oil_usd.

Swift

var price_of_oil : Float = 45.71

C++

float price_of_oil = 99.87;

void print_value_of_pi()
{
     //print something
}

Names with type information

A naming convention that is quite popular is the one that mixes the previous 2 naming conventions, with the underscore used to separate the type description in the prefix. So if we take the example of the variable keeping track of the price of oil in US dollars then the variable name might be f_priceOfOil or float_priceOfOil. Either of the design styles work. The prefix is popularly abbreviated and you can create your own rules for abbreviating the type description.

This style is often referred to as the Hungarian notation. The additional information that is provided as a part of the prefix can be:

  • Whether the variable is a pointer
  • Whether the variable is an object
  • The scope of the variable
  • Type size
  • Whether the data can vary or is a constant

Swift

var f_priceOfOil : Float = 0.0

C++

float f_priceOfOil = 22.3;
int *ptr_memmoryBuffer = NULL; //ptr indicates variable is a pointer

Naming Rules

There are some rules that are typically followed while designing names for variables and  functions. Like the conventions themselves the rules are not binding but they are very useful an give the added punch that naming conventions provide.

  1. Variable names always start in lower case.
  2. Type names always start in upper case.
  3. The naming conventions is consistently applied through all the projects
  4. Names should be kept as small as possible without sacrificing on the description

Naming Strategies

As far as strategies are concerned there are multiple approaches that one can follow. Here are some potential strategies.

  • Follow one naming convention for variables and another convention for functions.
  • Let constants be all upper case
  • Prefix types with your companies initials.

Summary

The above illustrate just some of the naming conventions that can be followed. By no means are they comprehensive or complete. Also it is not necessarily true that everyone follows the above naming conventions. You may find that many software development firms have their own unique naming convention. This article should give you an an idea about naming conventions. Feel free to share some naming conventions that you have come across.

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

Creating multi-OS Install Disk

In this article we are going to look at how to create a multi-OS Install Disk. We are going to look at the example of creating a multi-OS Install Disk for the following versions of the OS:

  • 10.9.1
  • 10.10
  • 10.10.4
  • 10.11.5
  • 10.12
  • 10.12.1
  • 10.12.2
  • 10.12.3

The idea is to have a single disk with multiple versions of the Install Disk on it. The versions should reflect the need of the organisation.

REQUIREMENTS

  1. USB Drive at least 75GB in Size. This depends on the number of Install drives you wish to have. At the very least there should be enough space to create 2 partitions of 8 GB each. 
    While I have mentioned USB drive, it need not be restricted to that interface. You can use Thunderbolt, FireWire or even an SDXC slot for this. Ideally the port should be one that is supported on maximum possible computers.
  2. Install setup for each version of the OS for which you want to create the install disk. The setup must match the version desired.
  3. A Mac running the same major version of the OS. You can only create an install disk for 10.9.x on a Mac running OS X 10.9.x, the same applies for the other versions of the OS.

The process is the same. It’s just that it needs to be repeated.

STEPS

  1. Create 8 partitions on a USB Drive. Assume that the USB Drive is called Recovery Drive. Give the partitions names Partition 1, Partition 2,….
  2. Connect the USB Drive to a Mac running 10.9.1 or later.
  3. Make sure that the OS Installer setup is located in the Applications folder.
  4. Run the following command in the command line.
    sudo /Applications/Install\ OS\ X\ Mavericks.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 1 --applicationpath  /Applications/Install\ OS\ X\ Mavericks.app
  5. Rename the partition as Install disk for OS X 10.9.1, if necessary.
  6. Once completed eject the USB Drive & connect it to a Mac running 10.10
  7. Make sure that the OS Installer setup is located in the Applications folder.
  8. Run the following command in the command line.
    sudo /Applications/Install\ OS\ X\ Yosemite.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 2 --applicationpath  /Applications/Install\ OS\ X\ Yosemite.app
  9. Rename the partition as Install disk for OS X 10.10, if necessary.
  10. Once completed eject the USB Drive & connect it to a Mac running 10.10.4
  11. Make sure that the OS Installer setup is located in the Applications folder.
  12. Run the following command in the command line.
    sudo /Applications/Install\ OS\ X\ Yosemite.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 3 --applicationpath  /Applications/Install\ OS\ X\ Yosemite.app
  13. Rename the partition as Install disk for OS X 10.10.4, if necessary.
  14. Once completed eject the USB Drive & connect it to a Mac running 10.11.5 or later.
  15. Make sure that the OS Installer setup is located in the Applications folder.
  16. Run the following command in the command line.
    sudo /Applications/Install\ OS\ X\ El\ Capitan.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 4 --applicationpath  /Applications/Install\ OS\ X\ El\ Capitan.app
  17. Rename the partition as Install disk for OS X 10.11.5, if necessary.
  18. Once completed eject the USB Drive & connect it to a Mac running 10.12 or later.
  19. Make sure that the OS Installer setup is located in the Applications folder.
  20. Run the following command in the command line.
    sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 5 --applicationpath  /Applications/Install\ macOS\ Sierra.app
  21. Rename the partition as Install disk for OS X 10.12., if necessary.
  22. Once completed eject the USB Drive & connect it to a Mac running 10.12.1 or later.
  23. Make sure that the OS Installer setup is located in the Applications folder.
  24. Run the following command in the command line.
    sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 6 --applicationpath  /Applications/Install\ macOS\ Sierra.app
  25. Rename the partition as Install disk for OS X 10.12.1., if necessary.
  26. Once completed eject the USB Drive & connect it to a Mac running 10.12.2 or later.
  27. Make sure that the OS Installer setup is located in the Applications folder.
  28. Run the following command in the command line.
    sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 7 --applicationpath  /Applications/Install\ macOS\ Sierra.app
  29. Rename the partition as Install disk for OS X 10.12.2, if necessary.
  30. Once completed eject the USB Drive & connect it to a Mac running 10.12.3 or later.
  31. Make sure that the OS Installer setup is located in the Applications folder.
  32. Run the following command in the command line.
    sudo /Applications/Install\ macOS\ Sierra.app/Contents/Resources/createinstallmedia --volume /Volumes/Partition\ 8 --applicationpath  /Applications/Install\ macOS\ Sierra.app
  33. Rename the partition as Install disk for OS X 10.12.3, if necessary.

The commands shown above might be different from what appears on your screen. A lot will depend on what you have named your partitions as, the name you may have given to the OS Installer file, and the location of the OS Installer.

The process of renaming the partitions post creation of the install disk is not necessary, but very useful because that will help you identify the appropriate partition when using the drive.

The above process is very scalable & can be done for even more versions of the OS if required.

Screen Shot 2017-04-17 at 11.11.39 AM
This diagram illustrates the layout of the different partitions on a single USB Drive.

Creating Frameworks for iOS/OS X App Development

Creating Swift Frameworks

Creating Swift Frameworks is easy. The steps below walk you through creating a Swift Framework. The steps below have been performed on Xcode 7.3

  1. Launch Xcode.
  2. Select Create New Project. Or from the menu bar select File > New > Project
  3. From the Template chooser select the Framework & Library  Option under iOS
  4. Select Cocoa Touch Framework1
  5. Give your project a name.
  6. Make sure the language selected is Swift.
  7. Feel free to enter values of your choice for organisation name and organisation identifier.
  8. Save your project. Optionally, if you have a version control repository like Git you may save it there.
  9. In left hand side bar make sure you have selected the Project Navigator.
  10. Within the Project Navigator make sure you have selected the folder named after your project.
  11. Click on File > New > File.
  12. Make sure iOS Source is selected on the left hand side.
  13. Select the file type as Swift.IMG_3525
  14. Write down the code that you want to make available through a framework.
  15. Now this is the key point. Place the keyword public before all the elements that you want to make publicly accessible.Why do we need to do this? To understand this we need to understand the scope of different elements within a typical Swift project. IMG_3521

    Different variables/classes/functions that are declared within a module are accessible freely within the module. Swift files contain code & are themselves found within Swift modules. So a module can mean project or a framework.So, to access the variables/functions/classes from module A in module B, we have to make those elements of module A public in order to access them in module B.

    For more information, do read Apple’s Swift Documentation.

  16. The next steps depend on what your ultimate objective is. If you wish to build a framework for distribution then you need to follow a process that is similar to distributing an app. You need to get the code signing done & prepare the project for distribution.
  17. If however, you plan to release it internally, or even just test it. Then you can follow the steps below.
  18. Firstly, our objective is to make this framework run on both OS X(macOS) as well as iOS.
  19. To do that we will be adding a new target. Click on File > New > Target.
  20. Select OS X & the Frameworks & Libraries from the sidebar.
  21. Select Cocoa Touch Framework
  22. Give your framework a unique name. Something that indicates this framework is for OS X(macOS).
  23. Now, we don’t need to rewrite the code for the Mac. We can simply make the file we have written a member for the OS X Framework Target.
  24. To do that make sure that the right hand side sidebar is visible.
  25. In the left hand side sidebar make sure that you have selected the new Swift file with the code you have written in there.
  26. In the right hand side sidebar select the Document Inspector.
  27. Under Target Membership make sure that both the Targets are checked. The target for iOS should already be checked.IMG_3520
  28. Thats it. If you do not wish to make your code available for both iOS & OS X then skip steps 19 – 27.
  29. The next part is building the framework. We will be building this framework for use internally. We will first build the iOS framework.
  30. From the tool bar, make sure the target selected is for iOS. For the device you can select any device that you wish.
  31. Then click on Product > Build to build the framework. If all goes well then you should get the message Build Succeeded on your screen.
    IMG_3519
  32. To get hold of the framework, expand the product folder from the left hand side sidebar.
  33. Select the Framework you have just built. Note that it should be black in colour. If you have opted to make a framework for OS X, then you should see that framework listed too, it should be in red colour. The red colour indicates that it has not yet been built.IMG_3524
  34. Control-click on the iOS version of the framework and select Show in Finder.
  35. This will take you directly to the folder containing the framework. Copy paste it to the desktop or to any other location to easily access it when required.
  36. Repeat steps 30 – 34 to build the OS X version of the Framework. Make sure that the target selected is OS X.
  37. Once we have done that, we need to test the framework we just created.
  38. Create a dummy iOS Project for testing.
  39. From the left hand side project navigator make sure that the blue project settings file is selected.
  40. Make sure that the Target is selected within the settings screen.
  41. Under the General tab scroll down to the Embedded Binaries section.
  42. Click on the ‘+’ sign to add a framework.IMG_3523
  43. Click on Add other
  44. Navigate to the folder where you saved the Framework and select it.
  45. Click Open
  46. Select Copy Items if needed
  47. The framework should be added to your project.
  48. In the ViewController.swift file import your Framework: import CustomStack
  49. Replace CustomStack with your frameworks name.
  50. Try to write the code which uses the elements you have packaged within the framework.

Creating Mixed Frameworks (Swift & Objective-C)

The process of creating a mixed library is straightforward. Its almost the same as above with some minor differences.

  1. Follow the steps mentioned above to add your Swift Code.
  2. Add your objective-C files to the project.
  3. While adding the files make sure that the checkbox for the targets is selected appropriately. Screen Shot 2016-08-05 at 1.20.37 PM
  4. Write the code that you wish to write in Objective-C. Of course, if you are including prewritten files then you do not need to do this.
  5. To make the Objective-C code accessible in Swift you need to make the following changes:
    1. In the umbrella header of your framework add the line to import the header
      #import "<FrameworkName>/<HeaderName>.h
    2. Modify the access property located within the target membership of the Objective-C header file. IMG_3527
  6. This should make your Objective-C code accessible to the Swift files.
  7. Test the changes by accessing your Objective-C code in your Swift files within the framework.
  8. Test the changes further by embedding your mixed language framework into a project & then try to access both the Swift as well as Objective-C versions of the code in your new project.
  9. To make your Swift code accessible to Objective-C File make the following changes:
    1. Make sure that your Swift code is compatible with Objective-C. There are 2 ways of doing this. One you can make your Swift class inherit from NSObject. The second way is to use the @objc keyword before your class declaration.
    2. In the Objective-C header file add the line to add the bridging header which is auto generated. You do not need to create your own bridging header.
      #import "<FrameworkName>/<FrameworkName>-Swift.h"

      Replace the word FrameworkName with the name of your Framework.

    3. This should allow you to access your Swift code in your Objective-C header file within the same Framework Project.
  10. This way you can make a single framework which contains code written in both Swift & Objective-C.

 

 

What to do before buying/selling Apple devices?

Apple’s devices are getting more and more popular by the day. People are really excited to get hold of the newest product that comes out of its stable. This guide walks you through some of the things you need to keep in mind while buying used devices or selling your existing device. This may not apply when buying a new product from the store for the first time, however, its still good to know these things & run your device through a checklist.

Note the checklist provided below is by no means comprehensive nor is it complete. There might be other things to keep in mind before buying &/or selling used devices, depending on the geographic area, situation, and circumstances.

Buying

Before buying a used products run them through this checklist. Some items are device specific.

  • Make sure there is no physical damage to the device. Dents, scratches, cracks, missing screws.
  • Start the device & make sure it loads up as expected.
  • Check the different user interface elements: touch screen, 3d touch, keyboard, iSight camera, speakers, home button, Microphone
  • Check the different ports: USB, Ethernet, FireWire, Thunderbolt, USB-C, HDMI, Audio-out, SD card reader, lightning connector, 30-pin connector
  • Check the power cord, adapter & charging port
  • Note the version of the OS. Eg: OS X 10.10.3
  • Note the build number
  • Check the model number. This is important for Software Upgrades/Hardware upgrades. Older hardware may have an upper limit on the hardware expansion capability &/or the ability to run latest software optimally.
  • Check the Support Coverage for your device. This is important, especially if you have to take your device in for repairs.
    https://checkcoverage.apple.com/in/en/
    https://support.apple.com/en-us/HT204308 – Find your devices Serial Number
  • Note down the serial number
  • Make sure that the device does not contain any personal data belonging to the seller. While it is the sellers responsibility to ensure this, it still is a good idea to verify that there are no accounts are signed into. This is VERY IMPORTANT for iOS Devices due to its implications on Activation Lock.
    Activation lock is used to prevent anyone from using a stolen device: https://support.apple.com/en-us/HT201365
  • Before buying please check the Activation lock status: https://www.icloud.com/activationlock/
  • Make sure there is no personal digital content in the form of Apps/Song/Movies or documents.
  • For Mac, make sure that there is no Firmware Password that is set.

Selling

The list above should give you a good idea on what you need to do while planning to sell your Apple device.

  • Delete all personal data. Make sure you have a backup of the same.
  • Remove any applications you may have installed.
  • Sign out of all accounts: Gmail, Hotmail, Facebook, iCloud, Apple ID…
  • Delete any user accounts you may have created. Leave a single admin account.
  • If you have used any Encryption service then make sure you turn off encryption before selling the device. This is more of a precaution to prevent issues that may arise in the future.
  • This article illustrates what to do if you are selling giving away iOS Devices: https://support.apple.com/en-in/HT201351
  • As a good measure, delink your Apple ID from your device. You can do this by:
    • Go to http://www.icloud.com
    • Sign in with your Apple ID
    • Click on Settings
    • Select the device you want to give away: IMG_2941
    • Click on the cross to remove it from your Apple IDIMG_2978
  • De-register from iMessage.
  • Remove any custom settings, passwords (Firmware Password) that may compromise your security or prevent the user from fully using the device.
  • As a good measure completely erase the hard drive of your device.
  • Document items such as OS Version, Serial Number for your own reference.

Enterprises may take additional steps

  • To ensure data security, Enterprises may perform Secure Erase or drive replacement to prevent recovery of corporate information, when assigning devices to employees or selling them out in the market.
  • Enterprises should also protect against Activation lock. When collecting iOS Devices, assigned to an employee who is leaving the organisation, always check to make sure that the device is not locked to the employees Apple ID.

These are some of the things that you can do to make the transaction easy on both the sides.