Premium projects bundle

Buy the 14 premium projects bundle for $1000. The bundle contains projects in the following technologies:

  • Node JS and Mongo DB
  • PHP & MySQL, Laravel
  • Vue JS
  • Android apps

Project’s list

  1. Single page chat application – Vue JS, Node JS, Mongo DB
  2. E-commerce single page application – Vue JS, Node JS, Mongo DB
  3. Chat app – Android, Web admin panel
  4. Email marketing tool – Laravel, Vue JS
  5. Financial ledger – Vue JS, Node JS, Mongo DB
  6. Image sharing web app – Node JS, Mongo DB / MySQL
  7. Movie ticket booking site – PHP & MySQL, MVC
  8. Realtime blog in Node JS and Mongo DB
  9. File transfer web app – Node JS + Mongo DB
  10. Realtime customer support chat widget
  11. Video streaming website – Node JS, Mongo DB
  12. Picture competition web app – Node JS, Mongo DB
  13. Questionnaire – Node JS, Mongo DB
  14. Blog website – Laravel, Google Adsense approved

You can buy each project separately too as well. Besides getting all the pro features of all 14 projects, we also provide additional services to them.

Secure payment

We allow users to make payments easily and securely using their bank accounts. You can contact us here and we will send you an invoice to make the payment.

Source code

Complete source code is included in all the projects. You will enjoy the pro version of each project.

Support

If you encounter any problem in installing the project or deployment, our technical support team is here. You can schedule a meeting with them and they will be able to assist you over AnyDesk or TeamViewer.

Use as a college project

If you are a student and are looking to get ready-to-go projects to learn about code and how real projects work, this will be beneficial for you. Also, Node JS projects are good learning points for students in advanced programming.

Customize as you want

Once you download the projects, you can customize them as per your needs. You can change the color theme, add new features to it, etc.

Get help in deployment

Once projects are set up in your local host, we will be here if you needed any help in deployment to the live server. For Node JS projects, we will assist you in deployment to Heroku. And for Mongo DB projects, we will help you with a deployment to mongodb.com.

Price: $1000

Out TrustPilot reviews

TrustPilot-reviews
TrustPilot-reviews

Search bar Swift UI with history – SQLite

SQLite is used to store the data locally inside the app in SQL structure. It is a relational local database. You can use this database to store data inside the app using Swift and Swift UI. We will be creating a simple search bar in an iOS app in Swift UI to search animals from an array and save the user’s searched strings in the SQLite database.

We will be using a library called SQLite by Stephen Celis. To install this library, you must have Cocoapods installed in your system.

Installation

You can install Cocoapods in your system by simply running the following command in your terminal:

sudo gem install cocoapods

First, you need to open a command prompt (Terminal) at the root of your XCode project and run the following command in it:

pod init

Now you will see a new file created at the root of your project named Podfile. Open that file in your text editor and add the line to install the library. Following will be the content of your Podfile:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'
 
target 'SQLite_Database' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!
 
  # Pods for SQLite_Database
  pod 'SQLite.swift', '~> 0.12.0'
 
end

After that, run the following command in your Terminal to install this library:

pod update

Once installed, close your XCode and re-open but this time double-click on the file which has an extension “.xcworkspace“. This file will be created only after the pod has been installed/updated.

Create a search bar

First, we will create a search bar using TextField. Then, when the user hits submit, we will send the searched value in the next view.

In the second view, we will get the value from the text field of the first view and search that value in an array. Then, display all the records that matched the searched string and display them in the list view.

Create a state variable in your content view:

// variable to goto search view
@State var gotoSearchPage: Bool = false

// value that is searched from the text field
@State var searchedText: String = ""

Following will be the content of your content view’s body:

// live tracking of input field value
let binding = Binding<String>(get: {
    self.searchedText
}, set: { (value) in
    self.searchedText = value
})

// navigation view to goto search view
return NavigationView {

    VStack (alignment: .leading, spacing: 10) {
    
        // navigation link to goto search view
        NavigationLink (destination: SearchView(searchedText: self.$searchedText), isActive: self.$gotoSearchPage) {
            EmptyView()
        }
    
        // search field
        TextField("Search ...", text: binding, onCommit: {
        
            // goto search view when search icon is clicked
            self.gotoSearchPage = true
        
        })
            .padding(7)
            .padding(.horizontal, 5)
            .background(Color(.systemGray6))
            .cornerRadius(8)
            .disableAutocorrection(true)
            .keyboardType(.webSearch)
        
    }
    .padding(20)
    .navigationBarTitle("Search - SQLite")
}

This will create a text field where you can enter your query, on hitting the “search icon” it should take you to the search view which we will create in the next step.

Create a search view

Now, we need to create a search view where we will perform the searching and display the filtered records in a list view.

Create a modal class for Animal:

//
//  Animal.swift
//  Search bar with history
//
//  Created by Adnan Afzal on 02/12/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import Foundation

class Animal: Identifiable {
    var id: Int64 = 0
    var name: String = ""
    
    init() {
        //
    }
    
    init(name: String) {
        self.name = name
    }
}

Create a new file named SearchView.swift and paste the following code in it:

//
//  SearchView.swift
//  Search bar with history
//
//  Created by Adnan Afzal on 02/12/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import SwiftUI

struct SearchView: View {
    
    // get searched value from the previous view
    @Binding var searchedText: String
    
    // a list of all items (change this variable as per your need)
    @State var animals: [Animal] = []
    
    // list of items that matched the searched text
    @State var searchedArray: [Animal] = []
    
    var body: some View {
        
        VStack {
            
            // show searched text
            Text("\(searchedText)").bold()
            
            // show items that matched the searched text in list view
            List (self.searchedArray) { (item) in
                Button(action: {
                    //
                }, label: {
                    Text(item.name)
                })
            }
        }.onAppear(perform: {
        
            // make the items empty when the page loads
            self.animals.removeAll()
            
            // add the data that needs to be searched (you can put your own array items here)
            self.animals.append(Animal(name: "Lion"))
            self.animals.append(Animal(name: "Tiger"))
            self.animals.append(Animal(name: "Rhino"))
            self.animals.append(Animal(name: "Elephant"))
            self.animals.append(Animal(name: "Cheetah"))
            self.animals.append(Animal(name: "Polar bear"))
            self.animals.append(Animal(name: "Leopard"))
            self.animals.append(Animal(name: "Wolf"))
            
            // empty the searched array
            self.searchedArray.removeAll()
            
            // find all the elements that matched the searched string
            for animal in self.animals {
                if (animal.name.lowercased().contains(self.searchedText.lowercased())) {
                    self.searchedArray.append(animal)
                }
            }
        })
        
    }
}

