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

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”.
1
@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.
1
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  1. Create an array of data, you might be getting this from API:
1
private var array: [String] = ["Cow", "Lion", "Wolf", "Camel", "Tiger"]
  1. Now register your table view with Swift built-in table view cell:
1
2
3
4
5
6
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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.
1
@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:
1
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate {
  1. Create another array which will hold the initial values:
1
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
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:

1
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:

1
2
3
4
5
6
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

1
2
3
4
5
6
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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:

1
2
3
4
5
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

1
2
3
4
5
6
7
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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

1
2
3
4
5
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?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:

1
2
3
4
5
6
7
8
9
10
11
# 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:

1
2
<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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?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’]