Posts

Showing posts from June, 2017

Helpful videos to learn basics

Image
Here are some videos which I think are really useful for those who are starting out: Programming basics: Your first app Note: To drag a line from the button to its code, using control+click. Constraints Using multiple view controllers (when your app has more than one page) Images Table views and table view cells: Core data (database) basics

Uploading to the store

Make sure that you have the following ready: Screenshots: Go to  https://theapplaunchpad.com/ to generate screenshots Your app Your app's name A description of your app Promotional message for your app Tags for your app Support URL.  Icon images - one of them has to be 1024x1024. You can generate them at https://makeappicon.com . Steps Go to https://developer.apple.com/account/ios/identifier/bundle/create Create the app,  App name: Name of your app, like Classroom Manager Pro Bundle ID: com.yourcompanyname.yourappname Go to your applications finder. Look for keychain access. Open it up. Maximise it. Click on certificate assistant,  Type in the following details: Click Request a Certificate From a Certificate Authority… User email: Email address of developer Enter the name of the app. You don’t have to enter the CA email address Check saved to disk and save it to the disk. Go to https://developer.apple.com/account/ios/certificate/ Go to Production.

Simulator

Go to home page: command shift H Delete apps from simulator command shift H control alt and click on an app. Wait for 'x' to appear. Delete the apps. command shift H again In order to change orientation, click on command + left or right arrow.

Navigation bar - bar button

If you are unable to add a bar button after you embed in navigator: Add navigation item from object library to scene Add bar button under navigation item in the left hand side of the screen that shows all objects and scenes To enable navigation: Control click the button on the left hand side and link it to the page it will navigate to. If you receive a warning about misplaced size, go to simulated metrics, change size from inferred to freeform and change it back to inferred again.

Go to another page

let loginVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AddPupilsToClass") as! AddPupilsViewController                 self.navigationController?.pushViewController(loginVC, animated: true)

Getting contacts from address book