struct SearchView_Previews: PreviewProvider {

    // when using @Binding, use this in preview provider
    @State static var searchedText: String = ""

    static var previews: some View {
        SearchView(searchedText: $searchedText)
    }
}

Comments have been added on each line to explain each line individually. Now, at this point, you will be able to perform the search and see the animals which contain the name field that matches with the text field value you entered in the first view.

Show search history

Now, we need to show the search history in the content view. For that, first, we have to save each searched string in the SQLite database.

Create a separate class named “DB_Manager” that will hold all the functions for the SQLite database.

//
//  DB_Manager.swift
//  Search bar with history
//
//  Created by Adnan Afzal on 02/12/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import Foundation

// import library
import SQLite

class DB_Manager {

    // sqlite instance
    private var db: Connection!
     
    // table instance
    private var animals: Table!
 
    // columns instances of table
    private var id: Expression<Int64>!
    private var name: Expression<String>!
    
    // constructor of this class
    init () {
         
        // exception handling
        do {
             
            // path of document directory
            let path: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? ""
 
            // creating database connection
            db = try Connection("\(path)/my_animals.sqlite3")
             
            // creating table object
            animals = Table("animals")
             
            // create instances of each column
            id = Expression<Int64>("id")
            name = Expression<String>("name")
             
            // check if the animal's table is already created
            if (!UserDefaults.standard.bool(forKey: "is_db_created")) {
 
                // if not, then create the table
                try db.run(animals.create { (t) in
                    t.column(id, primaryKey: true)
                    t.column(name)
                })
                 
                // set the value to true, so it will not attempt to create the table again
                UserDefaults.standard.set(true, forKey: "is_db_created")
            }
             
        } catch {
            // show error message if any
            print(error.localizedDescription)
        }
         
    }

    // check if record already exists in SQLite
    public func isExists(searchedText: String) -> Bool {
     
        var isExists: Bool = false
         
        // exception handling
        do {
     
            // get animal using ID
            let animal: AnySequence<Row> = try db.prepare(animals.filter(name.lowercaseString == searchedText.lowercased()))
     
            // get row
            animal.forEach({ (rowValue) in
                isExists = true
            })
            
        } catch {
            print(error.localizedDescription)
        }
     
        return isExists
    }
    
    // add a new row in SQLite
    public func addAnimal(nameValue: String) {
        do {
            try db.run(animals.insert(name <- nameValue))
        } catch {
            print(error.localizedDescription)
        }
    }
    
}

Comments have been added with each line for an explanation. Now, in your search view inside the onAppear() function, check if the searched string already exists in the SQLite database. If NOT, then add the searched text in the SQLite database.

// add the searched text in SQLite database if NOT exists
let isExists: Bool = DB_Manager().isExists(searchedText: self.searchedText)
if (!isExists) {
    DB_Manager().addAnimal(nameValue: self.searchedText)
}

Now, we need to show the search history in the main content view when the user clicks on the search bar text field. So, create 2 state wrapper properties in your content view:

// variable to show search history view
@State var showSearchHistoryView: Bool = false

// array of history array
@State var history: [Animal] = []

And inside the body, we need to track the live text change of the input field. We have already created a binding variable inside the body of the content view. Change the binding variable inside the content view body to the following:

// live tracking of input field value
let binding = Binding<String>(get: {
    self.searchedText
}, set: { (value) in
    self.searchedText = value
    
    // show history if the text field is not empty
    self.showSearchHistoryView = !self.searchedText.isEmpty
})

Now, when the showSearchHistoryView variable is true, we need to display a list of all previously searched strings. So, create a list view under an if condition below the search bar text field:

// show history view only when a variable is true
if (self.showSearchHistoryView) {
    
    // create list view to show all history items
    List (self.history) { (model) in
    
        // show history text
        HStack {
        
            Image(systemName: "arrow.counterclockwise")
        
            Button(action: {
                self.searchedText = model.name
                self.gotoSearchPage = true
            }, label: {
                Text(model.name)
            })

        }
    }
}

This will display a counter clock icon that represents that it is data from history, a button that shows the previously searched string, and which when clicked will move to the search view.

Now, we need to load the data in our history array. So, attach an onAppear() event to your VStack and fetch the data from the SQLite database and save it in the history array.

// load data in history models array
.onAppear(perform: {
    self.history = DB_Manager().getAnimals()
})

Now, we need to create a function named getAnimals() in our DB_Manager class that will fetch the records from the SQLite database.

// return array of animal models
public func getAnimals() -> [Animal] {
     
    // create empty array
    var animalModels: [Animal] = []
 
    // get all animals in descending order
    animals = animals.order(id.desc)
 
    // exception handling
    do {
 
        // loop through all animals
        for animal in try db.prepare(animals) {
 
            // create new model in each loop iteration
            let animalModel: Animal = Animal()
 
            // set values in model from database
            animalModel.id = animal[id]
            animalModel.name = animal[name]
 
            // append in new array
            animalModels.append(animalModel)
        }
    } catch {
        print(error.localizedDescription)
    }
 
    // return array
    return animalModels
}

Comments have been added with each line for an explanation. If you run the code now, you will be able to view all the searched strings in a list view, upon click it will take you to the search view screen.

At this point, the search bar in Swift UI is completed. But you can go further and add the delete functionality. So user can remove his searched queries.

Delete history

Now, we need a function to delete the string from search history. First, create a button inside your history list after the counter-clock icon and button in your content view:

... counter-clock icon and button

// show delete button
Spacer()
Button(action: {
    
    // delete history item from SQLite
    DB_Manager().deleteAnimal(idValue: model.id)
    
    // refresh the list view
    self.history = DB_Manager().getAnimals()
    
}, label: {
    Text("Delete")
        .foregroundColor(Color.red)
})// by default, buttons are full width.
// to prevent this, use the following
.buttonStyle(PlainButtonStyle())

Now, we need to create a function named deleteAnimal() in our DB_Manager class that will delete the row from the SQLite database.

// function to delete animal from search history
public func deleteAnimal(idValue: Int64) {
    do {
    
        // get animal using ID
        let animal: Table = animals.filter(id == idValue)
         
        // run the delete query
        try db.run(animal.delete())
        
    } catch {
        print(error.localizedDescription)
    }
}

