iOS Revisited

Hot

Post Top Ad

13 Sept 2017

Toggle between ListView(UITableView) and GridView(UICollectionView) - iOS, Swift 4

9/13/2017 04:09:00 am 1
In this article we are creating a sample project on how to switch between ListView and GridView.

Toggle between ListView(UITableView) and GridView(UICollectionView) - iOS, Swift 4

This Article Covers Following Related questions  :

How to Switch Between List View and Grid View in iOS.
UICollectionView - ListView and GridView.
Change the flow layout of a collectionView – from grid to list view.
Converting a UICollectionView to a UITableView.
Swift ios switching between listview and gridview
uitableview uicollectionview switch
uicollectionview table layout


In iOS native We call ListView as UITableView and GridView as UICollectionView.

Every one thinks that we need to take both UITableView & UICollectionView to achieve our goal. But that's Wrong.

We can achieve using UICollectionView itself. Let's see how simple to create ListView and GridView with UICollectionView.

Before starting this tutorial please read How to create UICollectionView.

If already done then download the starter project from here.


Open the file UICollectionViewProgramitically-master then open 'UICollectionViewProgramitically.xcodeproj'.

Build and run we can see Collection View or Grid Layout.

UICollectionViewProgramitically
We are going to use same project for the ListView also.

Getting Started :

Initially change project name to ListAndGrid.

Xcode App name change

Then a new pop window comes like follow:

App name change Confirmation

Tap on rename, then OK. Build and Run nothing changed.

First step is we need to create List cell and Grid cell. Grid cell already present as Custom Cell. List cell is not exists.


Creating ListCell :

So first create List cell. Add the following code at the end of ViewController.Swift file.
class ListCell : UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        setUpViews()
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

Next add imageView, Title Label and Description label to ListCell.

So, add the following code for adding sub views to ListCell :

let imgView : UIImageView = {
    let imageView = UIImageView()
    imageView.image = UIImage(named: "car.jpg")
    imageView.contentMode = .scaleAspectFill
    imageView.clipsToBounds = true
    imageView.translatesAutoresizingMaskIntoConstraints = false
    return imageView
}()

let titleLabel : UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.title2)
    
    return label
}()

let descriptionLabel : UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.numberOfLines = 0
    label.font = UIFont.preferredFont(forTextStyle: UIFontTextStyle.body)
    return label
}()

After creating sub views we need to add them as sub views with proper layout.

Add the following method to the end of ListCell:

func setUpViews() {
    backgroundColor = UIColor.init(red: 245.0/255.0, green: 245.0/255.0, blue: 245.0/255.0, alpha: 1.0)
    addSubview(imgView)
    addSubview(titleLabel)
    addSubview(descriptionLabel)
    imgView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true
    imgView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true
    imgView.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true
    imgView.widthAnchor.constraint(equalToConstant: frame.height).isActive = true
    
    titleLabel.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8).isActive = true
    titleLabel.topAnchor.constraint(equalTo: imgView.topAnchor, constant: 4).isActive = true
    titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .vertical)
    
    descriptionLabel.topAnchor.constraint(equalTo: titleLabel.bottomAnchor, constant: 4).isActive = true
    descriptionLabel.leadingAnchor.constraint(equalTo: imgView.trailingAnchor, constant: 8).isActive = true
    descriptionLabel.bottomAnchor.constraint(equalTo: imgView.bottomAnchor, constant: -4).isActive = true
    descriptionLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8).isActive = true
    descriptionLabel.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
}

Great we created ListCell. Next step is we need to add ListCell to UICollectionView.

Before that we need to add some Global variables. Add the following code after Cell Identifier :

let listCellIdentifier = "ListCell"

var isListView = false

var toggleButton = UIBarButtonItem()

Next, register the ListCell to create new cells in collection View and add Toggle Button to Navigation Bar. Add the following code inside viewDidLoad() method :
collectionView?.register(ListCell.self, forCellWithReuseIdentifier: listCellIdentifier)

