ViewController.swift
//
// ViewController.swift
// UNISA_SWAMahasiswa
//
// Created by pdsi on 11/15/18.
// Copyright © 2018 pdsi. All rights reserved.
//import UIKit
/*
variabel global, variabel yang dapat diakses dari kelas/objek lain
format variabel:
var namavariabel
atau
var namavariabel: tipedata = dataawal
*///direktori di mana berkas setting disimpan
var filenameURL: URL = URL.init(fileURLWithPath: “”)
//apakah berkas setting sudah terverifikasi?
var terverifikasi: Bool = false
//string username, password dan nim
var usernamepasswordnim: String = “”class ViewController: UIViewController {
//connections
@IBOutlet weak var ButtonPresensiTextSc1: UIButton!
@IBOutlet weak var LabelPesanSc1: UILabel!
@IBOutlet weak var TextBoxQRCodeSc1: UITextField!
@IBOutlet weak var ButtonKirimTextSc1: UIButton!
@IBOutlet weak var LabelNIMSc1: UILabel!/*
variabel lokal kelas/objek
*///jenis aksi yang dilakukan
var idtombol: Int = 0
//apakah user valid?
var cekuser: Bool = false/*
fungsi/prosedur
*/override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}//dieksekusi pertama kali ketika view muncul
override func viewDidAppear(_ animated: Bool) {
LabelPesanSc1.text = “Silakan tekan tombol untuk melakukan aksi.”
usernamepasswordnim = “”
PROCSetFilepath()
}//menentukan lokasi penyimpanan berkas setting
func PROCSetFilepath() {
/*
let : konstan. Fahami kalimat berikut: Let it be, artinya biarkan saja, sehingga dapat berarti konstan, tidak berubah
! :
*/
let dir = try! FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
filenameURL = dir.appendingPathComponent(“upMahasiswaUnisaIOS”).appendingPathExtension(“txt”)
}//user klik tombol Presensi. Meskipun segue sudah diatur pada tombol ini, tetapi segue tidak langsung dijalankan secara otomatis
@IBAction func ButtonPresensiTextSc1_Click(_ sender: Any) {
if ButtonPresensiTextSc1.isEnabled {
LabelPesanSc1.text = “Proses verifikasi…”
PROCVerifikasi(idt: 2)
}
}//performsegue dilakukan manual, override ke false
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return false
}//menentukan aksi jika terverifikasi atau tidak
func PROCVerifikasi(idt: Int) {
idtombol = idt
if (terverifikasi && !(usernamepasswordnim.isEmpty)) {
PROCCekUserViaWeb()
}
else {
FileSettingReadFrom()
}
}//membaca berkas setting dan menentukan langkah selanjutnya dengan memeriksa data di dalam berkas apakah sudah sesuai dengan format yang telah ditentukan
func FileSettingReadFrom() {
var value_ = “”
//baca berkas
do {
value_ = try String(contentsOf: filenameURL, encoding: .utf8)
}
catch { //jika terjadi masalah dalam membaca berkas, misalnya: berkas tidak ada
PROCScreenSetting()
}
//hasil pembacaan dari berkas disimpan ke dalam variabel
usernamepasswordnim = value_.trimmingCharacters(in: .whitespacesAndNewlines)
//apakah format data valid? Terdapat karakter ‘_’
if usernamepasswordnim.contains(“_”) {
PROCCekUserViaWeb()
}
else {
PROCScreenSetting()
}
}//cek apakah user terdaftar di UNISAYOGYA?
func PROCCekUserViaWeb(){
LabelNIMSc1.text = “NIM: ” + usernamepasswordnim.split(separator: “_”)[1]
//siapkan alamat pengecekan dan parameternya
let WebAPICekUser_url = “https://service.unisayogya.ac.id/cumahasiswa.php?u=” + usernamepasswordnim
WebCekUserGet(urlString: WebAPICekUser_url)
}//kirim permintaan dan mendapatkan hasil cek user
func WebCekUserGet(urlString: String) {
/*
guard: menjaga nilai agar tetap valid, bukan nil
*/
guard let url = URL(string: urlString) else { return }//background process, thread berbeda dari thread utama
URLSession.shared.dataTask(with: url) { (data, response, error) in
//hasil cek
var data_ = “”
//jika permintaan tidak error
if error == nil {
guard let data = data else { return }
/*
??: opsional, pilihan, menjaga nilai agar tetap valid, bukan nil
*/
data_ = (String (data: data, encoding: .utf8) ?? “”)
//apakah hasil cek sama dengan isi berkas setting?
self.cekuser = data_.contains(usernamepasswordnim)
//print (“usernamepasswordnim: \(usernamepasswordnim), cekuser: \(self.cekuser), terverifikasi: \(terverifikasi)”)
}
else { //jika permintaan error
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanSc1.text = “Maaf, terjadi kesalahan koneksi. Silakan hubungi UNISA.”
}
self.cekuser = false
}
if self.cekuser {
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanSc1.text = “Silakan melakukan presensi.”
terverifikasi = true
if self.idtombol == 1 {
self.LabelPesanSc1.text = usernamepasswordnim + data_
}
else if self.idtombol == 2 {
self.DivTombolPresensi(disablePresensiText: true)
self.DivPresensiTextSet(disablePresensiText: false)
}
}
}
else {
self.PROCScreenSetting()
}
}.resume()
}//setting enable tombol presensi
func DivTombolPresensi(disablePresensiText: Bool) {
ButtonPresensiTextSc1.isEnabled = !disablePresensiText
}//setting enable presensi text
func DivPresensiTextSet(disablePresensiText: Bool) {
ButtonKirimTextSc1.isEnabled = !disablePresensiText
if !disablePresensiText {
TextBoxQRCodeSc1.text = “”
}
}//membuka jendela setting
func PROCScreenSetting(){
LabelNIMSc1.text = “”
LabelPesanSc1.text = “”
//secara manual membuka jendela setting
performSegue(withIdentifier: “bukaSetting”, sender: self)
}@IBAction func ButtonKirimTextSc1_Click(_ sender: Any) {
//deklarasi konstan, jika tidak nil maka lanjutkan proses
if let kode = TextBoxQRCodeSc1.text {
//siapkan alamat presensi mahasiswa dan parameternya
let WebAPIPresensi_url = “https://service.unisayogya.ac.id/pmahasiswa.php?u=” + usernamepasswordnim + “&k=” + kode + “&j=1”
//print (“Presensi: \(WebAPIPresensi_url)”)
DivTombolPresensi(disablePresensiText: false)
DivPresensiTextSet(disablePresensiText: true)
WebPresensiGet(urlString: WebAPIPresensi_url)
}
}//kirim permintaan dan mendapatkan hasil presensi mahasiswa
func WebPresensiGet(urlString: String) {
guard let url = URL(string: urlString) else { return }//background process
URLSession.shared.dataTask(with: url) { (data, response, error) in
//hasil presensi
var data_ = “”
//jika permintaan tidak error
if error == nil {
guard let data = data else { return }
data_ = (String (data: data, encoding: .utf8) ?? “”)
//ekseskusi UI (main thread) dari background process
DispatchQueue.main.async {
self.PROCRespon(stringrespon: data_)
}
}
else {
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanSc1.text = “Maaf, terjadi kesalahan koneksi. Silakan hubungi UNISA.”
}
self.cekuser = false
}
}.resume()
}//menampilkan pesan sesuai dengan hasil presensi mahasiswa
func PROCRespon(stringrespon: String) {
if (stringrespon == “FAILED”) {
LabelPesanSc1.text = “Maaf, Presensi gagal dilakukan”
}
else if (stringrespon == “NOCHANGED”) {
LabelPesanSc1.text = “Presensi hanya dapat dilakukan 1 kali saja.”
}
else if (stringrespon == “SUCCEED”) {
LabelPesanSc1.text = “Presensi BERHASIL dilakukan”
DivTombolPresensi(disablePresensiText: true)
}
else {
LabelPesanSc1.text = stringrespon
DivTombolPresensi(disablePresensiText: true)
}
}
}
ScreenSettingViewController.swift
//
// ScreenSettingViewController.swift
// UNISA_SWAMahasiswa
//
// Created by pdsi on 11/17/18.
// Copyright © 2018 pdsi. All rights reserved.
//import UIKit
/*
Secara garis besar, penjelasan sama dengan ViewController.
Namun, di sini ada penjelasan tentang cara menulis berkas
*/class ScreenSettingViewController: UIViewController {
@IBOutlet weak var LabelPesanScset: UILabel!
@IBOutlet weak var TextBoxNimScset: UITextField!
@IBOutlet weak var TextBoxUsernameScset: UITextField!
@IBOutlet weak var TextBoxPasswordScset: UITextField!
@IBOutlet weak var ButtonSimpanScset: UIButton!
@IBOutlet weak var ButtonPresensiScset: UIButton!var cekuser: Bool = false
override func viewDidLoad() {
super.viewDidLoad()// Do any additional setup after loading the view.
}@IBAction func ButtonSimpanScset_Click(_ sender: Any) {
if ButtonSimpanScset.isEnabled {
if TextBoxNimScset.text?.isEmpty ?? false {
LabelPesanScset.text = “Maaf, NIM belum diisi”
}
else if TextBoxUsernameScset.text?.isEmpty ?? false {
LabelPesanScset.text = “Maaf, Username belum diisi”
}
else if TextBoxPasswordScset.text?.isEmpty ?? false {
LabelPesanScset.text = “Maaf, Password belum diisi”
}
else {
LabelPesanScset.text = “Proses verifikasi…”
if let strUser = self.TextBoxUsernameScset.text, let strPass = self.TextBoxPasswordScset.text, let strNIM = self.TextBoxNimScset.text {
let WebAPICekUser_url = “https://service.unisayogya.ac.id/cumahasiswa.php?u=” + strUser + strPass + “_” + strNIM
WebCekUserGet(urlString: WebAPICekUser_url)
}
}
}
}func WebCekUserGet(urlString: String) {
//teks yang akan ditulis ke berkas
var text = “”
if let strUser = self.TextBoxUsernameScset.text, let strPass = self.TextBoxPasswordScset.text, let strNIM = self.TextBoxNimScset.text {
text = strUser + strPass + “_” + strNIM
}
guard let url = URL(string: urlString) else { return }//background process
URLSession.shared.dataTask(with: url) { (data, response, error) in
var data_ = “”
if error == nil {
guard let data = data else { return }
data_ = (String (data: data, encoding: .utf8) ?? “”)
self.cekuser = data_.contains(text)
text = data_
}
else {
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanScset.text = “Maaf, terjadi kesalahan koneksi. Silakan hubungi UNISA.”
}
self.cekuser = false
}
if self.cekuser {
do {
//menulis teks ke berkas
try text.write(to: filenameURL, atomically: false, encoding: .utf8)
usernamepasswordnim = text
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanScset.text = “Username dan Password berhasil disimpan. Klik tombol Presensi untuk melakukan presensi atau muat ulang aplikasi.”
self.DivTombolPresensi(disablePresensiText: false)
}
terverifikasi = true
}
catch {
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanScset.text = “Maaf, proses penyimpanan gagal. Harap menghubungi UNISA.”
}
}
}
else {
//eksekusi UI (main thread) dari background process
DispatchQueue.main.async {
self.LabelPesanScset.text = “Maaf, Mahasiswa dengan NIM, Username dan Password tersebut belum terdaftar”
}
}
}.resume()
}func DivTombolPresensi(disablePresensiText: Bool) {
ButtonSimpanScset.isEnabled = disablePresensiText
ButtonPresensiScset.isEnabled = !disablePresensiText
}@IBAction func ButtonPresensiScset_Click(_ sender: Any) {
if ButtonPresensiScset.isEnabled {
performSegue(withIdentifier: “bukaPresensi”, sender: self)
}
}//performsegue dilakukan manual, override ke false
override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {
return false
}/*
// MARK: – Navigation// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/}
Setting Info.plist
Sebuah berkas yang berisi informasi konfigurasi penting untuk aplikasi, misalnya untuk aplikasi kali ini berhubung ada proses baca dan tulis berkas, maka diperlukan Supports opening documents in places dengan nilai Yes.
Lihat juga: Belajar Swift