
Domains
Agile Management
Master Agile methodologies for efficient and timely project delivery.
View All Agile Management Coursesicon-refresh-cwCertifications
Scrum Alliance
16 Hours
Best Seller
Certified ScrumMaster (CSM) CertificationScrum Alliance
16 Hours
Best Seller
Certified Scrum Product Owner (CSPO) CertificationScaled Agile
16 Hours
Trending
Leading SAFe 6.0 CertificationScrum.org
16 Hours
Professional Scrum Master (PSM) CertificationScaled Agile
16 Hours
SAFe 6.0 Scrum Master (SSM) CertificationAdvanced Certifications
Scaled Agile, Inc.
32 Hours
Recommended
Implementing SAFe 6.0 (SPC) CertificationScaled Agile, Inc.
24 Hours
SAFe 6.0 Release Train Engineer (RTE) CertificationScaled Agile, Inc.
16 Hours
Trending
SAFe® 6.0 Product Owner/Product Manager (POPM)IC Agile
24 Hours
ICP Agile Certified Coaching (ICP-ACC)Scrum.org
16 Hours
Professional Scrum Product Owner I (PSPO I) TrainingMasters
32 Hours
Trending
Agile Management Master's Program32 Hours
Agile Excellence Master's ProgramOn-Demand Courses
Agile and ScrumRoles
Scrum MasterTech Courses and Bootcamps
Full Stack Developer BootcampAccreditation Bodies
Scrum AllianceTop Resources
Scrum TutorialProject Management
Gain expert skills to lead projects to success and timely completion.
View All Project Management Coursesicon-standCertifications
PMI
36 Hours
Best Seller
Project Management Professional (PMP) CertificationAxelos
32 Hours
PRINCE2 Foundation & Practitioner CertificationAxelos
16 Hours
PRINCE2 Foundation CertificationAxelos
16 Hours
PRINCE2 Practitioner CertificationSkills
Change ManagementMasters
Job Oriented
45 Hours
Trending
Project Management Master's ProgramUniversity Programs
45 Hours
Trending
Project Management Master's ProgramOn-Demand Courses
PRINCE2 Practitioner CourseRoles
Project ManagerAccreditation Bodies
PMITop Resources
Theories of MotivationCloud Computing
Learn to harness the cloud to deliver computing resources efficiently.
View All Cloud Computing Coursesicon-cloud-snowingCertifications
AWS
32 Hours
Best Seller
AWS Certified Solutions Architect - AssociateAWS
32 Hours
AWS Cloud Practitioner CertificationAWS
24 Hours
AWS DevOps CertificationMicrosoft
16 Hours
Azure Fundamentals CertificationMicrosoft
24 Hours
Best Seller
Azure Administrator CertificationMicrosoft
45 Hours
Recommended
Azure Data Engineer CertificationMicrosoft
32 Hours
Azure Solution Architect CertificationMicrosoft
40 Hours
Azure DevOps CertificationAWS
24 Hours
Systems Operations on AWS Certification TrainingAWS
24 Hours
Developing on AWSMasters
Job Oriented
48 Hours
New
AWS Cloud Architect Masters ProgramBootcamps
Career Kickstarter
100 Hours
Trending
Cloud Engineer BootcampRoles
Cloud EngineerOn-Demand Courses
AWS Certified Developer Associate - Complete GuideAuthorized Partners of
AWSTop Resources
Scrum TutorialIT Service Management
Understand how to plan, design, and optimize IT services efficiently.
View All DevOps Coursesicon-git-commitCertifications
Axelos
16 Hours
Best Seller
ITIL 4 Foundation CertificationAxelos
16 Hours
ITIL Practitioner CertificationPeopleCert
16 Hours
ISO 14001 Foundation CertificationPeopleCert
16 Hours
ISO 20000 CertificationPeopleCert
24 Hours
ISO 27000 Foundation CertificationAxelos
24 Hours
ITIL 4 Specialist: Create, Deliver and Support TrainingAxelos
24 Hours
ITIL 4 Specialist: Drive Stakeholder Value TrainingAxelos
16 Hours
ITIL 4 Strategist Direct, Plan and Improve TrainingOn-Demand Courses
ITIL 4 Specialist: Create, Deliver and Support ExamTop Resources
ITIL Practice TestData Science
Unlock valuable insights from data with advanced analytics.
View All Data Science Coursesicon-dataBootcamps
Job Oriented
6 Months
Trending
Data Science BootcampJob Oriented
289 Hours
Data Engineer BootcampJob Oriented
6 Months
Data Analyst BootcampJob Oriented
288 Hours
New
AI Engineer BootcampSkills
Data Science with PythonRoles
Data ScientistOn-Demand Courses
Data Analysis Using ExcelTop Resources
Machine Learning TutorialDevOps
Automate and streamline the delivery of products and services.
View All DevOps Coursesicon-terminal-squareCertifications
DevOps Institute
16 Hours
Best Seller
DevOps Foundation CertificationCNCF
32 Hours
New
Certified Kubernetes AdministratorDevops Institute
16 Hours
Devops LeaderSkills
KubernetesRoles
DevOps EngineerOn-Demand Courses
CI/CD with Jenkins XGlobal Accreditations
DevOps InstituteTop Resources
Top DevOps ProjectsBI And Visualization
Understand how to transform data into actionable, measurable insights.
View All BI And Visualization Coursesicon-microscopeBI and Visualization Tools
Certification
24 Hours
Recommended
Tableau CertificationCertification
24 Hours
Data Visualization with Tableau CertificationMicrosoft
24 Hours
Best Seller
Microsoft Power BI CertificationTIBCO
36 Hours
TIBCO Spotfire TrainingCertification
30 Hours
Data Visualization with QlikView CertificationCertification
16 Hours
Sisense BI CertificationOn-Demand Courses
Data Visualization Using Tableau TrainingTop Resources
Python Data Viz LibsCyber Security
Understand how to protect data and systems from threats or disasters.
View All Cyber Security Coursesicon-refresh-cwCertifications
CompTIA
40 Hours
Best Seller
CompTIA Security+EC-Council
40 Hours
Certified Ethical Hacker (CEH v12) CertificationISACA
22 Hours
Certified Information Systems Auditor (CISA) CertificationISACA
40 Hours
Certified Information Security Manager (CISM) Certification(ISC)²
40 Hours
Certified Information Systems Security Professional (CISSP)(ISC)²
40 Hours
Certified Cloud Security Professional (CCSP) Certification16 Hours
Certified Information Privacy Professional - Europe (CIPP-E) CertificationISACA
16 Hours
COBIT5 Foundation16 Hours
Payment Card Industry Security Standards (PCI-DSS) CertificationOn-Demand Courses
CISSPTop Resources
Laptops for IT SecurityWeb Development
Learn to create user-friendly, fast, and dynamic web applications.
View All Web Development Coursesicon-codeBootcamps
Career Kickstarter
6 Months
Best Seller
Full-Stack Developer BootcampJob Oriented
3 Months
Best Seller
UI/UX Design BootcampEnterprise Recommended
6 Months
Java Full Stack Developer BootcampCareer Kickstarter
490+ Hours
Front-End Development BootcampCareer Accelerator
4 Months
Backend Development Bootcamp (Node JS)Skills
ReactOn-Demand Courses
Angular TrainingTop Resources
Top HTML ProjectsBlockchain
Understand how transactions and databases work in blockchain technology.
View All Blockchain Coursesicon-stop-squareBlockchain Certifications
40 Hours
Blockchain Professional Certification32 Hours
Blockchain Solutions Architect Certification32 Hours
Blockchain Security Engineer Certification24 Hours
Blockchain Quality Engineer Certification5+ Hours
Blockchain 101 CertificationOn-Demand Courses
NFT Essentials 101: A Beginner's GuideTop Resources
Blockchain Interview QsProgramming
Learn to code efficiently and design software that solves problems.
View All Programming Coursesicon-codeSkills
Python CertificationInterview Prep
Career Accelerator
3 Months
Software Engineer Interview PrepOn-Demand Courses
Data Structures and Algorithms with JavaScriptTop Resources
Python TutorialIn order to monitor and handle the memory usage of your app, Swift utilizes Automatic Reference Counting (ARC). As a programmer, you are not required to think about memory management as it is being taken care of by ARC. If such instances are no longer required, ARC automatically releases the memory used by class instances.
In a few instances, however, ARC needs further data on the connections between components of your code to handle your memory.
ARC allocates a piece of memory for storing data every time you generate a fresh class instance . This memory contains data on the type of class and any stored characteristics connected with that instance.
ARC assures an additional property of class instances which no longer take up memory space when they are not required, and hence the space can be utilized for some other purposes.
However, In case if ARC deallocates an instance that was already being used, the instance's properties would no longer be accessed. Infact , if the user attempted to achieve the above kind of instance, the app would most probably crash.
ARC monitors the number of properties , constants and variables presently referred to each class instance , to ensure that instances do not vanish as required. As long as at least one active reference exists still, ARC will not deallocate an instance.To enable this, property, constant or variable refers strongly to instance where the user assigns a class instance to a property, constant or variable. The reference is called a "strong" reference . It is being referred as strong here since the instance does not allow it to be distributed for as long as it remains a same i:s“Strong reference”.
Example
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
ARC Strong Reference Cycles Class Instances
class studmarks {
let name:String
var stud: student?
init (name:String){
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
class student {
let name:String
var strname: studmarks?
init (name:String){
print("Initializing: \(name)")
self.name = name
}
deinit {
print("Deallocating: \(self.name)")
}
}
var shiba: studmarks?
var mari: student?
shiba = studmarks(name:"Hello")
mari = student(name:"ARC")
shiba!.stud = anushka
mari!.strname = Swati
These references are used to allow an individual instance in a reference process to refer to other instances. Instead of taking great care of the strong reference cycle, the instance may refer to every single instance. If the user understands that a certain instance can return nil, we can point out that the weak reference is used. If something is returned instead of nil, then declare it with an unknown reference.
Weak Reference
classmodule{
let name:String
init(name:String){self.name = name }
varsub: submodule?
deinit {print("\(name) Is The Main Module")}
}
class submodule {
let number:Int
init(number:Int){self.number = number }
weak var topic:module?
deinit {print("Sub Module with its topic number is \(number)")}
}
var toc:module?
var list: submodule?
toc =module(name:"ARC")
list = submodule(number:4)
toc!.sub= list
list!.topic = toc
toc =nil
list =nil
The output of the above program would be
ARC Is The Main Module
Sub Module with its topic number is 4
Unowned References
class student {
let name: String
var section: marks?
init(name: String) {
self.name = name
}
deinit { print("\(name)") }
}
class marks {
let marks: Int
unowned let stname: student
init(marks: Int, stname: student) {
self.marks = marks
self.stname = stname
}
deinit { print("Marks Obtained by the student is \(marks)") }
}
var module: student?
module = student(name: "ARC")
module!.section = marks(marks: 98, stname: module!)
module = nil
The output of the above program would be
ARC
Marks Obtained by the student is 98
Strong Reference Cycles for Closures
When we actually assign a closure statement to the class instance property and to the body of the closure to capture a particular instance ,there is a scope that the strong reference cycle can occur. Strong reference to the closure in particular is well addressed and defined as by 'self.someProperty' or 'self.someMethod()'. Strong reference cycles are in turn used as reference types for the closures.
The strong reference cycle can happen if a closure for the class instance property and the body of the closure is assigned in order to capture a specific instance. self.someProperty' or' self.someMethod()' is the strong reference to closure. As reference types for closures, strong reference cycles are used.
class HTMLElement{
let samplename:String
let text:String?
lazy var asHTML:()->String={
if let text = self.text {
return "<\(self.samplename)>\(text)</\(self.samplename)>"
} else {
return "<\(self.samplename) />"
}
}
init(samplename:String, text:String?= nil){
self.samplename = samplename
self.text = text
}
deinit {
print("\(samplename) is being deinitialized")
}
}
var paragraph:HTMLElement?=HTMLElement(samplename:"p", text:"Welcome to Closure SRC")
print(paragraph!.asHTML())
The output for the above program would be
<p>Welcome to Closure SRC</p>
Optional chaining is an operation on an optional that could presently be nil for querying and calling properties, methods, and subscriptions. If the options include the value, the property, methods, or subscript call is successful, if the optional is nil, then nil returns the property, method or subscript call. Many queries can be linked together, and if any link is nil, the whole chain will fail gracefully.
If you want to call a property, method or subscript on optional value if you have an optional non-nil, you indicate optional chaining by putting the question mark(?). This is very comparable to a mark(!) after an optional value to force its value to be unwrapped. The major distinction is that if the optional is nil, optional chaining fails, whereas forced unwrapping causes a runtime error when the optional is nil.
classLoksabhaPoll{
var candidate:Constituency? //Optional
}
lass Constituency{
var name ="Hajipur"
}
let cand =LoksabhaPoll ()
let candname = cand.candidate!.name //forced unwrapping
The output for the above program would be as follows
fatal error: unexpectedly found nil while unwrapping an Optional value
0 Swift 4 0x0000000103410b68
llvm::sys::PrintStackTrace(__sFILE*) + 40
1 Swift 4 0x0000000103411054 SignalHandler(int) + 452
2 libsystem_platform.dylib 0x00007fff9176af1a _sigtramp + 26
3 libsystem_platform.dylib 0x000000000000000b _sigtramp + 1854492939
4 libsystem_platform.dylib 0x00000001074a0214 _sigtramp + 1976783636
5 Swift 4 0x0000000102a85c39
llvm::JIT::runFunction(llvm::Function*, std::__1::vector > const&) + 329
6 Swift 4 0x0000000102d320b3
llvm::ExecutionEngine::runFunctionAsMain(llvm::Function*,
std::__1::vector<std::__1::basic_string, std::__1::allocator >,
std::__1::allocator<std::__1::basic_string, std::__1::allocator > > > const&,
char const* const*) + 1523
7 Swift 4 0x000000010296e6ba Swift 4::RunImmediately(Swift
4::CompilerInstance&, std::__1::vector<std::__1::basic_string,
std::__1::allocator >, std::__1::allocator<std::__1::basic_string,
std::__1::allocator > > > const&, Swift 4::IRGenOptions&, Swift 4::SILOptions
const&) + 1066
8 Swift 4 0x000000010275764b frontend_main(llvm::ArrayRef,
char const*, void*) + 5275
9 Swift 4 0x0000000102754a6d main + 1677
10 libdyld.dylib 0x00007fff8bb9e5c9 start + 1
11 libdyld.dylib 0x000000000000000c start + 1950751300
Stack dump:
0.Program arguments:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/
usr/bin/Swift 4 -frontend -interpret - -target x86_64-apple-darwin14.0.0 -
target-cpu core2 -sdk
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/
SDKs/MacOSX10.10.sdk -module-name main
/bin/sh: line 47: 15672 Done cat <<'SWIFT 4'
import Foundation
</std::__1::basic_string</std::__1::basic_string</std::__1::basic_string</std::
__1::basic_string
Since the values are not stated in their base class, the value ' NIL' is saved and the force unwrapping operation returns a fatal error.
Program for optional chaining by (?)
classLoksabhaPoll{
var candidate:Constituency? //Optional
}
lass Constituency{
var name ="Hajipur"
}
let cand =LoksabhaPoll()
if let candname = cand.candidate?.name {
print("Candidate name is \(candname)")
} else {
print("Candidate name cannot be retrieved")
}
The output for the above program would be
Candidate name cannot be retrieved
Defining Model Classes for Optional Chaining & Accessing Properties
Swift also offers the optional chaining idea in the form of declaring more than one subclass as a model class. This idea is very helpful for defining and accessing complicated models and sub-properties of properties, methods, and subscriptions.
class rectangle {
var print: circle?
}
class circle {
var area =[radius]()
var cprint:Int{
return area.count
}
subscript(i:Int)-> radius {
get {
return area[i]
}
set {
area[i]= newValue
}
}
func circleprint(){
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname:String
init(radiusname:String){ self.radiusname = radiusname }
}
class circumference {
var circumName:String?
var circumNumber:String?
var street:String?
func buildingIdentifier()->String?{
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let rectname = rectangle()
if let rectarea = rectname.print?.cprint {
print("Area of rectangle is \(rectarea)")
} else {
print("Rectangle Area is not specified")
}
The output for the above program would be
Rectangle Area is not specified
class rectangle {
varprint: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} elseif circumNumber != nil {
return circumNumber
} else {
returnnil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
.
In the circle () subclass, the function circleprint() is called when an instance 'circname' is created. If the function includes some value, the value is given back, it checks the value by checking 'circname.print?.circleprint() != nil’ to return some specified print message in case of nil.
To set and retrieve a subscript value we can leverage optional chaining for ensuring whether a call to that subscript returns a value or not. The optional value of a specific subscript can be accessed by putting before’?’ the subscript braces.
Example 1
class rectangle {
var print: circle?
}
class circle {
var area =[radius]()
var cprint:Int{
return area.count
}
subscript(i:Int)-> radius {
get {
return area[i]
}
set {
area[i]= newValue
}
}
func circleprint(){
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname:String
init(radiusname:String){ self.radiusname = radiusname }
}
class circumference {
var circumName:String?
var circumNumber:String?
var circumarea:String?
func buildingIdentifier()->String?{
if circumName != nil {
return circumName
} else if circumNumber != nil {
return circumNumber
} else {
return nil
}
}
}
let circname = rectangle()
if let radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
The output of the above program would be
Radius is not specified.
In the example above the membership function, 'radiusName' instance values are not specified.
Example 2
In the below example membership function instance values are specified.
class rectangle {
varprint: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} elseif circumNumber != nil {
return circumNumber
} else {
returnnil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
iflet radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
class rectangle {
varprint: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} elseif circumNumber != nil {
return circumNumber
} else {
returnnil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
var area = ["Radius": [35, 45, 78, 101], "Circle": [90, 45, 56]]
area["Radius"]?[1] = 78
area["Circle"]?[1]--
print(area["Radius"]?[0])
print(area["Radius"]?[1])
print(area["Radius"]?[2])
print(area["Radius"]?[3])
print(area["Circle"]?[0])
print(area["Circle"]?[1])
print(area["Circle"]?[2])
The output for the above program would be
Optional(35)
Optional(78)
Optional(78)
Optional(101)
Optional(90)
Optional(44)
Optional(56)
The optional chaining also facilitates multiple subclasses linking with its superclass properties, methods, and subscripts.
class rectangle {
varprint: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} elseif circumNumber != nil {
return circumNumber
} else {
returnnil
}
}
}
let circname = rectangle()
iflet radiusName = circname.print?[0].radiusname {
print("The first room name is \(radiusName).")
} else {
print("Radius is not specified.")
}
The instance values for the' radiusName' member function are not specified in the above program.It will return only else part of function, while returning values we need to define values for membership function. If the value we are trying to retrieve is optional, then optional chaining will also retrieve the optional value.
class rectangle {
varprint: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("The number of rooms is \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} elseif circumNumber != nil {
return circumNumber
} else {
returnnil
}
}
}
let circname = rectangle()
circname.print?[0] = radius(radiusname: "Diameter")
let printing = circle()
printing.area.append(radius(radiusname: "Units"))
printing.area.append(radius(radiusname: "Meter"))
circname.print = printing
iflet radiusName = circname.print?[0].radiusname {
print("Radius is measured in \(radiusName).")
} else {
print("Radius is not specified.")
}
When we run the above program the output would be
Radius is measured in Units.
The subclasses methods can be also accessed by optional chaining.
class rectangle {
varprint: circle?
}
class circle {
var area = [radius]()
var cprint: Int {
return area.count
}
subscript(i: Int) -> radius {
get {
return area[i]
}
set {
area[i] = newValue
}
}
func circleprint() {
print("Area of Circle is: \(cprint)")
}
var rectarea: circumference?
}
class radius {
let radiusname: String
init(radiusname: String) { self.radiusname = radiusname }
}
class circumference {
var circumName: String?
var circumNumber: String?
var circumarea: String?
func buildingIdentifier() -> String? {
if circumName != nil {
return circumName
} elseif circumNumber != nil {
return circumNumber
} else {
returnnil
}
}
}
let circname = rectangle()
if circname.print?.circleprint() != nil {
print("Area of circle is specified)")
} else {
print("Area of circle is not specified")
}
Typecasting is a way of examining the type of instance or treating it as a superclass or subclass different from that of another one in its class hierarchy. The casting of type in Swift is carried out with operators ”is” and “as”. Both operators provide an easy and expressive way of checking a value type or casting a value to a different type.
Typecasting is used to check the type of instance to see if it belongs to a specific type of class. It also examines the class hierarchy and its subclasses in order to check and cast these instances in the same hierarchy.
classSubjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
classChemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
classMaths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [ Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
The output for the above program would be
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
The' is' operator will perform the type check. The 'Is' type checks if the instance is a subclass-type instance and returns true if it belongs to this instance, otherwise it returns false.
class Subjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
classChemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
classMaths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
if item isChemistry {
++chemCount
} elseif item isMaths {
++mathsCount
}
}
print("Subjects in chemistry contains \(chemCount) topics and maths contains \(mathsCount) topics")
The output for the above program would be
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Subjects in chemistry contains 2 topics and maths contains 3 topics
Two operators (as? and as!) can be used to downcast the subclass type. In case the nil value gets returned the ‘as? , the operator returns an optional value. It is used to monitor downcast success. The as! Operator is used for forced unwrapping in the context of optional chaining when downcasting returns nil value. It is used in case of downcast failure to trigger runtime errors
classSubjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
classChemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
classMaths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
ifletprint = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} elseiflet example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
The above program output would be
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
The keyword 'Any' is used to represent an instance which belongs to any type including function types. For representing an instance of any type including function we use ‘Any’ keyword.
classSubjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
classChemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
classMaths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let sa = [
Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in sa {
ifletprint = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} elseiflet example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
forprintin exampleany {
switchprint {
caselet someInt asInt:
print("Integer value is \(someInt)")
caselet someDouble asDoublewhere someDouble > 0:
print("Pi value is \(someDouble)")
caselet someString asString:
print("\(someString)")
caselet phy asChemistry:
print("Topics '\(phy.physics)', \(phy.equations)")
default:
print("None")
}
}
The output for the above program would be the following:
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz
The ‘AnyObject’ keyword is used for representing an instance of any class type.
classSubjects {
var physics: String
init(physics: String) {
self.physics = physics
}
}
classChemistry: Subjects {
var equations: String
init(physics: String, equations: String) {
self.equations = equations
super.init(physics: physics)
}
}
classMaths: Subjects {
var formulae: String
init(physics: String, formulae: String) {
self.formulae = formulae
super.init(physics: physics)
}
}
let saprint: [AnyObject] = [Chemistry(physics: "solid physics", equations: "Hertz"),
Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz"),
Chemistry(physics: "Thermo physics", equations: "Decibels"),
Maths(physics: "Astro Physics", formulae: "MegaHertz"),
Maths(physics: "Differential Equations", formulae: "Cosine Series")]
let samplechem = Chemistry(physics: "solid physics", equations: "Hertz")
print("Instance physics is: \(samplechem.physics)")
print("Instance equation is: \(samplechem.equations)")
let samplemaths = Maths(physics: "Fluid Dynamics", formulae: "Giga Hertz")
print("Instance physics is: \(samplemaths.physics)")
print("Instance formulae is: \(samplemaths.formulae)")
var chemCount = 0
var mathsCount = 0
for item in saprint {
ifletprint = item as? Chemistry {
print("Chemistry topics are: '\(print.physics)', \(print.equations)")
} elseiflet example = item as? Maths {
print("Maths topics are: '\(example.physics)', \(example.formulae)")
}
}
var exampleany = [Any]()
exampleany.append(12)
exampleany.append(3.14159)
exampleany.append("Example for Any")
exampleany.append(Chemistry(physics: "solid physics", equations: "Hertz"))
forprintin exampleany {
switchprint {
caselet someInt asInt:
print("Integer value is \(someInt)")
caselet someDouble asDoublewhere someDouble > 0:
print("Pi value is \(someDouble)")
caselet someString asString:
print("\(someString)")
caselet phy asChemistry:
print("Topics '\(phy.physics)', \(phy.equations)")
default:
print("None")
}
}
The output for the above program would be
Instance physics is: solid physics
Instance equation is: Hertz
Instance physics is: Fluid Dynamics
Instance formulae is: Giga Hertz
Chemistry topics are: 'solid physics', Hertz
Maths topics are: 'Fluid Dynamics', Giga Hertz
Chemistry topics are: 'Thermo physics', Decibels
Maths topics are: 'Astro Physics', MegaHertz
Maths topics are: 'Differential Equations', Cosine Series
Integer value is 12
Pi value is 3.14159
Example for Any
Topics 'solid physics', Hertz
Extensions
Extensions in a layman’s language add to a class, structure, enumeration or type of protocol new functionality. This even includes the feasibility to extend types for which the original source code is not even available (called retroactive modeling). Extensions in Swift are exactly the same as categories in Objective-C.Swift extension within the functionalities :
Syntax
extension SomeType {
// new functionality can be added here
}
Existing type can also be added as a protocol standard with extensions and its syntax is similar to the classes or structures.
extension SomeType: SomeProtocol, AnotherProtocol {
// protocol requirements is described here
}
With the help of extensions computed ‘instance’ and type properties can be extended.
extension Int {
varadd: Int {returnself + 100 }
varsub: Int { returnself - 10 }
var mul: Int { returnself * 10 }
var div: Int { returnself / 5 }
}
let addition = 3.add
print("Addition is \(addition)")
let subtraction = 120.sub
print("Subtraction is \(subtraction)")
let multiplication = 39.mul
print("Multiplication is \(multiplication)")
let division = 55.div
print("Division is \(division)")
let mix = 30.add + 34.sub
print("Mixed Type is \(mix)")
The above program output would be
Addition is 103
Subtraction is 110
Multiplication is 390
Division is 11
Mixed Type is 154
Swift offers the flexibility of adding new initializers by extensions to an existing type. The user can add his own custom types to extend the defined types and also allow further initialization options. Only init() is supported by extensions. The deinit() are not supported by extensions.
struct sum {
var num1 = 100, num2 = 200
}
struct diff {
var no1 = 200, no2 = 100
}
struct mult {
var a = sum()
var b = diff()
}
let calc = mult()
print ("Inside mult block \(calc.a.num1, calc.a.num2)")
print("Inside mult block \(calc.b.no1, calc.b.no2)")
let memcalc = mult(a: sum(num1: 300, num2: 500),b: diff(no1: 300, no2: 100))
print("Inside mult block \(memcalc.a.num1, memcalc.a.num2)")
print("Inside mult block \(memcalc.b.no1, memcalc.b.no2)")
extension mult {
init(x: sum, y: diff) {
let X = x.num1 + x.num2
let Y = y.no1 + y.no2
}
}
let a = sum(num1: 100, num2: 200)
print("Inside Sum Block:\( a.num1, a.num2)")
let b = diff(no1: 200, no2: 100)
print("Inside Diff Block: \(b.no1, b.no2)")
The output for the above program would be
Inside mult block (100, 200)
Inside mult block (200, 100)
Inside mult block (300, 500)
Inside mult block (300, 100)
Inside Sum Block:(100, 200)
Inside Diff Block: (200, 100)
The extensions also help subclasses to add new instance methods and type methods.
extension Int {
func topics(summation: () -> ()) {
for _ in0..<self {
summation()
}
}
}
4.topics(summation: {
print("Inside Extensions Block")
})
3.topics(summation: {
print("Inside Type Casting Block")
})
The output for the above program would be
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Extensions Block
Inside Type Casting Block
Inside Type Casting Block
Inside Type Casting Block
Mutating Instance Methods
When declared as extensions, instance methods can also be mutated.
Structures and enumeration methods that modify themselves or their properties must identify the instance method as mutating, as do methods from the original implementation.
extension Double {
mutating func square() {
let pi = 3.1415
self = pi * self * self
}
}
varTrial1 = 3.3
Trial1.square()
print("Area of circle is: \(Trial1)")
varTrial2 = 5.8
Trial2.square()
print("Area of circle is: \(Trial2)")
varTrial3 = 120.3
Trial3.square()
print("Area of circle is: \(Trial3)")
Subscript & Nested Type
extension Int {
subscript(var multtable: Int) -> Int {
var no1 = 1
while multtable > 0 {
no1 *= 10
--multtable
}
return (self / no1) % 10
}
}
print(12[0])
print(7869[1])
print(786543[2])
The extensions can help in extending nested types for class, structure and enumeration instance.
extension Int {
enum calc {
caseadd
casesub
case mult
case div
case anything
}
varprint: calc {
switchself {
case0:
return .add
case1:
return .sub
case2:
return .mult
case3:
return .div
default:
return .anything
}
}
}
func result(numb: [Int]) {
for i in numb {
switch i.print {
case .add:
print(" 10 ")
case .sub:
print(" 20 ")
case .mult:
print(" 30 ")
case .div:
print(" 40 ")
default:
print(" 50 ")
}
}
}
result(numb: [0, 1, 2, 3, 4, 7])
A protocol defines the actual blueprint of any methods, its properties along with other requirements which are perfectly suitable for a specific task or feature. Any class enumeration or structure can then take the protocol to ensure its actual execution. Any type of protocol complying with the requirements is said to comply with that protocol. You can extend the protocol to implement some of these needs and can also implement additional functionality which conforms the types that can be used. Along with that it can even specify requirements that conform types that are a must for implementation.
Syntax
protocol SomeProtocol {
// protocol definition
}
Protocols are declared after names of class, structure or type of enumeration. It is also feasible to declare single and multiple protocols. When defining various protocols, they must be split up by commas.
structSomeStructure: Protocol1, Protocol2 {
// structure definition
}
If a protocol for superclass has to be defined, the name of the protocol should follow the name of Super Class with commas.
class SomeClass: SomeSuperclass, Protocol1, Protocol2 {
// class definition
}
A protocol is used to indicate a property of instance or instance of specific class type. It simply specifies the property of the type or instance alone, instead of whether it has been stored or computed property. It is also used to indicate if the property is 'gettable' or 'settable'.
‘var' keyword declares property requirements as property variables. After their type declaration,{ get set} is used for declaring gettable and settable properties. Gettable is specified after a type declaration by {get} property.
protocol classa {
var marks: Int { getset }
var result: Bool { get }
func attendance() -> String
func markssecured() -> String
}
protocol classb: classa {
var present: Bool { getset }
var subject: String { getset }
var stname: String { getset }
}
class classc: classb {
var marks = 96
let result = true
var present = false
var subject = "Swift Protocols"
var stname = "Protocols"
func attendance() -> String {
return"The \(stname) has secured 99% attendance"
}
func markssecured() -> String {
return"\(stname) has scored \(marks)"
}
}
let studdet = classc()
studdet.stname = "Swift"
studdet.marks = 98
studdet.markssecured()
print(studdet.marks)
print(studdet.result)
print(studdet.present)
print(studdet.subject)
print(studdet.stname)
The output for the above program would be
98
true
false
Swift Protocols
Swift
protocol daysofaweek {
mutating func print()
}
enum days: daysofaweek {
case sun, mon, tue, wed, thurs, fri, sat
mutating func print() {
switchself {
case sun:
self = sun
print("Sunday")
case mon:
self = mon
print("Monday")
case tue:
self = tue
print("Tuesday")
case wed:
self = wed
print("Wednesday")
case mon:
self = thurs
print("Thursday")
case tue:
self = fri
print("Friday")
case sat:
self = sat
print("Saturday")
default:
print("NO Such Day")
}
}
}
var res = days.wed
res.print()
Swift allows users to initialize protocols that conform like normal initializers to type compliance.
Syntax
protocol SomeProtocol {
init(someParameter: Int)
}
Example
protocol tcpprotocol {
init(aprot: Int)
}
Class Implementations of Protocol Initializer Requirements
To initialize a protocol, designated or convenience initializer allows the user to conform its standard by reserved ‘required’ keyword.
lass SomeClass: SomeProtocol {
required init(someParameter: Int) {
// initializer implementation statements
}
}
protocol tcpprotocol {
init(aprot: Int)
}
class tcpClass: tcpprotocol {
required init(aprot: Int) {
}
}
Conformity to the Protocol is guaranteed on all subclasses with a "required" modifier for explicit or inherited execution. When a subclass overrides its superclass initialization requirement, the' override' keyword is used.
protocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int// local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
letprint = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
Protocols are used as types of functions , classes, methods, etc., instead of applying functionality in a protocol.
There are numerous ways in which protocols can be applicable :
protocol Generator {
typealias members
func next() -> members?
}
var items = [10,20,30].generate()
whilelet x = items.next() {
print(x)
}
for lists in map([1,2,3], {i in i*5}) {
print(lists)
}
print([100,200,300])
print(map([1,2,3], {i in i*10}))
The output for the above program would be
10
20
30
5
10
15
[100, 200, 300]
[10, 20, 30]
By using extensions, the existing type can be embraced and complied with by a fresh protocol. The existing type can be supplemented by extensions with new properties, methods, and subscripts.
protocol AgeClasificationProtocol {
var age: Int { get }
func agetype() -> String
}
classPerson {
let firstname: String
let lastname: String
var age: Int
init(firstname: String, lastname: String) {
self.firstname = firstname
self.lastname = lastname
self.age = 10
}
}
extension Person : AgeClasificationProtocol {
func fullname() -> String {
var c: String
c = firstname + " " + lastname
return c
}
func agetype() -> String {
switch age {
case0...2:
return"Baby"
case2...12:
return"Child"
case13...19:
return"Teenager"
caselet x where x > 65:
return"Elderly"
default:
return"Normal"
}
}
}
Swift permits protocols to inherit properties that have been defined. It's comparable to class inheritance, but with several inheritance protocols separated by commas being listed.
protocol classa {
var no1:Int{getset}
func calc(sum:Int)
}
protocol result {
func print(target: classa)
}
class student2: result {
func print(target: classa){
target.calc(sum:1)
}
}
class classb: result {
func print(target: classa){
target.calc(sum:5)
}
}
class student: classa {
var no1:Int=10
func calc(sum:Int){
no1 -= sum
print("Student attempted \(sum) times to pass")
if no1 <=0{
print("Student is absent for exam")
}
}
}
classPlayer{
var stmark: result!
init(stmark: result){
self.stmark = stmark
}
func print(target: classa){
stmark.print(target: target)
}
}
var marks =Player(stmark: student2())
var marksec = student()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
marks.stmark = classb()
marks.print(target: marksec)
marks.print(target: marksec)
marks.print(target: marksec)
The above program output would be
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 1 times to pass
Student attempted 5 times to pass
Student attempted 5 times to pass
Student is absent for exam
Student attempted 5 times to pass
Student is absent for exam
When protocols and class protocols are described, the user needs to add class first followed by the inheritance list of protocols.
rotocol tcpprotocol {
init(no1: Int)
}
class mainClass {
var no1: Int// local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1: 20)
letprint = subClass(no1: 30, no2: 50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
The protocol composition can help multiple protocols to be called at once.
Syntax
protocol<SomeProtocol, AnotherProtocol>
Example
protocol stname {
var name:String{get}
}
protocol stage {
var age:Int{get}
}
structPerson: stname, stage {
var name:String
var age:Int
}
func print(celebrator: stname & stage){
print("\(celebrator.name) is \(celebrator.age) years old")
}
let studname =Person(name:"Priya", age:21)
print(studname)
let stud =Person(name:"Rehan", age:29)
print(stud)
let student =Person(name:"Roshan", age:19)
print(student)
You can use the operators "is" and "as" defined in the type casting to verify protocol compliance and cast them into a particular protocol. The checking and casting on a protocol is identical to checking and casting to a type.
importFoundation
@objc protocol rectangle {
var area: Double { get }
}
@objcclassCircle: rectangle {
let pi = 3.1415927
var radius: Double
var area: Double { return pi * radius * radius }
init(radius: Double) { self.radius = radius }
}
@objcclass result: rectangle {
var area: Double
init(area: Double) { self.area = area }
}
class sides {
var rectsides: Int
init(rectsides: Int) { self.rectsides = rectsides }
}
let objects: [AnyObject] = [Circle(radius: 2.0),result(area:198),sides(rectsides: 4)]
forobjectin objects {
iflet objectWithArea = objectas? rectangle {
print("Area is \(objectWithArea.area)")
} else {
print("Rectangle area is not defined")
}
}
The output for the above program would be
Area is 12.5663708
Area is 198.0
Rectangle area is not defined
Generic code allows you to write flexible, reusable functions and type, depending on criteria that you define, that can work with any type. You can write code which prevents duplication and clearly, abstractly expresses its purpose.
Generics are one of Swift's strongest characteristics and many Swift standard libraries are made from generic code. Swift's Array and Dictionary are generic collections, for instance. You can generate an array containing Int or an array containing String values or a set for any other type in Swift. Likewise, you can generate a dictionary to store any given type of values and there are no restrictions on what type.
func exchange(a: inout Int, b: inout Int) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping values are: \(numb1) and \(numb2)")
The output for the above program would be
Before Swapping values are: 100 and 200
After Swapping values are: 200 and 100
Generic Functions: Type Parameters
Generic functions can be used to access any data type like 'Int' or 'String'.
func exchange<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")
The output for the above program would be
Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics
The exchange() function is used to exchange values outlined above, and < T > is used as a parameter sort. The exchange() function is called first to return the value of' Int' and then the second call to the exchange() function gives the value of' String.' Inside the angle brackets, separated by commas, several parameter types can be included.
The user-specified parameters of the type are named to understand what type of parameter it holds. As a generic parameter type name, Swift offers < T>. However, parameters such as Arrays and Dictionaries can be used to define that they are of the' Dictionary' type.
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift ")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()
The output for the above program would be
[Swift ]
[Swift , Generics]
[Swift , Generics, Type Parameters]
[Swift , Generics, Type Parameters, Naming Type Parameters]
Extending the stack property to know the top of the item is included with 'extension' keyword.
struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift ")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
extension TOS {
var first: T? {
return items.isEmpty ? nil : items[items.count - 1]
}
}
iflet first = tos.first {
print("The top item on the stack is \(first).")
}
The output for the above program would be
["Swift "]
["Swift ", "Generics"]
["Swift ", "Generics", "Type Parameters"]
["Swift ", "Generics", "Type Parameters", "Naming Type Parameters"]
The top item on the stack is Naming Type Parameters.
Specifically, 'type constraints’' may allow the specified type parameter to be inherited from a certain class, or the protocol conformity standard to be ensured.
func exchange<T>(a: inout T, b: inout T) {
let temp = a
a = b
b = temp
}
var numb1 = 100
var numb2 = 200
print("Before Swapping Int values are: \(numb1) and \(numb2)")
exchange(a: &numb1, b: &numb2)
print("After Swapping Int values are: \(numb1) and \(numb2)")
var str1 = "Generics"
var str2 = "Functions"
print("Before Swapping String values are: \(str1) and \(str2)")
exchange(a: &str1, b: &str2)
print("After Swapping String values are: \(str1) and \(str2)")
The output for the above program would be
Before Swapping Int values are: 100 and 200
After Swapping Int values are: 200 and 100
Before Swapping String values are: Generics and Functions
After Swapping String values are: Functions and Generics
In the protocol definition, Swift allows associated types to be declared by the 'associatedtype' keyword.
protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
struct TOS<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
The output for the above program would be
Access control limits access by other source files and modules to parts of your code from the code. This feature assists the user to hide the implementation details of the user code, and to specify a particular interface through which that code can be accessed and easily used by the end users.
In addition to offering different levels of control of access, Swift reduces the requirement for explicit levels of access control by providing standard access levels for typical scenarios.
Module and abstraction are done through access control to restrict access to code blocks. According to their properties, methods, initializers and subscriptions, access to classes, structures and enumerations can be achieved through access control procedures.
Access control is applicable to properties, types and functions can be referred to as 'entities'. Constants, variables and functions are restricted in a protocol and allowed access as global or local by way of access control.
Modules and source files are the basis of the Access Control Model.
The module is described as a single distribution unit of code and can be exported using an 'import' keyword.
A single source file with multiple types and features in a module is defined as the source file.
Three different types of access provided by Swift language are:
Public, Internal and Private
Syntax:
public class SomePublicClass {}
internal class SomeInternalClass {}
private class SomePrivateClass {}
public var somePublicVariable = 0
internal let someInternalConstant = 0
private func somePrivateFunction() {}
Some functions may even have their arguments being declared within the function without any return values. Such programs declare a and b as arguments to the sum() function. Within the function itself the values for the arguments a and b are fed by invoking the function call sum() and its values are automatically printed; thereby completely eliminating the return values. Inorder to make the function's return type as private, the end user declares the function’s overall access level with a private modifier.
Live demo for the same would be:
private func sum(a: Int, b: Int) {
let a = a + b
let b = a - b
print(a, b)
}
sum(a: 20, b: 10)
sum(a: 40, b: 10)
sum(a: 24, b: 6)
The output achieved in this case is
30 20
50 40
30 24
Live Demo
publicenumStudent {
caseName(String)
caseMark(Int,Int,Int)
}
var studDetails = Student.Name("Swift 4")
var studMarks = Student.Mark(98,97,95)
switch studMarks {
case .Name(let studName):
print("Student name is: \(studName).")
case .Mark(letMark1, letMark2, letMark3):
print("Student Marks are: \(Mark1),\(Mark2),\(Mark3).")
}
While running this program with the playground we achieve the following output:
Student Marks are: 98,97,95
For individual cases of an enumeration, the listing in Swift 4 automatically receives the same level of access.
Consider accessing the name and trademarks of students in three subjects, for example. Enumerated names are declared as students and members of the enum class are names of a data type string, mark 2, and mark3 of an Integer data type.
They have entered either the name of the student or the marks. Now, if that case block is carried out, the switch case will print out the name of the student. If both conditions fail, the default block will be executed.
Swift 4 enables the user to subclass any class accessible in the existing access framework.
A subclass cannot be greater than its superclass access level. A public subclass of an internal superclass is limited for the user.
publicclass cricket {
internal func printIt() {
print("Welcome to Swift 4 Super Class")
}
}
internalclass tennis: cricket {
overrideinternal func printIt() {
print("Welcome to Swift 4 Sub Class")
}
}
let cricinstance = cricket()
cricinstance.printIt()
let tennisinstance = tennis()
tennisinstance.printIt()
On running the above program with the playground, the following output can be achieved:
Welcome to Swift Super Class
Welcome to Swift Sub Class
Swift 4 is not defined as the public constant, variable, or characteristic other than the type. A public property with a personal form is not valid to be documented. More so, a subscript cannot be more public in comparison to its index or return type.
If a constant, variable, property or subscript uses a private form, it must also be labeled privately as a constant, variable, property or subscription.
private var privateInstance = SomePrivateClass()
The same access levels are automatically received by getters and setters of constant, variable, properties and subscript to which they actually belong to.
class Samplepgm {
var counter: Int = 0{
willSet(newTotal) {
print("Total Counter is: \(newTotal)")
}
didSet {
if counter > oldValue {
print("Newly Added Counter \(counter - oldValue)")
}
}
}
}
letNewCounter = Samplepgm()
NewCounter.counter = 100
NewCounter.counter = 800
The output of the above program is shown below:
Total Counter is: 100
Newly Added Counter 100
Total Counter is: 800
Newly Added Counter 700
Custom initializers can actually be assigned the access less than or equal to the initialized type. The required initializer must have the same amount of access as its class. The types of parameters of an initializer cannot be more private than the access level of the initializer itself.
For declaration of each and every subclass of the initialize,the 'required' keyword needs to be pre-defined prior the init() function.
class classA {
required init() {
let a = 10
print(a)
}
}
class classB: classA {
required init() {
let b = 30
print(b)
}
}
let res = classA()
letprint = classB()
Following outputs are obtained by running the above program:
10
30
10
A default initializer has the same level of access as its initialised type, unless that type is publicly defined.If initializing by default is public, it is internally considered. If the user needs to have a public type initialized in another module with a no-argument initializer, it provides exclusively a public no-argument initializer as part of the type's definition.
The same levels of access to each other must be stated when defining a new protocol to inherit functions from the existing prototype. The Swift 4 access control will not enable users inherent in an 'internal' protocol to define a 'public' protocol.
public protocol tcpprotocol {
init(no1: Int)
}
publicclass mainClass {
var no1: Int// local storage
init(no1: Int) {
self.no1 = no1 // initialization
}
}
class subClass: mainClass, tcpprotocol {
var no2: Int
init(no1: Int, no2 : Int) {
self.no2 = no2
super.init(no1:no1)
}
// Requires only one parameter for convenient method
required override convenience init(no1: Int) {
self.init(no1:no1, no2:0)
}
}
let res = mainClass(no1:20)
let print = subClass(no1:30, no2:50)
print("res is: \(res.no1)")
print("res is: \(print.no1)")
print("res is: \(print.no2)")
While running the program, the following output is being achieved:
res is: 20
res is: 30
res is: 50
Swift 4 does not entertain the end users to facilitate an explicit access level modifier for an extension when the user uses that particular extension to add protocol conformance. The default access level in case of every single protocol requirement actually does the implementation within the extension and is provided with its very own protocol access level.
In case of Generics users are allowed to specify minimum access levels to access the type constraints along with its type parameters.
public struct TOS<T> {
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
}
var tos = TOS<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Type Parameters")
print(tos.items)
tos.push(item: "Naming Type Parameters")
print(tos.items)
let deletetos = tos.pop()
The following results are obtained when the program is being run:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Type Parameters]
[Swift 4, Generics, Type Parameters, Naming Type Parameters]
The user can readily define type aliases to treat the unique access control types, whereas the same or different access levels can be easily identified by the user. In scenarios wherein the type alias is 'private' its associated members can be declared as 'private, internal of public type', and in the situations wherein the type alias is public the members cannot be an alias as an 'internal' or 'private' name.
Any type aliases defined are regarded as distinct types for the exclusive purposes of access control. A type alias can even have an access level less than or equal to the access level of the type its aliases have in original. For example, a private type alias can actually alias a private, internal, or public type in contrary to which a public type alias cannot alias an internal or private type.
public protocol Container {
associatedtype ItemType
mutating func append(item: ItemType)
var count: Int { get }
subscript(i: Int) -> ItemType { get }
}
structStack<T>: Container {
// original Stack<T> implementation
var items = [T]()
mutating func push(item: T) {
items.append(item)
}
mutating func pop() -> T {
return items.removeLast()
}
// conformance to the Container protocol
mutating func append(item: T) {
self.push(item: item)
}
var count: Int {
return items.count
}
subscript(i: Int) -> T {
return items[i]
}
}
func allItemsMatch<
C1: Container, C2: Container
where C1.ItemType == C2.ItemType, C1.ItemType: Equatable>
(someContainer: C1, anotherContainer: C2) -> Bool {
// check that both containers contain the same number of items
if someContainer.count != anotherContainer.count {
returnfalse
}
// check each pair of items to see if they are equivalent
for i in0..<someContainer.count {
if someContainer[i] != anotherContainer[i] {
returnfalse
}
}
// all items match, so return true
returntrue
}
var tos = Stack<String>()
tos.push(item: "Swift 4")
print(tos.items)
tos.push(item: "Generics")
print(tos.items)
tos.push(item: "Where Clause")
print(tos.items)
var eos = ["Swift 4", "Generics", "Where Clause"]
print(eos)
The following output is being achieved while the above program is being run:
[Swift 4]
[Swift 4, Generics]
[Swift 4, Generics, Where Clause]
[Swift 4, Generics, Where Clause]
Swift 4 introduces the new Codable protocol, which allows you to serialize and remove customized data types without any special code – and without worrying about losing your value types.
struct Language: Codable {
var name: String
var version: Int
}
let swift = Language(name: "Swift", version: 4)
let java = Language(name: "java", version: 8)
let R = Language(name: "R", version: 3
let encoder =JSONEncoder()
iflet encoded =try? encoder.encode(java){
//Perform some operations on this value.
}
let decoder =JSONDecoder()
iflet decoded =try? decoder.decode(Language.self,from: encoded){
//Perform some operations on this value.
}
This module covered all other details related to ARC ,optional chaining ,type casting, extensions ,protocols and generics. We have also got fair understanding of access control with help of this module.