toggleButton = UIBarButtonItem(title: "List", style: .plain, target: self, action: #selector(butonTapped(sender:)))
self.navigationItem.setRightBarButton(toggleButton, animated: true)

Add the following method that calls when Ever toggle Button has been tapped.
@objc func butonTapped(sender: UIBarButtonItem) {
    if isListView {
        toggleButton = UIBarButtonItem(title: "List", style: .plain, target: self, action: #selector(butonTapped(sender:)))
        isListView = false
    }else {
        toggleButton = UIBarButtonItem(title: "Grid", style: .plain, target: self, action: #selector(butonTapped(sender:)))
        isListView = true
    }
    self.navigationItem.setRightBarButton(toggleButton, animated: true)
    self.collectionView?.reloadData()
}

The above method will check the condition whether to show list or grid then reloads the collection View to show the corresponding view.

Then Replace the code inside cellForItemAt method with the following code:

if isListView {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: listCellIdentifier, for: indexPath) as! ListCell
    cell.titleLabel.text = "Ferrari 812 Superfast"
    cell.descriptionLabel.text = "The car has a larger 6.5-liter V12 engine compared to the 6.3-liter used in the F12berlinetta. The engine produces 800 PS (588 kW, 789 bhp) at 8,500 rpm and 718 N·m (530 lbf·ft) of torque at 7,000 rpm. The 812 Superfast's V12 engine is, in 2017, the most powerful naturally aspirated production car engine ever made."
    return cell
}else {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CustomCell
    return cell
}

The main and important thing for changing the ListView and GridView is the Size of CollectionViewCell.

So ListCell means the width must equal to the device width. So, replace the code inside sizeForItemAt method with the following code.

let width = view.frame.width
if isListView {
    return CGSize(width: width, height: 120)
}else {
    return CGSize(width: (width - 15)/2, height: (width - 15)/2)
}

Great, Build and Run now we will see GridView. Tap on List button the view changes from grid to list and Vice-versa.

Switching between ListView(UITableView) and GridView(UICollectionView) - iOS, Swift 4

Download sample project with examples :


Read More

ARKit Tutorial iOS Example using Swift 4 - iOS 11.

9/13/2017 02:40:00 am 0
In this tutorial we are going to create Augmented Reality example by using ARKit released by apple in Swift 4.

We need to integrate iOS device camera and motion features to produce augmented reality experiences in the app. For that Apple introduced SceneKit, this will do all for us.
So we are going to start ARKit using SceneKit.


ARKit Tutorial

Requirements : 

Xcode 9 , Device with an A9 or later processor running with iOS11.

We are going to add a cube to real word. 

Getting Started :


First create a new project -> open Xcode -> File -> New -> Project -> Single View App, then tap next button. Type product name as 'ARKitAddingCube' then tap next and select the folder to save project.

We are going to use camera, So add 'NSCameraUsageDescription' to Info.plist.


NSCameraUsageDescription
Then open ViewController.swift add the following line next to 'import UIKit'.
import ARKit

For getting access to camera we are going to add ARSCNView() as subview. ARSCNView will provide camera to us.

Add the following property before viewDidLoad() method.

var sceneView = ARSCNView()

Add created property as subview. Write following code inside viewDidLoad() method.
sceneView.frame = view.frame
view.addSubview(sceneView)

Build and Run you nothing is there except white screen. No worries stop and follow next steps.

As we all know that camera is based on sessions. So for this also we need to create and maintain sessions. For ARKit we are going to create ARSession.

Every session is based on configuration. In ARKIt there are ARSessionConfiguration.

The good thing about using SceneKit is no need to create session by default ARSCNView() having a session. But the for running session we need ARSessionConfiguration. Then configuration as follow.

let configuration = ARWorldTrackingSessionConfiguration()

Then run the session with above configuration.
sceneView.session.run(configuration)
Build and Run, we see camera's permission . Allow camera and we see camera running on your device.
 

Now its time to add a cube to real world space.

Before that, add a Button to view. Add two methods next to viewDidLoad() method.

@IBAction func addCubeButtonTapped(sender: UIButton) {
    print("Cube Button Tapped")
}

func addButton() {
    let button = UIButton()
    view.addSubview(button)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setTitle("Add a CUBE", for: .normal)
    button.setTitleColor(UIColor.red, for: .normal)
    button.backgroundColor = UIColor.white.withAlphaComponent(0.4)
    button.addTarget(self, action: #selector(addCubeButtonTapped(sender:)) , for: .touchUpInside)
    
    // Contraints
    button.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -8.0).isActive = true
    button.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0.0).isActive = true
    button.heightAnchor.constraint(equalToConstant: 50)
}

Then add 'addButton()' to the end of viewDidLoad() method.

Build and Run we will see Button at the bottom.


In this whole project we don't use StoryBoards. If you want to know why follow this link.

http://iosrevisited.blogspot.com/2017/08/11-reasons-why-not-to-use-storyboards.html

Now all set for adding Cube.

Providing 3D Virtual Content with SceneKit.

For adding any object to scene we need to create SCNNode and add that as a child node to SceneView.

let's create SCNNode as follow. Write the following code in @IBAction method.

let cubeNode = SCNNode(geometry: SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0)) // SceneKit/AR coordinates are in meters