Run the code now, and you will be able to see a delete button at the end of each history row. Upon clicking, it will remove the row from the SQLite database and from the list view as well.

So you have successfully created a search bar in Swift UI along with search history.

You can also learn to create a UICollectionView with a search bar from the following tutorial.

UICollectionview with Search Bar – Swift iOS

[wpdm_package id=’929′]

Swift UI SQLite – Create, Read, Update and Delete in Swift

SQLite is used to store the data locally inside the app in SQL structure. It is a relational local database. You can use the SQLite database to store data inside the app using Swift and Swift UI.

We will be creating a simple iOS app in Swift UI to create, read, update, and delete users from the SQLite database.

We will be using a library called SQLite by Stephen Celis. To install this library, you must have Cocoapods installed in your system.

Installation

You can install Cocoapods in your system by simply running the following command in your terminal:

sudo gem install cocoapods

First, you need to open a command prompt (Terminal) at the root of your XCode project and run the following command in it:

pod init

Now you will see a new file created at the root of your project named Podfile. Open that file in your text editor and add the line to install the library. Following will be the content of your Podfile:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'SQLite_Database' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for SQLite_Database
  pod 'SQLite.swift', '~> 0.12.0'

end

After that, run the following command in your Terminal to install this library:

pod update

Once installed, close your XCode and re-open but this time double-click on the file which has an extension “.xcworkspace“. This file will be created only after the pod has been installed/updated.

1. Add user

First, we will create a model class that will hold the data structure for each user. Create a file named “UserModel.swift” and paste the following code in it:

//
//  UserModel.swift
//  SQLite_Database
//
//  Created by Adnan Afzal on 24/11/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import Foundation

class UserModel: Identifiable {
    public var id: Int64 = 0
    public var name: String = ""
    public var email: String = ""
    public var age: Int64 = 0
}

Your model class must conform to Identifiable protocol in order to show the users in List view.

DB_Manager.swift

To handle the database functions, we will create a separate file named “DB_Manager.swift“. In this class, we will create the database, tables and it’s columns in the constructor.

//
//  DB_Manager.swift
//  SQLite_Database
//
//  Created by Adnan Afzal on 24/11/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import Foundation

// import library
import SQLite

class DB_Manager {
    
    // sqlite instance
    private var db: Connection!
    
    // table instance
    private var users: Table!

    // columns instances of table
    private var id: Expression<Int64>!
    private var name: Expression<String>!
    private var email: Expression<String>!
    private var age: Expression<Int64>!
    
    // constructor of this class
    init () {
        
        // exception handling
        do {
            
            // path of document directory
            let path: String = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first ?? ""

            // creating database connection
            db = try Connection("\(path)/my_users.sqlite3")
            
            // creating table object
            users = Table("users")
            
            // create instances of each column
            id = Expression<Int64>("id")
            name = Expression<String>("name")
            email = Expression<String>("email")
            age = Expression<Int64>("age")
            
            // check if the user's table is already created
            if (!UserDefaults.standard.bool(forKey: "is_db_created")) {

                // if not, then create the table
                try db.run(users.create { (t) in
                    t.column(id, primaryKey: true)
                    t.column(name)
                    t.column(email, unique: true)
                    t.column(age)
                })
                
                // set the value to true, so it will not attempt to create the table again
                UserDefaults.standard.set(true, forKey: "is_db_created")
            }
            
        } catch {
            // show error message if any
            print(error.localizedDescription)
        }
        
    }
}

Comments have been added with each line for clarification. Now, in your content view, we will create a navigation link that will move to the AddUserView file.

AddUserView.swift

Open your content view file and place this code inside the body:

// create navigation view
NavigationView {

    VStack {

        // create link to add user
        HStack {
            Spacer()
            NavigationLink (destination: AddUserView(), label: {
                Text("Add user")
            })
        }

        // list view goes here

    }.padding()
    .navigationBarTitle("SQLite")
}

Now, create a new view file named “AddUserView.swift” and paste the following code in it:

//
//  AddUserView.swift
//  SQLite_Database
//
//  Created by Adnan Afzal on 24/11/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import SwiftUI

struct AddUserView: View {
    
    // create variables to store user input values
    @State var name: String = ""
    @State var email: String = ""
    @State var age: String = ""
    
    // to go back on the home screen when the user is added
    @Environment(\.presentationMode) var mode: Binding<PresentationMode>
    
    var body: some View {
        
        VStack {
            // create name field
            TextField("Enter name", text: $name)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .disableAutocorrection(true)
            
            // create email field
            TextField("Enter email", text: $email)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .keyboardType(.emailAddress)
                .autocapitalization(.none)
                .disableAutocorrection(true)
            
            // create age field, number pad
            TextField("Enter age", text: $age)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .keyboardType(.numberPad)
                .disableAutocorrection(true)
            
            // button to add a user
            Button(action: {
                // call function to add row in sqlite database
                DB_Manager().addUser(nameValue: self.name, emailValue: self.email, ageValue: Int64(self.age) ?? 0)
                
                // go back to home page
                self.mode.wrappedValue.dismiss()
            }, label: {
                Text("Add User")
            })
                .frame(maxWidth: .infinity, alignment: .trailing)
                .padding(.top, 10)
                .padding(.bottom, 10)
        }.padding()
        
    }
}

This is a bit lengthy but comments have been added with each line for an explanation.

At this point, you will see an error in the highlighted line. Because we have to create that function in our DB manager class. So, create the following function in your DB_Manager.swift file:

public func addUser(nameValue: String, emailValue: String, ageValue: Int64) {
    do {
        try db.run(users.insert(name <- nameValue, email <- emailValue, age <- ageValue))
    } catch {
        print(error.localizedDescription)
    }
}

If you run the app now, you will a link to add a user view, on that view you will see 3 fields. After filling the fields and hitting the submit button, the data will be saved in the SQLite database and you will be moved to the home view.

However, you will not see the data that has been saved in the database. So now we will show the data in List view.

2. View all users

In your content view, where you want to show all the data from the database, create a state property wrapper:

// array of user models
@State var userModels: [UserModel] = []

Now, create a list view in the content view body after the navigation link for adding a user view:

// create list view to show all users
List (self.userModels) { (model) in

    // show name, email and age horizontally
    HStack {
        Text(model.name)
        Spacer()
        Text(model.email)
        Spacer()
        Text("\(model.age)")
        Spacer()

        // edit and delete button goes here
    }
}

