Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
424 changes: 424 additions & 0 deletions StudentPairs/StudentPairs.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
//
// StudentController.swift
// StudentPairs
//
// Created by Aaron Prestidge on 5/29/20.
// Copyright © 2020 AaronPrestidge. All rights reserved.
//

import CoreData
import Foundation

class StudentController {

//MARK: - Shared Instance
static let shared = StudentController()

//MARK: - Properties
var students: [Student] {
let request: NSFetchRequest<Student> = Student.fetchRequest()
let result = try? CoreDataStack.context.fetch(request)
print("Students array set")
return result ?? []
}

var pairs: [[Student]] = []

//MARK: - Helper Methods
func shuffle() {
var tempStudents: [Student] = []
var tempPairs: [[Student]] = []
for student in students.shuffled() {
if tempStudents.count < 2 {
tempStudents.append(student)
print("Student added to temporary array of students")
} else if tempStudents.count == 2 {
tempPairs.append(tempStudents)
print("Student pair added to temporary array of pairs")
tempStudents = []
print("Temp student array emptied")
tempStudents.append(student)
print("Student added to temp students array")
}
}
if tempStudents.count > 0 {
tempPairs.append(tempStudents)
print("Student pair added to temporary array of pairs")
}
pairs = tempPairs
print("Pairs property set equal to tempPairs array.")
}

//MARK: - CoreData Persistence
private func saveToPersistentStore() {
let mOC = CoreDataStack.context
do {
try mOC.save()
print("Data saved to CoreData")
} catch {
print("Error saving to CoreData: \(error.localizedDescription)")
}
}

//MARK: - CRUD Functions
func create(from name: String) {
let _ = Student(name: name)
print("New student created")
saveToPersistentStore()
}

func update(with student: Student, and name: String) {
student.name = name
print("Student has been updated")
saveToPersistentStore()
}

func delete(student: Student) {
CoreDataStack.context.delete(student)
print("Student has been deleted")
saveToPersistentStore()
}


}//End Class
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// StudentDetailViewController.swift
// Randomizer
//
// Created by Aaron Prestidge on 5/28/20.
// Copyright © 2020 AaronPrestidge. All rights reserved.
//

import UIKit

class StudentDetailViewController: UIViewController {

//MARK: - Properties
var student: Student? {
didSet {
self.loadViewIfNeeded()
}
}

//MARK: - Outlets
@IBOutlet weak var nameTextField: UITextField!

//MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()

if let student = student {
nameTextField.text = student.name
}
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
nameTextField.becomeFirstResponder()
}

//MARK: - Actions
@IBAction func saveButtonTapped(_ sender: UIButton) {
guard let name = self.nameTextField.text,
let student = self.student else { return }
StudentController.shared.update(with: student, and: name)
navigationController?.popViewController(animated: true)

}

@IBAction func cancelButtonTapped(_ sender: UIBarButtonItem) {
navigationController?.popViewController(animated: true)
}

}//End Class
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
//
// StudentsTableViewController.swift
// StudentPairs
//
// Created by Aaron Prestidge on 5/29/20.
// Copyright © 2020 AaronPrestidge. All rights reserved.
//

import UIKit

class StudentsTableViewController: UITableViewController {

// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
StudentController.shared.shuffle()
tableView.reloadData()
}

// MARK: - Actions
@IBAction func addButtonTapped(_ sender: UIBarButtonItem) {
presentAddStudentAlert()
tableView.reloadData()
print("Add student alert controller presented, table view reloaded")
}

@IBAction func shuffleButtonTapped(_ sender: UIBarButtonItem) {
StudentController.shared.shuffle()
tableView.reloadData()
print("Student pairs shuffled, table view reloaded")
}

// MARK: - Methods
func presentAddStudentAlert() {
let alertController = UIAlertController(title: "Add Student", message: "Add a new student to the list", preferredStyle: .alert)
var newStudentTextField: UITextField?
alertController.addTextField { (alertTextField) in
alertTextField.placeholder = "Enter name..."
newStudentTextField = alertTextField
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
let addAction = UIAlertAction(title: "Add", style: .default) { (_) in
guard let inputText = newStudentTextField?.text else { return }
StudentController.shared.create(from: inputText)
StudentController.shared.shuffle()
self.tableView.reloadData()
}
alertController.addAction(cancelAction)
alertController.addAction(addAction)
present(alertController, animated: true, completion: nil)
}

// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
return StudentController.shared.pairs.count
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Pair \(section + 1)"
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return StudentController.shared.pairs[section].count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "studentCell", for: indexPath)
let pair = StudentController.shared.pairs[indexPath.section]
let student = pair[indexPath.row]
cell.textLabel?.text = student.name
return cell
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
let student = StudentController.shared.pairs[indexPath.section][indexPath.row]
StudentController.shared.pairs[indexPath.section].remove(at: indexPath.row)
StudentController.shared.delete(student: student)
tableView.deleteRows(at: [indexPath], with: .fade)
StudentController.shared.shuffle()
tableView.reloadData()
}
}

// MARK: - Navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "toUpdateVC" {
guard let indexPath = tableView.indexPathForSelectedRow,
let destination = segue.destination as? StudentDetailViewController else { return }
destination.student = StudentController.shared.pairs[indexPath.section][indexPath.row]
}
}

}//End Class

@IBDesignable extension UIButton {
@IBInspectable var borderWidth: CGFloat {
set {
layer.borderWidth = newValue
} get {
return layer.borderWidth
}
}

@IBInspectable var cornerRadius: CGFloat {
set {
layer.cornerRadius = newValue }
get {
return layer.cornerRadius }
}

@IBInspectable var borderColor: UIColor? {
set {
guard let uiColor = newValue else { return }
layer.borderColor = uiColor.cgColor
} get {
guard let color = layer.borderColor else { return nil }
return UIColor(cgColor: color)
}
}
}//End Extension
28 changes: 28 additions & 0 deletions StudentPairs/StudentPairs/Models/CoreDataStack.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
//
// CoreDataStack.swift
// StudentPairs
//
// Created by Aaron Prestidge on 5/29/20.
// Copyright © 2020 AaronPrestidge. All rights reserved.
//

import CoreData
import Foundation

enum CoreDataStack {

static let container: NSPersistentContainer = {

let appName = Bundle.main.object(forInfoDictionaryKey: (kCFBundleNameKey as String)) as! String
let container = NSPersistentContainer(name: appName)
container.loadPersistentStores() { (_, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
}
return container
}()

static var context: NSManagedObjectContext { return container.viewContext }

}//End enum
20 changes: 20 additions & 0 deletions StudentPairs/StudentPairs/Models/Student+Convenience.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// Student+Convenience.swift
// StudentPairs
//
// Created by Aaron Prestidge on 5/29/20.
// Copyright © 2020 AaronPrestidge. All rights reserved.
//

import CoreData
import Foundation

extension Student {

@discardableResult
convenience init(name: String, moc: NSManagedObjectContext = CoreDataStack.context) {
self.init(context: moc)
self.name = name
}

}//End Ext
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>StudentPairs.xcdatamodel</string>
</dict>
</plist>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="16119" systemVersion="19E287" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Student" representedClassName="Student" syncable="YES" codeGenerationType="class">
<attribute name="name" optional="YES" attributeType="String"/>
</entity>
<elements>
<element name="Student" positionX="-54" positionY="-9" width="128" height="58"/>
</elements>
</model>
Loading