CubeNode created with a 0.1 meters of height, width and length.

Now where to position this cube ? In this for visualize we are going to place 0.2 metres in front of device. Give position to cubeNode as follow.

cubeNode.position = SCNVector3(0, 0, -0.2)

Then add cubeNode as child node to Scenview.
self.sceneView.scene.rootNode.addChildNode(cubeNode)

Great! Build and Run, Tap on Add a cube button, we see white cube. Move device around if can not see Cube.

ARKit adding a cube to real world


On tapping Add a Cube button multiple times it's adding cube again and again at same position so we can't see multiple cubes.

Next step, adding multiple cubes to real world space. 

For this nothing much to do. Simply we need to change cubes position according to cameras position.

To get camera relative postion add following method.

func getMyCameraCoordinates(sceneView: ARSCNView) -> MDLTransform {
    let cameraTransform = sceneView.session.currentFrame?.camera.transform
    let cameraCoordinates = MDLTransform(matrix: cameraTransform!)
    return cameraCoordinates
}

By using above method we get camera relative position. So we need give cube node postion as camera position.

Replace code inside 'addCubeButtonTapped' method with the following code.

DispatchQueue.main.async {
    print("cube button tapped")
    let cubeNode = SCNNode(geometry: SCNBox(width: 0.1, height: 0.1, length: 0.1, chamferRadius: 0))
    let cc = self.getMyCameraCoordinates(sceneView: self.sceneView)
    cubeNode.position = SCNVector3(cc.translation.x, cc.translation.y, cc.translation.z)
    self.sceneView.scene.rootNode.addChildNode(cubeNode)
}

In the above code we are assigning camera's position to cube node.

Done. Build and Run we will see camera with 'Add a Cube' button.

Now tap button and wait until cube appears. If not step back and see. Move your device as you like and observe the added cube, it won't change it's position. That's what Augmented Reality means.

Your final output for ARKit will be like the following Video.


ARKit adding a multiple cubes to real world - swift 4, iOS


Download sample project with examples :

Read More

9 Sept 2017

Email Validation,Password Validation,URL Validation using Regex - Swift 4, iOS

9/09/2017 11:47:00 pm 4
Now a days, every app is using signup and login method. For that we need to do Field Validation, so that we can avoid fake signups and logins.

In this article we are going to cover following validation :