When the content view is loaded, we need to add the data from the database in that userModels array. Attach an onAppear function at the end of your VStack like below:

VStack {
    ...
}
// load data in user models array
.onAppear(perform: {
    self.userModels = DB_Manager().getUsers()
})

Now, we need to create a function named getUsers() in our DB manager class:

// return array of user models
public func getUsers() -> [UserModel] {
    
    // create empty array
    var userModels: [UserModel] = []

    // get all users in descending order
    users = users.order(id.desc)

    // exception handling
    do {

        // loop through all users
        for user in try db.prepare(users) {

            // create new model in each loop iteration
            let userModel: UserModel = UserModel()

            // set values in model from database
            userModel.id = user[id]
            userModel.name = user[name]
            userModel.email = user[email]
            userModel.age = user[age]

            // append in new array
            userModels.append(userModel)
        }
    } catch {
        print(error.localizedDescription)
    }

    // return array
    return userModels
}

This will fetch the users from the SQLite database in descending order (latest users first) and return them as an array of user model classes.

Run the app and now you will see the users that have been added in a tabular format. You can try removing the app from the background and open again, the data will still be there. Data will only be removed when the app is uninstalled.

3. Edit user

Editing the user requires multiple steps:

  1. Get user by ID.
  2. Show user details in input fields.
  3. Update the user in the database using his ID.

First, we need to create 2 state variables at the top of the content view which will tell WHEN the user is selected for editing and WHICH user is selected.

// check if user is selected for edit
@State var userSelected: Bool = false

// id of selected user to edit or delete
@State var selectedUserId: Int64 = 0

Now, in your HStack inside the list view, create a button to edit the user:

// button to edit user
Button(action: {
    self.selectedUserId = model.id
    self.userSelected = true
}, label: {
    Text("Edit")
        .foregroundColor(Color.blue)
    })
    // by default, buttons are full width.
    // to prevent this, use the following
    .buttonStyle(PlainButtonStyle())

This will set the userSelected variable to true, and selectedUserId to the ID of the user you have selected. Now we need to move to the new view to edit the user.

Create a navigation link with an empty view, inside the content view body and before the list view:

// navigation link to go to edit user view
NavigationLink (destination: EditUserView(id: self.$selectedUserId), isActive: self.$userSelected) {
    EmptyView()
}

EditUserView.swift

Create a new view file named EditUserView.swift and paste the following code into it. Pay close attention to the highlighted lines:

//
//  EditUserView.swift
//  SQLite_Database
//
//  Created by Adnan Afzal on 24/11/2020.
//  Copyright © 2020 Adnan Afzal. All rights reserved.
//

import SwiftUI

struct EditUserView: View {
    
    // id receiving of user from previous view
    @Binding var id: Int64
    
    // variables to store value from input fields
    @State var name: String = ""
    @State var email: String = ""
    @State var age: String = ""
    
    // to go back to previous view
    @Environment(\.presentationMode) var mode: Binding<PresentationMode>
    
    var body: some View {
        VStack {
            // create name field
            TextField("Enter name", text: $name)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .disableAutocorrection(true)
            
            // create email field
            TextField("Enter email", text: $email)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .keyboardType(.emailAddress)
                .autocapitalization(.none)
                .disableAutocorrection(true)
            
            // create age field, number pad
            TextField("Enter age", text: $age)
                .padding(10)
                .background(Color(.systemGray6))
                .cornerRadius(5)
                .keyboardType(.numberPad)
                .disableAutocorrection(true)
            
            // button to update user
            Button(action: {
                // call function to update row in sqlite database
                DB_Manager().updateUser(idValue: self.id, nameValue: self.name, emailValue: self.email, ageValue: Int64(self.age) ?? 0)

                // go back to home page
                self.mode.wrappedValue.dismiss()
            }, label: {
                Text("Edit User")
            })
                .frame(maxWidth: .infinity, alignment: .trailing)
                .padding(.top, 10)
                .padding(.bottom, 10)
        }.padding()

        // populate user's data in fields when view loaded
        .onAppear(perform: {
            
            // get data from database
            let userModel: UserModel = DB_Manager().getUser(idValue: self.id)
            
            // populate in text fields
            self.name = userModel.name
            self.email = userModel.email
            self.age = String(userModel.age)
        })
    }
}

struct EditUserView_Previews: PreviewProvider {
    
    // when using @Binding, do this in preview provider
    @State static var id: Int64 = 0
    
    static var previews: some View {
        EditUserView(id: $id)
    }
}

@Binding is used when you want to pass the value from one view to another. In that case, if you are using preview provider, then you have to create the @State variable in it.

At this time, you will be getting error at DB_Manager().updateUser and DB_Manager().getUser because these functions are not yet created in DB manager class.

First, we will create the function to get the single user from SQLite database using his ID. In your DB_Manager.swift:

// get single user data
public func getUser(idValue: Int64) -> UserModel {

    // create an empty object
    let userModel: UserModel = UserModel()
    
    // exception handling
    do {

        // get user using ID
        let user: AnySequence<Row> = try db.prepare(users.filter(id == idValue))

        // get row
        try user.forEach({ (rowValue) in

            // set values in model
            userModel.id = try rowValue.get(id)
            userModel.name = try rowValue.get(name)
            userModel.email = try rowValue.get(email)
            userModel.age = try rowValue.get(age)
        })
    } catch {
        print(error.localizedDescription)
    }

    // return model
    return userModel
}

The filter function at the highlighted line helps to perform the WHERE clause (to filter the data).

Now we need to create a function in the DB manager class to update the user in the SQLite database.

// function to update user
public func updateUser(idValue: Int64, nameValue: String, emailValue: String, ageValue: Int64) {
    do {
        // get user using ID
        let user: Table = users.filter(id == idValue)
        
        // run the update query
        try db.run(user.update(name <- nameValue, email <- emailValue, age <- ageValue))
    } catch {
        print(error.localizedDescription)
    }
}

Here, we are first getting the user object using the filter() function. Then we are running the update query on that user’s object.

Run the app and now you will see an “Edit” button at the end of each user’s record. Clicking on that will take you to another view, from where you will see the user’s data in input fields. Clicking the “Update” button will update the data and move it back to the home view.

4. Delete user

To delete a user from the SQLite database in Swift UI, first, we will create a delete button in the list view like we created the edit button.

