05 - Further Programming Recap


More advanced topics in programming are perhaps one of our most difficult sections in this course primarily because it's a little dry. There are no actual apps here, but we still need to learn all of these concepts very well. In doing so, we need to dive further into programming. And learn the following concepts:


  • Classes and Objects

  • Inheritance

  • Initialize (& de-initialize)

  • Protocols & Categories

  • Class Extensions

  • Class Methods

  • Properties

  • Closures (& Completion Blocks)

  • Type Casting

  • Timers

  • Getting Help

  • Selectors (& Class Type)


OOP

OOP is a fundamental concept. OOP is a programming paradigm that can be defined as a contrast to other programming paradigms:


There are four main coding paradigms

  • Functional which view programs as mathematical formulas

  • Imperative that view a program as a series of instructions

  • Logical that is a model of information and the relationship between them

  • OOP, where objects represent models and their interactions, handle data.


  • In OOP, you have instructions that can build something. Those we call a class.

  • When we create an instance of that class, that we call an object.

  • Each class has a set of attributes and methods.

  • Attributes are things that a class has and subsequently, their objects have.

  • Methods are functions that instances of a class can do.


Classes

The next thing we have to learn is how to use the functions and attributes of a class in an object. We first have to learn about initializing a class. We should also know how to use classes within the same file or spread them in separate files. Instantiate objects from a class is a process in which we make objects from our classes.


Classes in Objective-C

Similar to Swift, we can add classes in Objective-C which would require @interface and @implementation. We can then use these definitions to instantiate our objects. Unlike Swift, ObjC classes must have a base class. In the past, you have seen it when we used UIViewController Class and one of the most basic root classes is NSObject. Which is like a founding father of many classes. If you don’t know what base class you need, then you need NSObject.


Object Inisitializations

In classes, you can add multiple different inits. You can make them required or convenience. There is a default init() associated with all classes. Inits from superclasses can also be overridden

If you have overridden an init, you can no longer use the init()

Swift automatically deallocates your instances when they are no longer needed


De-init

Optionally classes may have a deinit method for deinitialization

You could use the deinit method with no argument for some very specific purposes. For further learning please refer to:

https://docs.swift.org/swift-book/LanguageGuide/Initialization.html

And

https://docs.swift.org/swift-book/LanguageGuide/Deinitialization.html


Guard

Guard a programming structure to make sure some value actually exists. Guard in many ways is similar to an if let process. The only difference is that in guard if the value (or values) that you want don’t exist, the function should return.


Convenience inits

Convenience initializers are supporting initializers to create an instance of that class for a specific use case or input value type. We often use convenience inits when we want to populate the initial values of an object using a set of values (mostly a dictionary)


Inheritence

Inheritance is about subclassing and overriding parent class methods and adding custom inits to the subclasses. To override a characteristic that would otherwise be inherited, you prefix your overriding definition with the override keyword. Doing so clarifies that you intend to provide an override and have not provided a matching definition by mistake. Subclasses can have their own attributes and functions. They can also override the base class’s functions. Further Reading: https://docs.swift.org/swift-book/LanguageGuide/Inheritance.html


Enumerations

Enumerations (or enums) are used to define a group of related values in a type-safe way. The reason they are type-safe is simply that their values are constrained. Please read more on Enumeration in: https://docs.swift.org/swift-book/LanguageGuide/Enumerations.html



Structures in Swift

Structs in Swift are very similar to that of Classes. The two big difference is:

  • Structs cannot have a base class

  • Structs pass the value while classes pass the reference

  • As a result, classes are a lot larger and slower

As a rule of thumb, if you can get away with structs, use them, if not, use a class


Selectors

In Objective-C we use respondsToSelector: to determine at runtime if an object knows how to handle a given message.

We will also use the isKindOfClass in Objective-C to learn about the type of an object.


Protocols

A protocol as the name implies is the blueprint of methods, properties, and other requirements that handle a certain task. They are then adopted by class, structure, or enumeration to do the actual work.

Unlike Objective-C, swift doesn’t have optional functions in a protocol. If you need an optional function, you must leave its body empty.

The protocol only specifies the required property name and type. Not whether it should be stored or computed.

Protocols contain no logic. They are simply definitions of methods, no implementations. Further reading: https://docs.swift.org/swift-book/LanguageGuide/Protocols.html


Delegation

Delegation is a very commonly used pattern in iOS development. The delegate design pattern is a pattern that uses protocols. Delegation is when an object delegates some of its behavior or control to another object using a protocol and it is often used when an object needs to communicate information or request information from another object.

In setting delegations for outlets, you could either add them by code using the .delegate, or in the storyboard by dragging over the view controller outlet. A text field for instance has many different delegates. It means many different protocols are being conformed in it.


Categories in Objective-C

We will talk about the private categories in View Controllers used to declare private properties and methods. These are not exposed to any class outside this one.


Categories

Categories are used when you want to add methods to classes. We use them for mathematical stuff or when we need new functionalities

A question to ask yourself might be what is the difference between a category and a subclass?


Extension

We use a class extension for breaking our code into so many pieces and modularizing it. These extensions in swift are the same as categories in Objective-C. In a real development in swift, we depend heavily on class extensions. Further reading at https://docs.swift.org/swift-book/LanguageGuide/Extensions.html


Class Methods

Class methods are used to enact a function directly from a class and not an instanced object of it. Class and Static keywords have similar roles. Both the static and class keywords allow us to attach variables to a class rather than to instances of a class.

Where static and class differ is how they support inheritance. When you make a static property it becomes owned by the class and cannot be changed by subclasses, whereas when you use class it may be overridden if needed. You can read further about this on https://www.hackingwithswift.com/example-code/language/whats-the-difference-between-a-static-variable-and-a-class-variable


Reference Counting

Understanding various property attributes such as weak or retain is an important aspect of reference counting and memory management for iOS.

ARC is XCode approach of memory management. It basically means when would the memory free up of an object.

All variables are strong by default. We use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization. You can read further about unowned references in this link:

https://agostini.tech/2017/07/23/memory-management-in-swift-the-strong-the-weak-and-the-unowned/



Here is also a little comparison of all variable property attributes:

  • weak -  it says "keep this as long as someone else points to it strongly

  • atomic - multi-threaded. Locks the value before any changes. so it turns something, even though it may not be correct

  • nonatomic - a single thread. Doesn’t lock the value, it clears it in the process of adding a new one. As a result, you might get nil

  • Retain is a pointer to an object. The setter will add a retain count to the object

  • Assign: When calling the getter of an assign property, it returns a reference to the actual data.


To read on this important topics, please visit:

https://stackoverflow.com/questions/8927727/objective-c-arc-strong-vs-retain-and-weak-vs-assign


Timer

We use the built-in Timer class to count time in a variety of formats.


Closure

Closures are important elements of swift programming. They help with dynamic variables as well as completion blocks (using Escaping Closures)

Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages

Closures are self-contained blocks of functionality that can be passed around and used in your code.

Closures are particularly useful when you work with functions or methods that take functions as one or more of their arguments

You can read further about closures in https://docs.swift.org/swift-book/LanguageGuide/Closures.html



Wrap Up

Doubles are similar to floats with more precision.

NSNumber and its superclass NSValue are container objects for keeping numeric (or otherwise) values.

We can use keywords such as the following to set regions in our code

  • Pragma Mark (Objective-C)

  • MARK

  • TODO

  • FIXME