1. Email Validation. (iosrevisited@gmail.com)
2. Password Validation. (Password@22)
3. URL Validation. (http://iosrevisited.blogspot.com)

This Article Covers Following Related questions  :

How to validate an e-mail address in swift?
Email & Phone Number Validation in Swift 3.?
swift email address validation -ios
url validation in swift3
swift 3 validate email address
password validation in swift
text field validation in swift
password validation in swift 3
email validation in swift3
password length validation in swift


 Email Validation,Password Validation,URL Validation using Regex - Swift 4, iOS


1. Email Validation :

We are using regex for validating email.

Some valid emails :

abc@gmail.com, hello@yahoo.com

Add the following method for email validation :

func isValidEmail(email: String) -> Bool {
    let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"
    let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
    let result = emailTest.evaluate(with: email)
    return result
}

Then call the above method as following :
var isValid = isValidEmail(email: textField.text!)

If valid it will give true otherwise false.

2. Password Validation :

There are different formats for password. Here we will do most commonly used format.

- Password length 6 to 16.
- One Alphabet in Password.
- One Special Character in Password.

Some valid Password :

letmein@11, swift&ios

Add the following method for Password validation :
func isValidPassword(password: String) -> Bool {
    let passwordRegEx = "^(?=.*[a-z])(?=.*[$@$#!%*?&])[A-Za-z\\d$@$#!%*?&]{6,16}"
    let passwordTest = NSPredicate(format:"SELF MATCHES %@", passwordRegEx)
    let result = passwordTest.evaluate(with: password)
    return result
}

Then call the above method as following :
var isValid = isValidPassword(email: textField.text!)

If valid it will give true otherwise false.

3. URL Validation :

We are validating url using regex.

Some valid Url's :

http://iosrevisited.blogspot.com, http://adeepdrive.com.

Add the following method for URL validation :
func isValidUrl(url: String) -> Bool {
    let urlRegEx = "(http|https)://((\\w)*|([0-9]*)|([-|_])*)+([\\.|/]((\\w)*|([0-9]*)|([-|_])*))+"
    let urlTest = NSPredicate(format:"SELF MATCHES %@", urlRegEx)
    let result = urlTest.evaluate(with: url)
    return result
}

Then call the above method as following :
var isValid = isValidUrl(email: textField.text!)

If valid it will give true otherwise false.

Download sample project with examples :

Read More

5 Sept 2017

UICollectionView Programmatically With Out Main.storyboard - Swift, iOS

9/05/2017 10:04:00 am 0
In this article we are going to create a sample project which explains all about UICollectionView.

In other programming languages collection view is called as grid View.

How to create UICollectionView using Swift without storyboards.

This Article Covers All Related questions  :

How to create UICollectionView using Swift without storyboards.
create uicollectionview programmatically swift 3.
uicollectionview programmatically example.
custom uicollectionviewcell programmatically swift.
programmatically create uicollectionview swift.
uicollectionview swift example.
uicollectionview custom cell example.



UICollectionView :

An object that manages an ordered collection of data items and presents them using customizable layouts.

Mainly collection view layout is used for displaying images rather than content.


Sample Project :

Firstly create a new project  open Xcode -> File -> New -> Project -> Single View App, then tap next button. Type product name as 'UICollectionViewProgramitically' then tap next and select the folder to save project.

We are not going to use Main.storyboard, so delete it and tap on 'Move to trash'.

 

Main.storyboard, so delete it and tap on 'Move to trash'.

Now if you run the project, it will crash with a reason 'Could not find a storyboard named 'Main' in bundle'. So fix that, go to project general settings and under 'Deployment Info' delete Main from 'Main Interface'.




'Main Interface'  to empty

Now run we will see black screen with out any crash. Good!


Let's get started. Open ViewController.swift them change class name from ViewController to UICollectionViewController.

Open AppDelegate.swift, add the following code inside 'didFinishLaunchingWithOptions' method.

window = UIWindow(frame: UIScreen.main.bounds) // 1
window?.makeKeyAndVisible()
let layout = UICollectionViewFlowLayout() // 2
let viewController = ViewController(collectionViewLayout: layout) // 3
window?.rootViewController = UINavigationController(rootViewController: viewController) // 4

1. Creating a window of size equal to device size. This window will keep all View Controllers hierarchy.

2. UICollectionViewFlowLayout is a default layout for collection View.


3. Initializing the ViewController with default layout.


4. Setting up the rootViewController to the window. We embedded view Controller inside UINavigationController.

Build and Run we still see the black background but here we are having navigation bar too.

Navigation bar

Creating Custom CollectionViewCell:

Firstly we will start with Custom Cell. Add the following class at the end of view controller class.
class CustomCell: UICollectionViewCell{
    
}

First we need to initialize cell. So add the following code inside CustomCell.
override init(frame: CGRect) {
    super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

In this collection view we are going to show images so, let's create imageView. Add the following code after init(frame: CGRect) method :
let imgView : UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.image = UIImage(named: "car.png")
    imageView.contentMode = .scaleAspectFill
    return imageView
}()

Here we are showing car image, so drag the image to the project and name it as car.png.

Then add the imgView to cell and provide auto layout as we required. Add the following code inside init(frame: CGRect) method :
addSubview(imgView)
imgView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
imgView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
imgView.topAnchor.constraint(equalTo: topAnchor).isActive = true
imgView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true

Great we created custom collection view cell.

Next step is adding custom cell to collection view.

Add Custom cell to Collection View :

First create cell identifier. Add the following line before viewDidLoad() method.
let cellIdentifier = "ImageCell"

Next register collection view with custom class. Add the following code inside viewDidLoad() method:
collectionView?.backgroundColor = UIColor.white
collectionView?.register(CustomCell.self, forCellWithReuseIdentifier: cellIdentifier)

There are two delegate methods which are required

1. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int

2. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

First one is for number of cells we need in a section.

Second one is for, which cell we are going to use. We can use different custom cells in one UICollectionView. Here we have one cell so no worries.

Add the following delegate methods : 

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 6
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CustomCell
    
    return cell
}