// create list view to show all users
List (self.userModels) { (model) in

    // show name, email, and age horizontally
    HStack {
        ... edit button
        
        // button to delete user
        Button(action: {

            // create db manager instance
            let dbManager: DB_Manager = DB_Manager()

            // call delete function
            dbManager.deleteUser(idValue: model.id)

            // refresh the user models array
            self.userModels = dbManager.getUsers()
        }, label: {
            Text("Delete")
                .foregroundColor(Color.red)
        })// by default, buttons are full width.
        // to prevent this, use the following
        .buttonStyle(PlainButtonStyle())
    }
}

The above code should be placed after the edit button in the content view. You can see that we created an instance of DB_Manager class and save it in another variable. Because we need to call 2 functions from DB_Manager class.

The first function will delete the user from the SQLite database, and the second function will update the list view. So the delete user will be removed from view as well.

Create the following function in your DB_Manager class:

// function to delete user
public func deleteUser(idValue: Int64) {
    do {
        // get user using ID
        let user: Table = users.filter(id == idValue)
        
        // run the delete query
        try db.run(user.delete())
    } catch {
        print(error.localizedDescription)
    }
}

If you run the app now, you will see a delete button at the end of each user’s record. Clicking that button will remove the user from the database and from the list view as well. You can try removing the app from the background process and re-open it again, the deleted data will not appear again.

Where you can use SQLite in the iOS app?

You can create a feature to save the search history of users locally in the app. So users can re-search the same thing from search history.

You can cache the frequent data in SQLite, so instead of requesting the data from the server, it will be accessed from inside the app. It will increase the performance of your app.

Or you can simply create a server-less app like “Personal account book-keeping app” using SQLite and Swift UI. These type of apps does not require an internet connection to work and the user can use them even without access to the internet.

[wpdm_package id=’923′]

UITableView with search – Swift iOS

In this tutorial, we are going to teach you, how you can create a UITableView with search bar in iOS using Swift 4. Following are the steps:

Video tutorial:

  1. Create a new project in XCode.
  2. Drag and drop a “Table view” in your storyboard.
  3. Open assistant from top menu bar Editor > Assistant.
  4. Hold shift and drag & drop your tableview in your controller to create an outlet. Give it a name like “tableview”.
@IBOutlet weak var tableview: UITableView!
  1. Connect datasource and delegate of your table view with your controller.
  2. Extend your view controller from UITableViewDataSource and UITableViewDelegate.
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  1. Create an array of data, you might be getting this from API:
private var array: [String] = ["Cow", "Lion", "Wolf", "Camel", "Tiger"]
  1. Now register your table view with Swift built-in table view cell:
override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    self.tableview.register(UITableViewCell.self, forCellReuseIdentifier: "cellIdentifier")
}
  1. Now create 3 functions:
    • 1st will return the total number of items needs to be displayed in table view.
    • 2nd will display the values from array in each table view cell.
    • 3rd will be called whenever any cell item is being tapped or clicked.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.array.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell = self.tableview.dequeueReusableCell(withIdentifier: "cellIdentifier")!
    
    cell.textLabel?.text = self.array[indexPath.row]
    
    return cell
}

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print(self.array[indexPath.row])
}
  1. Then drag and drop “Search bar” in your storyboard at the top of table view and create its outlet in your controller same as you did in step 4.
@IBOutlet weak var searchBar: UISearchBar!

At this point, you can see the UITableView with search on top in the XCode preview. But we need to make it functional.

  1. Join it’s delegate with your controller same as in step 5.
  2. Implement the UISearchBarDelegate in your controller class:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
  1. Create another array which will hold the initial values:
private var initialArray: [String] = ["Cow", "Lion", "Wolf", "Camel", "Tiger"]
  1. Finally, create a function which will be called whenever you type something in the search bar. This function search the text in all the initial values of array. You can make the search case insensitive by making both the text lowercased, text of search bar and of array. We also have to put a condition that when the search bar is empty, then we will display all the values from initial array. Lastly, you need to reload the data in table view in order to see searched data.
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    let text: String = self.searchBar.text ?? ""
    self.array = []
    for item in self.initialArray {
        if (item.lowercased().contains(text.lowercased())) {
            self.array.append(item)
        }
    }
    if (text.isEmpty) {
        self.array = self.initialArray
    }
    self.tableview.reloadData()
}

Follow more iOS tutorials.

[wpdm_package id=’727′]

UIDatePicker timezone fix – Swift iOS

UiDatePicker in Swift has some timezone issues, so we will teach you how you can fix it.

Convert time to different timezones

If you are working on UIDatePicker in your Swift project, you might come across a problem that when fetching the value from UIDatePicker it usually returns the value by mapping with your timezone. But we want to have the actual value from the date picker as it is (without having timezone mapping).

UIDatePicker timezone fix

You can use the following function to get the actual value selected from date picker:

datepicker.date.description(with: .current)

Assuming datepicker is your outlet for type UIDatePicker. You can also prevent the user from selecting previous dates by writing the following line at the end of your viewDidLoad() function:

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    
    datepicker.minimumDate = Date()
}

Video tutorial:

Easy way to save the class object in user defaults – Swift iOS

When it comes to saving the class object in user defaults, there is a hard way to do using NSKeyedArchiver class. But there is an easy to do using JSONEncoder and JSONDecoder classes. In this tutorial, we will teach you how you can:

  1. Save the class object in defaults using Swift by encoding in JSON.
  2. Get a class object from defaults by decoding from JSON.
  3. Remove the class object from defaults.

First, create a model class in Swift which will be the class that needs to be stored in user defaults.

User.swift

import Foundation

class User: Codable {
    public var id: Int = 0
    public var name: String = ""
}

Make sure it is a type of Codable protocol, this will help to convert the class into JSON. Set the default values to all data members, integers to 0, and strings to empty string. Then we will create a file which will have all the functions to save, retrieve, and remove the class object value from user defaults, we name that class LocalStorageManager.

LocalStorageManager.swift

import Foundation

class LocalStorageManager {
    
    public func saveUser(user: User) {
        do {
            
            let jsonEncoder = JSONEncoder()
            let jsonData = try jsonEncoder.encode(user)
            let json = String(data: jsonData, encoding: .utf8) ?? "{}"
            
            let defaults: UserDefaults = UserDefaults.standard
            defaults.set(json, forKey: "user")
            defaults.synchronize()
            
        } catch {
            print(error.localizedDescription)
        }
    }
    