info.plist: Privacy - Contacts Usage Description Import ContactsUI inherit from: CNContactPickerDelegate In button click: let cnPicker = CNContactPickerViewController()         cnPicker.delegate = self         self.present(cnPicker, animated: true, completion: nil) Implement function: func contactPicker(_ picker: CNContactPickerViewController, didSelect contact: CNContact) {         let userName:String = contact.givenName                 // user phone number         let userPhoneNumbers:[CNLabeledValue<CNPhoneNumber>] = contact.phoneNumbers         let firstPhoneNumber:CNPhoneNumber = userPhoneNumbers[0].value                 // user phone number string         let primaryPhoneNumberStr:String = firstPhoneNumber.stringValue         print(primaryPhoneNumberStr)     }         func contactPickerDidCancel(_ picker: CNContactPickerViewController) {         print("Cancel Contact Picker")     }

Adding an event to the calendar

Add: Privacy - Calendars Usage Description to plist.info import EventKit Then: func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {     let eventStore = EKEventStore()     eventStore.requestAccess(to: .event, completion: { (granted, error) in         if (granted) && (error == nil) {             let event = EKEvent(eventStore: eventStore)             event.title = title             event.startDate = startDate             event.endDate = endDate             event.notes = description             event.calendar = eventStore.defaultCalendarForNewEvents             do {                 try eventStore.save(event, span: .thisEvent)             } catch let e as NSError {                 completion?(false, e)                 return             }             completion?(true, nil)         } else {             completion?(false, error as NSError?)    

Notifications

Avoid calling your project UserNotifications. Give it another name. Create a button and add an action outlet to it. At the top of the code page, import UserNotifications In ViewDidLoad, add the following code to get authorisation for user notifications: UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound])  { (success, error) in             if error != nil             {                 print("Ok")             }else{                 print("Not ok")             }  } Create the following function: func timedNotifications(inSeconds: TimeInterval, completion: @escaping( _ Success: Bool) ->())     {         let trigger = UNTimeIntervalNotificationTrigger(timeInterval: inSeconds, repeats: false)         //repeats can be set to daily, if needed         let content = UNMutableNotificationContent()         content.title = "Hello"         content.subtitle = "My name is"        

Gestures

Split View

Page control

Page View

Page View Controller

Segmented control

Tab bar

CollectionView controller

Tool bar

Action sheet

ScrollView

PickerView

class inherits: UIPickerViewDelegate, UIPickerViewDataSource create a string array as a class variable in ViewDidLoad:         self.nameOfPickerView.delegate = self         self.nameOfPickerView.dataSource = self implement the following functions func numberOfComponents(in pickerView: UIPickerView) -> Int {         return 1     }       func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {         return theStringArray.count     }       func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {         return theStringArray[row]     }     func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {         //what happens when a row gets selected     } How to select a row based on a criteria: Put this in viewDidAppear, not viewDidLoad var defaultRowIndex = theArray.index(of: theValue)         if defaultRowIndex == nil         {

Datepicker

1. Get Date picker from library, add constraints and outlets. 2. To get the date: myDatePicker.date 3. Using the attribute inspector, you can set the style to date only

Stepper

Progress view

Indicator

Slider

In app purchases

Drawing

Videos

Sketch 3

Textfiles

Monetization

Json

Audio

Send an email

import Foundation import MessageUI import UIKit class emailClass: UIViewController, MFMailComposeViewControllerDelegate {     override func viewDidLoad() {         super.viewDidLoad()         if !MFMailComposeViewController.canSendMail() {             print("Mail services are not available")             return         }               sendEmail()     }     func sendEmail() {             let composeVC = MFMailComposeViewController()         composeVC.mailComposeDelegate = self         // Configure the fields of the interface. //this can be an array. Can also send to cc Recipients and bcc recipients.         composeVC.setToRecipients(["address@example.com"])         composeVC.setSubject("Hello!")         composeVC.setMessageBody("Hello this is my message body!", isHTML: false)         // Present the view controller modally.         self.present(composeVC, animated: true, completion: nil)     } func mailComposeController(

Sending an SMS

import MessageUI class inherits from: MFMessageComposeViewControllerDelegate Implement the following function: func messageComposeController(_ controller: MFMessageComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {        controller.dismiss(animated: true, completion: nil)    } in the method where you need to send the message: if(MFMessageComposeViewController.canSendText())         {             let msgCont = MFMessageComposeViewController()             msgCont.body = theMessage.text             msgCont.recipients = [phoneNumber.text!]             msgCont.messageComposeDelegate = self             self.present(msgCont, animated: true, completion: nil)                   } Sending to multiple recipients  let phoneNumberString = "1234567,89101112"             let recipientsArray = phoneNumberString.components(separatedBy: ",")             msgCont.recipients = recipientsArray

Core Data Master Course

Entity = table attribute = field When coding: import CoreData You can get CodeGen (click on the inspector of the entity) to manual/none. When you do that, the type for each row in the database is NSManagedObject Editor - create NSManagedObject subclass If you edit an attribute, remember to clean the project Accessing the data As a class variable: var managedObjectContext = NSManagedObjectContext() When calling on the datasource, for instancing, in view did load: let appDelegate = UIApplication.shared.delegate as! AppDelegate         managedObjectContext = appDelegate.persistentContainer.viewContext Loading the data into a table var results = [Grocery]()         let request: NSFetchRequest<Grocery> = Grocery.fetchRequest()         do         {             results = try managedObjectContext.fetch(request)             groceries = results             tableView.reloadData()         }catch{fatalError("Error in retrieving grocery item

Send data to another View Controller by clicking on a row in table

Make sure View Controller inherits from UITableViewDelegate When you are creating the segue from the table to the next view controller, select main page instead of the table cell and control click it to the next page. 1. In the View Controller receiving the data, give it a variable to hold the data, like task: var thisTask : Task? in ViewDidLoad, initialise UI elements with data         toUpdateTF.text = thisTask?.nameOfTask         toUpdateSW.isOn = thisTask?.isImportant as! Bool       Make sure the set the delegate to self: theTableView.delegate = self 2. Connect the table and second view controller with a segue and give it a name. 3. Prepare for segue in the first view controller (with the table): override func prepare(for segue: UIStoryboardSegue, sender: Any?) {               if let id = segue.identifier         {             if(id == "updateDataSegue")             {                 let newVC = segue.destination as! UpdateDataViewController        

Using a search bar

1. Let view controller class inherit: UISearchBarDelegate 2. Add a search bar to the storyboard, constrain it and add an outlet to it. 3. In ViewDidLoad: theSearchBar.delegate = self as UISearchBarDelegate         theSearchBar.returnKeyType = UIReturnKeyType.done       4. Class variable: var isSearching = false 5. Implement the following method: func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {         if searchBar.text == nil || searchBar.text == ""         {             isSearching = false             view.endEditing(true) //function to get the data and reload the table             getData()             ViewMyTasks.reloadData()         }         else         {             isSearching = true             getDataWithSearch(searchText: searchText)             ViewMyTasks.reloadData()         }

Alerts (popups)

Simple alert  DispatchQueue.main.async {             let alert = UIAlertController(title: "Hello", message: "This is an alert", preferredStyle: UIAlertControllerStyle.alert)             let cancelAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)                       alert.addAction(cancelAction)             self.present(alert, animated: true)                             } Two buttons    DispatchQueue.main.async {             let alertController = UIAlertController(title: "Simple", message: "Simple alertView demo with Cancel and Ok.", preferredStyle: UIAlertControllerStyle.alert)                       let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel) { (result : UIAlertAction) -> Void in                                                       }                       let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.default) { (r

Database - Core Data

Entities - tables Attributes - fields NSPredicate - used to query compilation, filter data Check - core data when creating app. Click on xcdatamodeled Create new entity Go to the bottom and click +Entities. Double click entity at the top and give it a name. Add attribute at the right hand side. Indicate the type. At the right hand side of the screen, you will find the data model inspector, where you can provide more details for the attribute. Click on the entity itself, on the right hand side, specify the codegen to be 'class definition'. If you are storing an image, the type will be Binary Data. Attributes - store in external data file (avoid huge use of space, can store pdf and other files as well) Editor -> Create NSManagedSubClass (If you change anything in the db, you need to add it manually into the classes) Defining relationships Storing data import CoreData //storing core data: let appDelegate = UIApplication.shared.delegate as! AppDeleg

Using programme to get to previous page

navigationController!.popViewController(animated: true)

Toggle Switch

If using more than one switch, make sure you give each a different number tag. If you need to assign them to a sender function, for instance an event where value changed, assign all to the same function (same name). Delete all the additional events being created and change parameter type to UISwitch: For instance, the following page has 6 switches: @IBAction func warmUpHasChanged( _ sender: UISwitch ) {         print (sender. isOn )         if sender. isOn         {             switch (sender. tag )             {             case 1 : self . warmUpHasTimer = true             case 2 : self . upperBodyHasTimer = true             case 3 : self . coreHasTimer = true             case 4 : self . lowerBodyHasTimer = true             case 5 : self . danceHasTimer = true             default : self . coolDownHasTimer = true                              }         }         else         {             switch (sender. tag )             {    

Global variables

Use structures as global variables struct MyVariables {     static var yourVariable = "someString" } let string = MyVariables.yourVariable println("Global variable:\(string)") //Changing value of it MyVariables.yourVariable = "anotherString"

View Will Appear

It is something like viewdidload but called whenever you need to refresh the screen and update the table. You can override it: override fun viewWillAppear(...) {  myTable.reloadData() }

Using the camera

Go to info.plist and add the following keys: Key       :  Privacy - Camera Usage Description   Value     :  $(PRODUCT_NAME) camera use Key       :  Privacy - Photo Library Usage Description   Value     :  $(PRODUCT_NAME) photo library use 2. At class: class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate 3. Add to button click function to get camera: if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.camera) {             let imagePicker = UIImagePickerController()             imagePicker.delegate = self             imagePicker.sourceType = UIImagePickerControllerSourceType.camera;             imagePicker.allowsEditing = false             present(imagePicker, animated: true, completion: nil)         } 4. Add the following function to post the image to the image view: func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {  

Bar button

Used when you want to add a button to the top bar. You can select a camera image.

Load a URL inside the app

1. Search for, drag and drop WKWebView into the app. 2. Constrain it. 3. Create an outlet. 4. Make sure the outlet is strong and not weak. Go to Info.plist and add a key: NSAppTransportSecurity It will be set to dictionary. Click on the triangle button till it faces downwards and click on the + sign. Select Allows Arbitrary Loads and Allows Arbitrary Loads Web Content Change both boolean values to YES In the source code, import WebKit Add the following code to ViewDidLoad:         let firstURL = URL(string: "http://www.youtube.com")         let requestObj = URLRequest(url: firstURL!)         myWebViewOne.load(requestObj) You must check to make sure the URL entered has the prefix http If you need the URL to stop playing a video: myWebViewOne.reload() If you need it to stop loading: myWebViewOne.stopLoading()

Sharing on social media

Sharing on facebook import Social //create a sharing function for Facebook, in button clicked  if let vc = SLComposeViewController(forServiceType: SLServiceTypeFacebook)         {          shareOnFb(vc: vc)                   } //add function below func shareOnFb(vc: SLComposeViewController)     {         vc.setInitialText("Posted this from my swift app")         vc.add(thisImage)         let theurl = URL(string: "http://swiftcodingreferencebook.blogspot.sg")         vc.add(theurl)         present(vc, animated: true, completion: nil)           } Sharing on Instagram in info.plist Create a key of type array: LSApplicationQueriesSchemes Control+click and add a row Item 0 value: instagram add to class ViewController: UIViewController, UIDocumentInteractionControllerDelegate Add class variable:     var documentController: UIDocumentInteractionController! Add the following code the the button action: DispatchQueue.main.async {    

Special Project: When you tap on a cell, you get to select its image

class ViewController: UIViewController , UITableViewDataSource , UITableViewDelegate , UINavigationControllerDelegate , UIImagePickerControllerDelegate In viewdidload:         myTable.dataSource = self         myTable.delegate = self func tableView( _ tableView: UITableView , didSelectRowAt indexPath: IndexPath ) {         //actions when you click on the row         let img = UIImagePickerController()         img.delegate = self         img.sourceType = UIImagePickerControllerSourceType.photoLibrary         self .present(img, animated: true , completion: nil )         currentIndexPath = indexPath     }          func imagePickerController( _ picker: UIImagePickerController , didFinishPickingMediaWithInfo info: [ String : AnyObject ]) {         if let image = info[UIImagePickerControllerOriginalImage] as ? UIImage {             let cell = myTable.cellForRow(at: currentIndexPath) as ! MyTableCellTableViewCell             cell.MyImageVi

Photo library

In the info.plist, add: Privacy - Photo Library Usage Description (You must search using the capital 'P') Get the image picker library Go to build phases Link binary with libraries, click + Grab photos.framework for IOS 10 Go view controller.swift Import Photos In the class: class ViewController: UIViewController, UINavigationControllerDelegate, UIImagePickerControllerDelegate Add the following functions:    @IBAction func getImages(_ sender: Any) {         let img = UIImagePickerController()         img.delegate = self         img.sourceType = UIImagePickerControllerSourceType.photoLibrary         self.present(img, animated: true, completion: nil)             }     func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {         if let image = info[UIImagePickerControllerOriginalImage] as? UIImage {         myImageView.image = image         } else{             print("Something went

Add another view controller

Add the view controller: 1. Go to the object library. 2. Search for view controller. 3. Drop it into an empty space in the storyboard. 4. Create a new ViewController file: cocoa touch class, subclass of UIViewController. 5. Assign this new view controller file as the class of the view controller created in the storyboard. Have it pop up when you click the table view cell: 1. In the left hand side of the screen, click and drag a line from the table view cell to the new view controller. 2. Choose 'show' if you want the view to be stacked on top of it. 3. You can also choose modal. How to send data from one view controller to another: 1. Click on the line joining the two view controllers. It is a storyboard segue. 2. Give it an identifier at the attribute inspector, for instance: nameOfTheSegue 3. Inside the first view controller class, override the following function and type: //overriden function - type prepare override func prepare(for segue: UIStoryboardSegue

Table view

Add a table: 1. Search for table view and add it to the screen. (Constrain it). 2. Add a table cell from the object library into the table. Drop it into the top of the table view. A cell is the prototype of the table. Give the table cell a name at its identifier in the attributes inspector. (Double click it such that you get table view cell and not prototype cell). 3. Outlet table view into the view controller. Populate the table view. 1. Let's say you named your table view cell tableViewCell as its identifier. Set the following as as property in the view controller. let reuseIdentifier = "tableViewCell" 2. Create an array of strings. 3. at the view controller class: class ViewController: UIViewController, UITableViewDataSource 4. Implement the following methods:  //type cellforrowat       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {         let cell: UITableViewCell = tableView.dequeueReusableCell(w

Navigation controller

It creates a navigation bar for all the pages in the storyboard. It has a back button, a title and a few other custom buttons that you can add. You can customise its colour as well. Add a navigation controller 1. Add it from the object library. 2. Drag it to a place outside the main storyboard. Make it the first page. 1. Select the navigation controller page 2. Drag it to the left of the first scene. 3. Go to attributes inspector, scroll and hide others until you see 'Is initial view controller' and check against it. 4. Control, click and drag from navigation controller to first scene and choose 'root view controller'. 5. To set the title, click on the view controller scene and select its title bar (the one with the battery). At where the attributes inspector is, key in the title of the app. 6. To make it such that all views have the same colour in the title bar, click on 'navigation bar' under 'navigation controller' on the left hand side of

Create your splash screen

1. Go to project navigator. 2. Click on launchscreen.storyboard. 3. This is where you key in the splash screen. 4. You can give it a background colour and an image view. 5. Assign an image to the image view and add a label to it. Notes You can't have navigation, animations or buttons. You can make use of view controllers to customise images for different devices.

Design elements like colour

Select colour based on RGB value: 1. After choosing 'other', choose colour sliders. 2. From the drop down box, select RGB

User design

UI tools  Sketch antetype photoshop axure - enterprise balsamiq invision - foc Note Plan using pen and paper first include a splash screen main screen status bar app title Clicking The user interface design comes after user experience design. covers color and design, the look and feel User experience - UX, deals with the flow, how it works and user feelings. Determine colour scheme Get colour schemes Colours invoke emotion Using paid tools for design ui sketch can be both a ux or ui tool foc - inkscape Design user interface Theming the entire app around one colour imply use with a picture Words used - linked to problem it is solving

Save data in phone

Saving data permanently in the phone: It will be stored in the root directory under info.plist. To access object, check if it is empty first. If it is give it a value: if UserDefaults.standard.string(forKey: "NameOfTheItem") == nil {  UserDefaults.standard.set("firstValue", forKey: "NameOfTheItem") }

Creating a class inside the app

Add a file (.swift). Type: class ClassName {   var property1: String  init(prop1: String)  {   self.property1 = prop1 } } When referring to properties, use self.propertyName

Location services

Show a map with apple maps Go to the object library and filter - look for 'Map Kit View'. Add constraints to it Go the the project navigator (left hand side of screen), click on the project name (topmost). Click on build phases Click on link binary with libraries. Click on the + sign. Search for map. Add Mapkit.framework Edit the attributes Go to the main.storyboard. Look for the map view. Look at attributes inspector.  Edit accordingly. Setting Required Device capabilities using Info.plist (see if it has GPS, don't want people to download the app if their device doesn't have it, else they will leave a bad review. Go to the project navigator. Look for the info.plist and click on it. Click on required device capabilities Click on the + sign In the blank space, key in gps Click on the + sign again, key in location-services Set permissions for location in info.plist Go back to info.plist. Click on the + sign next to Information Proper