Build and Run, we will see images. Great working fine but the padding between cell are not looking great.

create uicollectionview programmatically swift 3.


For that we have different delegate layout methods. We use some of them for our layout.


First add UICollectionViewDelegateFlowLayout delegate next to UICollectionViewController class.

Then add the following methods for layout and padding.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let width = view.frame.width
    return CGSize(width: (width - 15)/2, height: (width - 15)/2)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    return 5
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
}

Now Build and Run, we see car images with good looking.

create uicollectionview programmatically swift 3.
Download sample project with examples :

Read More

31 Aug 2017

Local Notifications using UserNotifications Class - Swift, iOS

8/31/2017 03:00:00 am 0
Local Notifications are mainly used in iOS apps for notifying user when new data or information available for your app.This will notify, even if the app is background.

Earlier we were using UILocalNotification class for sending local notification, now UILocalNotification deprecated in iOS 10.

From iOS 10 apple introduced new class called UserNotifications for sending or receiving notification. We can use UserNotifications for both Local Notification & Remote Notifications.

This Article Covers All Related questions  :

How to schedule a local notification in iOS 10 Swift.
Introduction to User Notifications Framework in iOS 10.
How To Set Up iOS 10 Local Notifications.
How to Make Local Notifications in iOS 10.


Notification center with LOCAL NOTIFICATION


UserNotifications :

UserNotifications framework used for delivery and handling of Local Notification & Remote Notifications. We can use this UserNotifications class for schedule the delivery of local notification based on either time or location. Apps and extensions also use this framework to receive and potentially modify local and remote notifications when they are delivered to the user’s device.

Local Notification :

With this, our app configures the notification details locally and passes those details to the system, which then handles the delivery of the notification when your app is not in the foreground.

When to Use :

Local notification can be used based on app data and functionality. Mostly used because, always apps are not running in foreground so we can alert user when a new information is downloaded from server, or may be from local data.

Local notification and Remote notification both same in appearance, when presented on a given device.

For delivering notification we are having 3 options, we can choose one of the following :

1. An onscreen alert or banner
2. A badge on your app’s icon
3. A sound that accompanies an alert, banner, or badge

Example Project:

First create a new project  open Xcode -> File -> New -> Project -> Single View App, then tap next button. Type product name as 'LocalNotifications-swift' then tap next and select the folder to save project.

For sending notification we need some action to be done, for that we are adding button to view of ViewController.

Let’s get started by first declaring a property of type UIButton and give auto layouts, title as we requires. Add the following methods to ViewController.swift file:
func addingButton() {
    let sendButton = UIButton()
    view.addSubview(sendButton)
    sendButton.translatesAutoresizingMaskIntoConstraints = false
    sendButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    sendButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
    sendButton.widthAnchor.constraint(equalToConstant: 200).isActive = true
    sendButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
    sendButton.setTitle("Send Notification", for: .normal)
    sendButton.setTitleColor(UIColor.white, for: .normal)
    sendButton.backgroundColor = UIColor.blue
    
    sendButton.addTarget(self, action: #selector(buttonTapped(sender:)), for: .touchUpInside)
}

@objc func buttonTapped(sender: UIButton) {

}

Call addingButton() inside viewDidLoad() method.

Now Run, we will see Button at center of View looks as :

Notifications Button

RequestAuthorization :

Now , let's dive into notification setup, delivery..

Firstly, we need to configure the app. That means we need to ask the user authentication whether device needs to get notification or not.

To request authorization, call the requestAuthorizationWithOptions:completionHandler: method of the shared UNUserNotificationCenter object.

Replace viewDidLoad() with following method :
override func viewDidLoad() {
    super.viewDidLoad()
    addingButton()
    let center = UNUserNotificationCenter.current()
    center.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
        if (granted) {
            print("granted")
        }else {
            print(error?.localizedDescription as Any)
        }
    }
}

Build and Run, we will see alert with notification request permissions. Tap 'Allow' for testing, if not then we don't receive any notification.