    public func getUser() -> User {
        do {
            if (UserDefaults.standard.object(forKey: "user") == nil) {
                return User()
            } else {
                let json = UserDefaults.standard.string(forKey: "user") ?? "{}"
                
                let jsonDecoder = JSONDecoder()
                guard let jsonData = json.data(using: .utf8) else {
                    return User()
                }
                
                let user: User = try jsonDecoder.decode(User.self, from: jsonData)
                return user
            }
        } catch {
            print(error.localizedDescription)
        }
        return User()
    }
    
    public func removeUser() {
        let defaults: UserDefaults = UserDefaults.standard
        defaults.removeObject(forKey: "user")
        defaults.synchronize()
    }
}
  1. Create a global data member that will be the key used to identify the object in user defaults.
  2. saveUser function will receive the User class instance as a parameter, convert that as JSON string and save in defaults.
  3. getUser function will return the user class instance by decoding from the JSON string. Here, we will handle all the validations that might be useful for decoding the JSON data.
  4. removeUser function is used to delete the user class instance from defaults.

To use this, we are going to simply call these functions from our main view controller file.

ViewController.swift

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let user: User = User()
        user.id = 565
        user.name = "Adnan"
        
        LocalStorageManager().saveUser(user: user)
        
        let cacheUser: User = LocalStorageManager().getUser() 
        print(cacheUser)
        
        LocalStorageManager().removeUser()
        
        let cacheUserAgain: User = LocalStorageManager().getUser() 
        print(cacheUserAgain)
    }
}
  1. First, we are creating an instance of user class and set the values.
  2. Then we are saving in defaults.
  3. After that, we are retrieving the saved user class object and printing it out for debugging.
  4. Finally, we are removing it from defaults and printing it out.

Learn how to do a CRUD operation using local storage in Swift UI

Local storage Swift UI – CRUD

UICollectionview with search bar – Swift iOS

In this article, we are going to show you how you can create a UICollectionview with search bar in Swift for your iOS application.

First, we will create a collection view and populate the data in it. We are using a MySQL database for employees table and a PHP API to fetch all employees data from database. The output of API will be in JSON format. So, we will also learn how to encode JSON data in Swift. We will be displaying employee number and name in it.

Create UICollectionView using storyboard

  1. First goto your storyboard, search for collection view and drag in in your main view.
  2. Your collection view will have a cell inside it. Search for label for employee number and drag it inside collection view cell.
Select collection view cell and set a custom class
add an identifer

Now select collection view, goto outlets, and attach data source & delegate of collection view to your view controller class.

Create a class for single cell layout named SingleCellView.swift:

import UIKit

class SingleCellView: UICollectionViewCell {
	// drag label outlet here
}

Select label from storyboard and drag it inside SingleCellView class:

Note: To drag label from storyboard into SingleCellView class, oepn storyboard, goto “Navigate” in menu and select “Open in assistant editor”. Then select the class file from left sidebar and it will appear in second window.

Populate data in UI collection view

We are receiving an array of objects from the API. Each object has employeeNumber, firstName, lastName, email and other fields as displayed above. We need to display them in each collection view cell:

EmployeeModel.swift

import Foundation

class EmployeeModel: Decodable {
    public var employeeNumber: String!
    
    public var firstName: String!
}
  1. Create an outlet for collection view same as we did for collection view cell labels.
  2. Open viewcontroller file and extend it with UICollectionViewDataSource and UICollectionViewDelegate
  3. Implement 2 functions, first for total number of items in collection view, and second for populating data in collection view cell.
  4. Create an array of EmployeeModel objects and initialize it as an empty array.
  5. We will be using NSURLConnection.sendAsynchronousRequest to fetch data from API.
  6. When the response is received, we validate the data using guard statement to make sure it is not null.
  7. Decode the JSON string into EmployeeModel array.

ViewController.swift

import UIKit

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UISearchBarDelegate {
    
    private var data: [EmployeeModel]! = []
    private var realData: [EmployeeModel]! = []
    
    @IBOutlet weak var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        let url: URL = URL(string: "http://192.168.43.64/test/api.php")!
        var request: URLRequest = URLRequest(url: url)
        request.httpMethod = "GET"
        
        // if using POST
//        request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
//        let dataStr: String = "value=1&value=2"
//        let postData: Data = dataStr.data(using: .utf8)!
//        request.httpBody = postData
        
        NSURLConnection.sendAsynchronousRequest(request, queue: .main) { (response, data, error) in
            
            guard let data = data else {
                print(error)
                return
            }
            
            let responseString: String! = String(data: data, encoding: .utf8)
            
            do {
                
                let jsonDecoder: JSONDecoder = JSONDecoder()
                self.data = try jsonDecoder.decode([EmployeeModel].self, from: data)
                
                self.realData = self.data
                
                self.collectionView.reloadData()
            } catch {
                print(error.localizedDescription)
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.data.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let singleCell: SingleCellView = collectionView.dequeueReusableCell(withReuseIdentifier: "singleCell", for: indexPath) as! SingleCellView
        
        singleCell.employeeNumber.text = self.data[indexPath.item].employeeNumber
        
        singleCell.firstName.text = self.data[indexPath.item].firstName
        
        return singleCell
    }
}

Add search bar in collection view

First select your collection view and enable section header. This will create a re-usable view inside collection view.

  1. Search for “Search bar” and drag it inside re-usable view. Also give it a identifier like we did for collection view cell.
  2. Set the custom class for re-usableview (in our case SearchBarView.swift), we will create that class in a moment.

SearchBarView.swift

import UIKit

class SearchBarView: UICollectionReusableView {
	// drag search bar outlet here same as we did for collection view cell
}
  1. Add delegate of search bar to our view controller same as we did for collection view delegate.
  2. Extend view controller class with UISearchBarDelegate and implement 2 more functions in this class.
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {

	let searchView: UICollectionReusableView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "SearchBar", for: indexPath)
	return searchView
}

func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
	self.data.removeAll()
        
	for item in self.realData {
		if (item.firstName.lowercased().contains(searchBar.text!.lowercased())) {
			self.data.append(item)
		}
	}
        
	if (searchBar.text!.isEmpty) {
		self.data = self.realData
	}
	self.collectionView.reloadData()
}

Now you will have a working UICollectionView with search bar in your iOS application.

Video tutorial:

How to upload single and multiple images in iOS Swift, PHP and MySQL

In this article, we will discuss how you can upload single or multiple images from your iOS app in Swift, and save them in the MySQL database.

