Alamofire is an HTTP networking library written in Swift.
SwiftyJSON makes it easy to deal with JSON data in Swift.
iOS
Create your own Slider menu (Drawer) in Swift
This article is updated with Swift 4 – Xcode 9 – iOS 11
Why to use a library everytime?
Let’s create our own Slide Menu (Drawer) in Swift 4.
1. Create New Project in Xcode 9 with Swift Language
2. Design the Menu in UIViewController
Declaration of Variables and Protocols (Delegate) :
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 |
protocol SlideMenuDelegate { func slideMenuItemSelectedAtIndex(_ index : Int32) } class MenuViewController: UIViewController, UITableViewDataSource, UITableViewDelegate { /** * Array to display menu options */ @IBOutlet var tblMenuOptions : UITableView! /** * Transparent button to hide menu */ @IBOutlet var btnCloseMenuOverlay : UIButton! /** * Array containing menu options */ var arrayMenuOptions = [Dictionary<String,String>]() /** * Menu button which was tapped to display the menu */ var btnMenu : UIButton! /** * Delegate of the MenuVC */ var delegate : SlideMenuDelegate? } |
Following method is for updating the Items in the Menu :
1 2 3 4 5 |
func updateArrayMenuOptions(){ arrayMenuOptions.append(["title":"Home", "icon":"HomeIcon"]) arrayMenuOptions.append(["title":"Play", "icon":"PlayIcon"]) tblMenuOptions.reloadData() } |
Following method is for click event and animation :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
@IBAction func onCloseMenuClick(_ button:UIButton!){ btnMenu.tag = 0 if (self.delegate != nil) { var index = Int32(button.tag) if(button == self.btnCloseMenuOverlay){ index = -1 } delegate?.slideMenuItemSelectedAtIndex(index) } UIView.animate(withDuration: 0.3, animations: { () -> Void in self.view.frame = CGRect(x: -UIScreen.main.bounds.size.width, y: 0, width: UIScreen.main.bounds.size.width,height: UIScreen.main.bounds.size.height) self.view.layoutIfNeeded() self.view.backgroundColor = UIColor.clear }, completion: { (finished) -> Void in self.view.removeFromSuperview() self.removeFromParentViewController() }) } |
3. Now we will create a Base UIViewController to use anywhere in the project which control the delegate of menu.
First we will create this 3 lines Drawer Icon via Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
func addSlideMenuButton(){ let btnShowMenu = UIButton(type: UIButtonType.system) btnShowMenu.setImage(self.defaultMenuImage(), for: UIControlState()) btnShowMenu.frame = CGRect(x: 0, y: 0, width: 30, height: 30) btnShowMenu.addTarget(self, action: #selector(BaseViewController.onSlideMenuButtonPressed(_:)), for: UIControlEvents.touchUpInside) let customBarItem = UIBarButtonItem(customView: btnShowMenu) self.navigationItem.leftBarButtonItem = customBarItem; } func defaultMenuImage() -> UIImage { var defaultMenuImage = UIImage() UIGraphicsBeginImageContextWithOptions(CGSize(width: 30, height: 22), false, 0.0) UIColor.black.setFill() UIBezierPath(rect: CGRect(x: 0, y: 3, width: 30, height: 1)).fill() UIBezierPath(rect: CGRect(x: 0, y: 10, width: 30, height: 1)).fill() UIBezierPath(rect: CGRect(x: 0, y: 17, width: 30, height: 1)).fill() UIColor.white.setFill() UIBezierPath(rect: CGRect(x: 0, y: 4, width: 30, height: 1)).fill() UIBezierPath(rect: CGRect(x: 0, y: 11, width: 30, height: 1)).fill() UIBezierPath(rect: CGRect(x: 0, y: 18, width: 30, height: 1)).fill() defaultMenuImage = UIGraphicsGetImageFromCurrentImageContext()! UIGraphicsEndImageContext() return defaultMenuImage } |
Delegate (Protocol) method call :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
func slideMenuItemSelectedAtIndex(_ index: Int32) { let topViewController : UIViewController = self.navigationController!.topViewController! print("View Controller is : \(topViewController) \n", terminator: "") switch(index){ case 0: print("Home\n", terminator: "") self.openViewControllerBasedOnIdentifier("Home") break case 1: print("Play\n", terminator: "") self.openViewControllerBasedOnIdentifier("PlayVC") break default: print("default\n", terminator: "") } } |
To open a view controller by identifier :
Set the Restoration Identifier and Storyboard Identifier. If current view is open then we will not open it once again for that we have to check via Restoration Identifier.
1 2 3 4 5 6 7 8 9 |
func openViewControllerBasedOnIdentifier(_ strIdentifier:String){ let destViewController : UIViewController = self.storyboard!.instantiateViewController(withIdentifier: strIdentifier) let topViewController : UIViewController = self.navigationController!.topViewController! if (topViewController.restorationIdentifier! == destViewController.restorationIdentifier!){ print("Same VC") } else { self.navigationController!.pushViewController(destViewController, animated: true) } } |
4. Now We will assign this drawer to any of the UIViewController
We have to use only one method to add drawer (slide menu) self.addSlideMenuButton()
1 2 3 4 5 6 7 |
import UIKit class HomeVC: BaseViewController { override func viewDidLoad() { super.viewDidLoad() addSlideMenuButton() } } |
Source Code is available at the Github AKSwiftSlideMenu
You can download for versions of Swift 2, Swift 3 or Swift 4. From Releases Tab at GitHub AKSwiftSlideMenu.
Check other blog posts about Swift
Happy Coding 🙂
Update : JSON Array Parsing in Swift Language – Swift 3 – iOS 10 – Xcode 8
So, how to parse following type of JSON?
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 |
"contacts": [ { "id": "c200", "name": "Ashish Kakkad", "email": "ashishhkakkad@gmail.com", "address": "xx-xx-xxxx,x - street, x - country", "gender" : "male", "phone": { "mobile": "+91 0000000000", "home": "00 000000", "office": "00 000000" } }, { "id": "c201", "name": "Johnny Depp", "email": "johnny_depp@gmail.com", "address": "xx-xx-xxxx,x - street, x - country", "gender" : "male", "phone": { "mobile": "+91 0000000000", "home": "00 000000", "office": "00 000000" } } ] |
Create JSON Array Object :
1 2 3 4 5 6 7 8 9 |
let url=URL(string:"https://ashishkakkad.com/contacts.json") do { let allContactsData = try Data(contentsOf: url!) let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject] if let arrJSON = allContacts["contacts"] { } } catch { } |
Parse JSON Array Object :
1 2 3 4 5 6 7 8 9 |
if let arrJSON = allContacts["contacts"] { for index in 0...arrJSON.count-1 { let aObject = arrJSON[index] as! [String : AnyObject] names.append(aObject["name"] as! String) contacts.append(aObject["email"] as! String) } } print(names) print(contacts) |
Complete code snippet with UITableView:
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 |
// // ViewController.swift // SwiftJSONParsingDemo // // Created by Ashish Kakkad on 12/10/16. // Copyright © 2016 Kode. All rights reserved. // import UIKit class ViewController: UIViewController { @IBOutlet weak var tableView: UITableView! var names: [String] = [] var contacts: [String] = [] override func viewDidLoad() { super.viewDidLoad() let url=URL(string:"https://ashishkakkad.com/contacts.json") do { let allContactsData = try Data(contentsOf: url!) let allContacts = try JSONSerialization.jsonObject(with: allContactsData, options: JSONSerialization.ReadingOptions.allowFragments) as! [String : AnyObject] if let arrJSON = allContacts["contacts"] { for index in 0...arrJSON.count-1 { let aObject = arrJSON[index] as! [String : AnyObject] names.append(aObject["name"] as! String) contacts.append(aObject["email"] as! String) } } print(names) print(contacts) self.tableView.reloadData() } catch { } } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() // Dispose of any resources that can be recreated. } func tableView(_ tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return self.names.count; } func tableView(_ tableView: UITableView!, didSelectRowAtIndexPath indexPath: IndexPath!) { print("You selected name : "+names[indexPath.row]) } func tableView(_ tableView: UITableView, cellForRowAtIndexPath indexPath: IndexPath) -> UITableViewCell{ var cell = tableView.dequeueReusableCell(withIdentifier: "cell") if !(cell != nil) { cell = UITableViewCell(style: .subtitle, reuseIdentifier: "cell") } cell?.textLabel?.text=self.names[indexPath.row] cell?.detailTextLabel?.text = self.contacts[indexPath.row] return cell! } } |
Posted a gist on github.
Helping, Learning, Coding 🙂