RequestAuthorization Notifications

Send Notification with Content :

Secondly, we need to send notification, so we are creating UNMutableNotificationContent object for setting up content. Add the following code inside buttonTapped() method :
let content = UNMutableNotificationContent()
content.title = NSString.localizedUserNotificationString(forKey: "Good morning!", arguments: nil)
content.body = NSString.localizedUserNotificationString(forKey: "Wake up! It's morning time!",
                                                        arguments: nil)
content.sound = UNNotificationSound.default()

So we created UNMutableNotificationContent with title,body and sound. There are more but for us it will be enough.

Next step is trigger, when to trigger there are several trigger methods but we are using UNTimeIntervalNotificationTrigger. Add following line at the end of buttonTapped() method :
let trigger = UNTimeIntervalNotificationTrigger(timeInterval:TimeInterval(10)  , repeats: false)

Here we are giving time interval as 10 sec, that means after tapping button then in next 10 seconds we will get notification.

Then we need request object. Add following line at the end of buttonTapped() method :
let request = UNNotificationRequest(identifier: "MorningAlarm", content: content, trigger: trigger)

Finally, we need to schedule the request using UNUserNotificationCenter object. Add following code at the end of buttonTapped() method :
let center = UNUserNotificationCenter.current()
center.add(request) { (error : Error?) in
    if let theError = error {
        print(theError.localizedDescription)
    }
}

Build and run, Then tap on notification button and lock the device. After 10 sec we will get Local Notification.

Notification center with LOCAL NOTIFICATION

UNUserNotificationCenterDelegate :

Great we are getting notification, but how to handle after receiving. Good for that we have delegates in place.

so add the following line of code to the end of viewDidLoad() method :
center.delegate = self

There are two delegates methods for handling notifications.

Foreground :

First one userNotificationCenter:willPresentNotification:withCompletionHandler: is for handling when app is running in foreground.

Add the following delegate method :
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            willPresent notification: UNNotification,
                            withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
    print(notification.request.content.title)
    
    // Play a sound.
    completionHandler(UNNotificationPresentationOptions.sound)
}

The completionHandler receives input as UNNotificationPresentationOptions. we used sound option, so when received notification in foreground we get notified with sound.

Background :

Second one userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: is for handling when user taps on notification while app is running in background.

Add the following delegate method :
func userNotificationCenter(_ center: UNUserNotificationCenter,
                            didReceive response: UNNotificationResponse,
                            withCompletionHandler completionHandler: @escaping () -> Void) {
    print(response.notification.request.content.title)
    
}

This delegate method will call when user taps on notification.

Inside delegate methods we need to handle our data based on app functionality.

Build and Run the app, Then tap on button then check both cases in Background and Foreground. we will see logs in console.


In next article, we will go through Custom actions on Notifications.

Download sample project with examples :

Read More

29 Aug 2017

Add UIDatePicker as Input View to UITextField Swift - iOS

8/29/2017 10:16:00 am 0
In this article we are going to add UIDatePicker as Keyboard to UITextField and also adding UIToolBar above UIDatePicker.

This Article Covers All Related questions  :

UITextField UIDatePicker inputview Example.
uidatepicker inputview uitextfield.
uidatepicker and inputview swift.
uidatepicker inputview example.
UITextField input with a UIDatePicker.
UIDatePicker pop up after UITextField is Tapped.
Display date picker on UITextField touch.


Read Getting Started with UIDatePicker Tutorial.

Final Output from this article will looks like as follow:

Add UIDatePicker as Input View to UITextField Swift

In this whole project we are not going to use Storyboards. We are adding all views programmatically using autoLayouts.

Add UITextField :

First we are going to add UITextField to the view in ViewController. So declare textField variable before viewDidLoad() as:
var textField = UITextField()

Then add textField to the view by adding following method :
func addTextField() {
    view.addSubview(textField)
    textField.translatesAutoresizingMaskIntoConstraints = false
    textField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 40.0).isActive = true
    textField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -40.0).isActive = true
    textField.topAnchor.constraint(equalTo: view.topAnchor, constant: 40.0).isActive = true
    textField.placeholder = "Select date"
    textField.borderStyle = .roundedRect
}

Call addTextField() method inside viewDidLoad() method.

Build and run, we see an textField with an placeholder as 'Select date'.