Solution for Swift UI

If you are developing your app in Swift UI, please follow this post.

When developing iOS applications, one of the most common features in almost all apps is to upload images. It can be in the form of a profile picture, or payment receipt or anything. Swift provides a built-in method to allow developers to add functionality. There users can select an image from their photo library. However, to upload multiple images, there is no built-in method in Swift at the time of writing this. But we have external libraries that allow users to pick multiple images.

Save image from iOS app

When it comes to saving the image in the database, there are again multiple choices. You can either convert the image in an encoded base64 string or you can send an image entirely as multipart. The second choice is not very often used because it has some drawbacks. The major one of them is that the image with very high quality and large size are unable to transfer. So we will choose the first method i.e. to convert an image into an encoded base64 string.

1. Single image upload

In this method, no external library has been used. All the functions required to select single image from gallery are already provided by Swift. We just need to implement 2 delegates UIImagePickerControllerDelegate and UINavigationControllerDelegate to our view controller that will be responsible to open the screen to gallery and also to return the selected image. We have created a simple button which when clicked will open the UIImagePickerController in current view controller. imagePickerController this is a delegate function present in UIImagePickerControllerDelegate that will return the selected image from photo library. We are displaying that image in our UIImageView for confirmation, and also to send to the server. Because we can convert an image to base64 string using its UIImageView object.

Then we are creating a button which when clicked will convert the image to base64 string and send the request to the server. For sending an HTTP request, you also have many choices, for example, you can use the Alamofire library. But to keep things simple, we are using Swift’s built-in NSURLConnection class. Before sending the request we are also displaying a loading dialog and when the response is received from the server, we are simply displaying an alert that the image has been uploaded.

Swift iOS

import UIKit

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

    private var image: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let btnSelectImage: UIButton = UIButton(frame: CGRect(x: 30, y: 100, width: view.frame.size.width - 60, height: 30))
        btnSelectImage.setTitle("Select image", for: .normal)
        btnSelectImage.setTitleColor(UIColor.systemBlue, for: .normal)
        btnSelectImage.contentHorizontalAlignment = .center
        btnSelectImage.addTarget(self, action: #selector(selectImage), for: .touchUpInside)
        view.addSubview(btnSelectImage)
        
        image = UIImageView(frame: CGRect(x: 30, y: btnSelectImage.frame.origin.y + btnSelectImage.frame.size.height + 30, width: 300, height: 300))
        image.clipsToBounds = true
        image.contentMode = .scaleAspectFill
        view.addSubview(image)
        
        let btnUpload: UIButton = UIButton(frame: CGRect(x: 30, y: image.frame.origin.y + image.frame.size.height + 30, width: view.frame.size.width - 60, height: 40))
        btnUpload.setTitle("Upload to server", for: .normal)
        btnUpload.backgroundColor = UIColor.systemGreen
        btnUpload.setTitleColor(UIColor.white, for: .normal)
        btnUpload.addTarget(self, action: #selector(uploadToServer), for: .touchUpInside)
        btnUpload.layer.cornerRadius = 5
        view.addSubview(btnUpload)
    }
    
    @objc private func uploadToServer(sender: UITapGestureRecognizer) {
        let imageData: Data = image.image!.pngData()!
        let imageStr: String = imageData.base64EncodedString()

        let alert = UIAlertController(title: "Loading", message: "Please wait...", preferredStyle: .alert)
        present(alert, animated: true, completion: nil)

        let urlString: String = "imageStr=" + imageStr
        
        var request: URLRequest = URLRequest(url: URL(string: "http://172.20.10.2:8888/tutorials/single-multiple-image-upload/index.php")!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = urlString.data(using: .utf8)

        NSURLConnection.sendAsynchronousRequest(request, queue: .main, completionHandler: { (request, data, error) in

            guard let data = data else {
                return
            }

            let responseString: String = String(data: data, encoding: .utf8)!
            print("my_log = " + responseString)

            alert.dismiss(animated: true, completion: {

                let messageAlert = UIAlertController(title: "Success", message: responseString, preferredStyle: .alert)
                messageAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in
                    //
                }))

                self.present(messageAlert, animated: true, completion: nil)
            })
        })
    }
    
    @objc private func selectImage(sender: UITapGestureRecognizer) {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self as! UIImagePickerControllerDelegate & UINavigationControllerDelegate
        imagePicker.sourceType = UIImagePickerController.SourceType.photoLibrary
        imagePicker.allowsEditing = false
        present(imagePicker, animated: true, completion: nil)
    }
    
    @objc func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
        let chosenImage = info[UIImagePickerController.InfoKey.originalImage.rawValue] as! UIImage
        image.image = chosenImage
        dismiss(animated: true, completion: nil)
    }

}

PHP & MySQL

Make sure to change the server path with yours. If you are working on localhost, you can get your IP address by command prompt or terminal and running the command: ifconfig. In our PHP file, we are first receiving base64 string in a variable and then creating a path where the image will be stored. We need to create a folder named “images” in our server’s root folder.

Then we need to decode that base64 string into actual image file, so remove the base64 data part from a string, replace all empty spaces with + sign, and then decoding the base64 string, and finally saving the file in the images folder. We also need to save that file’s reference in our database, so we are simply making a connection with MySQL database and running an INSERT query to save the path of the image. Then we are sending the response as a string back to the iOS app. Make sure to change the database credentials as well as per your server.

<?php

$picture = $_POST["imageStr"];
$folder_path = "images/" . time() . ".png";

$data = str_replace('data:image/png;base64,', '', $picture);
$data = str_replace(' ', '+', $data);
$data = base64_decode($data);
file_put_contents($folder_path, $data);

$conn = mysqli_connect("localhost:8889", "root", "root", "tutorials");

$sql = "INSERT INTO images (path) VALUES ('$folder_path')";
mysqli_query($conn, $sql);

echo "Image has been uploaded";

?>

2. Multiple image upload

As discussed earlier, we need to use an external library to implement multiple image features in our iOS app. So we are going to use a library called BSImagePicker. It will be installed in our project using Cocoa pods, first, you need to initialize it. Open command prompt or terminal in your project’s root folder and run the following command:

pod init

This will create a Podfile (without any extension) in your project’s root folder. Open that file and include the library like the following, your project name could be different of course:

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'MultipleImageUpload' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for MultipleImageUpload
  pod "BSImagePicker", "~> 3.1"

end

Now run the command

pod update