Add Textfiled Programitically
On tapping textField keyboard will appear from bottom, that's ok. But our target is to get UIDatePicker instead of Keyboard.

No worries, it's easy to achieve.

Add UIDatePicker As Keyboard :

First we need to create UIDatePicker, so declare datePicker object after textField declaration as follow:
var textField = UITextField()
var datePicker = UIDatePicker()

Now initialize and add target to datePicker as follow:
func createDatePicker() {
    datePicker.datePickerMode = .date
    datePicker.addTarget(self, action: #selector(self.datePickerValueChanged(datePicker:)), for: .valueChanged)
}

We set datePickerMode to date only, because we need date only. Then add response method datePickerValueChanged(datePicker:) as follow:
@objc func datePickerValueChanged(datePicker: UIDatePicker) {
    
}

Above method will call every time user scrolls UIDatePicker.

Call createDatePicker() method before addTextField() line inside viewDidLoad() method.

So we created datePicker, but not linked to textField. For that we need to set textField inputView as datePicker. So add the following line at the end of addTextField() method :
textField.inputView = datePicker

Build and run, we see textField, then tap on texfield. Great UIDatePicker is showing up as follow:

TextField With DatePicker

So every time user changes date we should update in textField text. So we need to add following code inside datePickerValueChanged() method :
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .none

textField.text = dateFormatter.string(from: datePicker.date)

What we have done here is that, we created dateFormatter with dateStyle as medium and timeStyle as none, because we don't need time.

And finally we are getting Date from datePicker.date, so we are converting Date to string and displaying in textField.

Run the project, we see same as before then select your date it will update in textFiled also.

TextField With DatePicker

Add UIToolBar To UIDatePicker :

Now for adding toolBar over UIDatePicker, we need to first create UIToolBar. so declare toolBar object after datePicker declaration as follow:
var textField = UITextField()
var datePicker = UIDatePicker()
var toolBar = UIToolbar()

Next initialize UIToolBar and add following UIBarButtonItem to toolBar as follow:
func createToolBar() {
    toolBar = UIToolbar(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 40))
    
    let todayButton = UIBarButtonItem(title: "Today", style: .plain, target: self, action: #selector(todayButtonPressed(sender:)))
    
    let doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonPressed(sender:)))
    
    let label = UILabel(frame: CGRect(x: 0, y: 0, width: view.frame.width/3, height: 40))
    label.text = "Choose your Date"
    let labelButton = UIBarButtonItem(customView:label)
    
    let flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: self, action: nil)
    
    toolBar.setItems([todayButton,flexibleSpace,labelButton,flexibleSpace,doneButton], animated: true)
}

What we have done here is that, created four UIBarButtonItem.

todayButton:

Shortcut for selecting today's date. On tapping this button we are calling following method :
@objc func todayButtonPressed(sender: UIBarButtonItem) {
    let dateFormatter = DateFormatter() // 1
    dateFormatter.dateStyle = .medium
    dateFormatter.timeStyle = .none
    
    textField.text = dateFormatter.string(from: Date()) // 2
    
    textField.resignFirstResponder()
}

1. Here again added required dateFormatter, but here we want today's date so simply use Date() property to get current date.

2. Then we are converting to string by using dateFormatter.

3. Dismissing the keyboard(here date picker) using resignFirstResponder() method.

doneButton :

After selecting our date we should dismiss datePicker, this button is for that. On tapping this button we are calling following method :
@objc func doneButtonPressed(sender: UIBarButtonItem) {
    textField.resignFirstResponder()
}

labelButton :

LabelButton is like a placeholder text, we can't add UILabel to UIToolbar so we created custom UIBarButtonItem for adding label.

We can customize that label what ever we like.

flexibleSpace :

FlexibleSpace is for giving equal spaces between items in UIToolBar. FlexibleSpace is also of type UIBarButtonItem.flexibleSpace.

We added all four buttons to toolBar as required order.

Call createToolBar() method before addTextField() line inside viewDidLoad() method.

Good, created toolbar but How to add over datePicker?

Its easy, we are going to set textField inputAccessoryView as toolBar, add following code at the end of addTextField() method:
textField.inputAccessoryView = toolBar

Now Build and run, tap on textfield.

Great we can see UIDatePicker with toolBar on it.

UITextField UIDatePicker inputview Example.

Download sample project with examples :

Read More

Post Top Ad