to install the library. Once installed, close the project if already opened and now run the project using XCode but with the file ending with “.xcworkspace” NOT “.xcodeproj”. Now accessing the library requires user permission so open your “info.plist” file as source code and paste the following lines at the end of dict tag:

<key>NSPhotoLibraryUsageDescription</key>
<string>Why you want to access photo library</string>

Now open your view controller file and first import 2 files named BSImagePicker and Photos. When user select multiple images we can also show them in a collection view for a better user experience, for that purpose we need to implement 2 delegates, UICollectionViewDelegate and UICollectionViewDataSource. Creating a global variable for collection view so it can be accessible throughout the view controller class, colleection view has multiple cells and each cell has its own identifer and a class. For cell, we have created a class named ImageCell and it has only an image view because that is all we needed here.

Swift iOS

import UIKit

import BSImagePicker
import Photos

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
    
    private var collectionView: UICollectionView!
    private let identifier: String = "identifier"
    private var selectedImages: [UIImage] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        let btnSelectImage: UIButton = UIButton(frame: CGRect(x: 30, y: 100, width: view.frame.size.width - 60, height: 30))
        btnSelectImage.setTitle("Select images", for: .normal)
        btnSelectImage.setTitleColor(UIColor.systemBlue, for: .normal)
        btnSelectImage.contentHorizontalAlignment = .center
        btnSelectImage.addTarget(self, action: #selector(selectImages), for: .touchUpInside)
        view.addSubview(btnSelectImage)
        
        let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        flowLayout.minimumLineSpacing = 10
        flowLayout.scrollDirection = .horizontal
        flowLayout.minimumInteritemSpacing = 10
        flowLayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        flowLayout.itemSize = CGSize(width: 300, height: 300)

        collectionView = UICollectionView(frame: CGRect(x: 0, y: btnSelectImage.frame.origin.y + btnSelectImage.frame.size.height + 30, width: view.frame.size.width, height: 300), collectionViewLayout: flowLayout)
        collectionView.dataSource = self
        collectionView.delegate = self
        collectionView.backgroundColor = UIColor.clear.withAlphaComponent(0)
        collectionView.alwaysBounceHorizontal = true
        collectionView.register(ImageCell.self, forCellWithReuseIdentifier: identifier)
        view.addSubview(collectionView)
        
        let btnUpload: UIButton = UIButton(frame: CGRect(x: 30, y: collectionView.frame.origin.y + collectionView.frame.size.height + 30, width: view.frame.size.width - 60, height: 40))
        btnUpload.setTitle("Upload to server", for: .normal)
        btnUpload.backgroundColor = UIColor.systemGreen
        btnUpload.setTitleColor(UIColor.white, for: .normal)
        btnUpload.addTarget(self, action: #selector(uploadToServer), for: .touchUpInside)
        btnUpload.layer.cornerRadius = 5
        view.addSubview(btnUpload)
    }
    
    @objc private func uploadToServer(sender: UITapGestureRecognizer) {
        let alert = UIAlertController(title: "Loading", message: "Please wait...", preferredStyle: .alert)
        present(alert, animated: true, completion: nil)

        var imageStr: [String] = []
        for a in 0..<self.selectedImages.count {
            let imageData: Data = self.selectedImages[a].jpegData(compressionQuality: 0.1)!
            imageStr.append(imageData.base64EncodedString())
        }

        guard let data = try? JSONSerialization.data(withJSONObject: imageStr, options: []) else {
            return
        }

        let jsonImageString: String = String(data: data, encoding: String.Encoding.utf8) ?? ""
        let urlString: String = "imageStr=" + jsonImageString

        var request: URLRequest = URLRequest(url: URL(string: "http://172.20.10.2:8888/tutorials/single-multiple-image-upload/multiple.php")!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.httpMethod = "POST"
        request.httpBody = urlString.data(using: .utf8)

        NSURLConnection.sendAsynchronousRequest(request, queue: .main, completionHandler: { (request, data, error) in

            guard let data = data else {
                return
            }

            let responseString: String = String(data: data, encoding: .utf8)!
            print("my_log = " + responseString)

            alert.dismiss(animated: true, completion: {
                let messageAlert = UIAlertController(title: "Success", message: responseString, preferredStyle: .alert)
                messageAlert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction!) in
                    //
                }))
                self.present(messageAlert, animated: true, completion: nil)
            })
        })
    }
    
    @objc private func selectImages(sender: UITapGestureRecognizer) {
        let imagePicker = ImagePickerController()
        presentImagePicker(imagePicker, select: { (asset) in
        }, deselect: { (asset) in
            
        }, cancel: { (assets) in
            
        }, finish: { (assets) in
            
            self.selectedImages = []
            let options: PHImageRequestOptions = PHImageRequestOptions()
            options.deliveryMode = .highQualityFormat

            for asset in assets {
                PHImageManager.default().requestImage(for: asset, targetSize: PHImageManagerMaximumSize, contentMode: .aspectFit, options: options) { (image, info) in
                    self.selectedImages.append(image!)
                    self.collectionView.reloadData()
                }
            }
        })
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return selectedImages.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let data: UIImage = selectedImages[indexPath.item]
        let cell: ImageCell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as! ImageCell
        cell.image.image = data
        return cell
    }


}

class ImageCell: UICollectionViewCell {
    var image: UIImageView!

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupViews()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupViews()
    }
    
    private func setupViews() {
        image = UIImageView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        image.clipsToBounds = true
        image.contentMode = .scaleAspectFill
        addSubview(image)
    }
}

PHP & MySQL

As we are sending multiple images in base64 string. So, we have to loop through all and save them one-by-one in the server as well as in MySQL database. The code for this is pretty much same as the previous file.

<?php

$conn = mysqli_connect("localhost:8889", "root", "root", "tutorials");
$imageStr = json_decode($_POST["imageStr"]);

for ($a = 0; $a < count($imageStr); $a++)
{
	$folder_path = "images/" . $a . "-" . time() . ".png";

	$picture = $imageStr[$a];
	$data = str_replace('data:image/png;base64,', '', $picture);
	$data = str_replace(' ', '+', $data);
	$data = base64_decode($data);

	file_put_contents($folder_path, $data);

	$sql = "INSERT INTO images (path) VALUES ('$folder_path')";
	mysqli_query($conn, $sql);
}

echo "Image has been uploaded";

?>

So that’s how you can upload single or multiple images from your iOS app in Swift, and save them in the MySQL database.

[wpdm_package id=’62’]