diff --git a/ELG.xcodeproj/project.pbxproj b/ELG.xcodeproj/project.pbxproj index 659a6d2..89d9f77 100644 --- a/ELG.xcodeproj/project.pbxproj +++ b/ELG.xcodeproj/project.pbxproj @@ -671,7 +671,7 @@ CODE_SIGN_ENTITLEMENTS = OmissionsWidget/OmissionsWidget.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = TRLMQKJQ97; ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = OmissionsWidget/Info.plist; @@ -681,7 +681,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 3.0.5; + MARKETING_VERSION = 3.0.6; PRODUCT_BUNDLE_IDENTIFIER = com.hardykrause.ELG.Widget; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -700,7 +700,7 @@ CODE_SIGN_ENTITLEMENTS = OmissionsWidget/OmissionsWidget.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = TRLMQKJQ97; ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = OmissionsWidget/Info.plist; @@ -710,7 +710,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 3.0.5; + MARKETING_VERSION = 3.0.6; PRODUCT_BUNDLE_IDENTIFIER = com.hardykrause.ELG.Widget; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -844,7 +844,7 @@ CODE_SIGN_ENTITLEMENTS = ELG/ELG.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = TRLMQKJQ97; ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = ELG/Info.plist; @@ -853,7 +853,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.0.5; + MARKETING_VERSION = 3.0.6; PRODUCT_BUNDLE_IDENTIFIER = com.hardykrause.ELG; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; @@ -874,7 +874,7 @@ CODE_SIGN_ENTITLEMENTS = ELG/ELG.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 2; + CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_TEAM = TRLMQKJQ97; ENABLE_HARDENED_RUNTIME = NO; INFOPLIST_FILE = ELG/Info.plist; @@ -883,7 +883,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.0.5; + MARKETING_VERSION = 3.0.6; PRODUCT_BUNDLE_IDENTIFIER = com.hardykrause.ELG; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; diff --git a/ELG/OmissionsViewController.swift b/ELG/OmissionsViewController.swift index 701a20e..87c184c 100644 --- a/ELG/OmissionsViewController.swift +++ b/ELG/OmissionsViewController.swift @@ -10,47 +10,47 @@ import UIKit import ColorCompatibility class OmissionsViewController: UITableViewController { - // MARK: - Properties - - @IBOutlet weak fileprivate var saveButton: UIBarButtonItem! - - var defaults: UserDefaults! - var selectedGrade = Int() - var rows = NSMutableArray() - var userPlan = NSMutableArray() - var offlineAvailable = Bool() - var autoSave = Bool() - var teacherMode = Bool() - var teacherToken = String() - let grades = ["Keine Klasse", "5a", "5b", "5c", "5d", "5e", "6a", "6b", "6c", "6d", "6e", "7a", "7b", "7c", "7d", "7e", "8a", "8b", "8c", "8d", "8e", "9a", "9b", "9c", "9d", "9e", "10a", "10b", "10c", "10d", "10e", "11a", "11b", "11c", "11d", "11e", "12a", "12b", "12c", "12d", "12e"] - - @IBAction func saveButtonTap(_ sender: UIBarButtonItem) { - saveOmissions() - } + // MARK: - Properties + + @IBOutlet weak fileprivate var saveButton: UIBarButtonItem! + + var defaults: UserDefaults! + var selectedGrade = Int() + var rows = [String]() + var userPlan = [String]() + var offlineAvailable = Bool() + var autoSave = Bool() + var teacherMode = Bool() + var teacherToken = String() + let grades = ["Keine Klasse", "5a", "5b", "5c", "5d", "5e", "6a", "6b", "6c", "6d", "6e", "7a", "7b", "7c", "7d", "7e", "8a", "8b", "8c", "8d", "8e", "9a", "9b", "9c", "9d", "9e", "10a", "10b", "10c", "10d", "10e", "11a", "11b", "11c", "11d", "11e", "12a", "12b", "12c", "12d", "12e"] + + @IBAction func saveButtonTap(_ sender: UIBarButtonItem) { + saveOmissions() + } // MARK: - UITableViewController - - override func viewDidLoad() { - super.viewDidLoad() - + + override func viewDidLoad() { + super.viewDidLoad() + defaults = UserDefaults.init(suiteName: "group.com.johjakob.elg") - - tableView.register(UINib(nibName: "OmissionsTableViewCell", bundle: nil), forCellReuseIdentifier: "OmissionsTableViewCell") - - let planRefreshControl = UIRefreshControl.init() - - planRefreshControl.addTarget(self, action: #selector(OmissionsViewController.refreshTableView), for: .valueChanged) - - refreshControl = planRefreshControl - - getUserDefaults() + + tableView.register(UINib(nibName: "OmissionsTableViewCell", bundle: nil), forCellReuseIdentifier: "OmissionsTableViewCell") + + let planRefreshControl = UIRefreshControl.init() + + planRefreshControl.addTarget(self, action: #selector(OmissionsViewController.refreshTableView), for: .valueChanged) + + refreshControl = planRefreshControl + + getUserDefaults() if offlineAvailable { getOfflinePlan() } else { downloadPlan() } - } + } override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() @@ -58,20 +58,20 @@ class OmissionsViewController: UITableViewController { print("Memory Warning") } - // MARK: - UITableView - - override func numberOfSections(in tableView: UITableView) -> Int { - var numberOfSections: Int - - let reachabilityStatus: NetworkStatus = Reachability.forInternetConnection().currentReachabilityStatus() - - if reachabilityStatus != NotReachable || (reachabilityStatus == NotReachable && offlineAvailable) { - numberOfSections = 2 + // MARK: - UITableView + + override func numberOfSections(in tableView: UITableView) -> Int { + var numberOfSections: Int + + let reachabilityStatus: NetworkStatus = Reachability.forInternetConnection().currentReachabilityStatus() + + if reachabilityStatus != NotReachable || (reachabilityStatus == NotReachable && offlineAvailable) { + numberOfSections = 2 // Remove background view tableView.backgroundView = nil - } else { - numberOfSections = 0 + } else { + numberOfSections = 0 let noConnectionView = NoConnectionView() @@ -80,270 +80,268 @@ class OmissionsViewController: UITableViewController { tableView.backgroundColor = UIColor.groupTableViewBackground tableView.separatorStyle = .none tableView.backgroundView = noConnectionView - } - - return numberOfSections - } - - override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - var numberOfRows: Int - - if section == 0 { - numberOfRows = userPlan.count - } else { - if rows.count < 3 { - numberOfRows = 0 - } else { - numberOfRows = rows.count - 2 - } - } - - return numberOfRows - } - - override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCell(withIdentifier: "OmissionsTableViewCell", for: indexPath) as! OmissionsTableViewCell - + } + + return numberOfSections + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + var numberOfRows: Int + + if section == 0 { + numberOfRows = userPlan.count + } else { + if rows.count < 3 { + numberOfRows = 0 + } else { + numberOfRows = rows.count - 2 + } + } + + return numberOfRows + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: "OmissionsTableViewCell", for: indexPath) as! OmissionsTableViewCell + // Use AccentColor on iOS 11+ if #available(iOS 11, *) { cell.gradeLabel.textColor = UIColor(named: "AccentColor") } - var planComponents: [String] - - if indexPath.section == 0 { - planComponents = (userPlan[indexPath.row] as AnyObject).components(separatedBy: "\",\"") - } else { - planComponents = (rows[indexPath.row + 1] as AnyObject).components(separatedBy: "\",\"") - } - - let grade = planComponents[0].replacingOccurrences(of: "\"", with: "") - let lesson = planComponents[1] - let teacher = planComponents[2] - let subject = planComponents[3] - let room = planComponents[4] - let text = planComponents[5] - let comment = planComponents[6].replacingOccurrences(of: "\"", with: "") - - if grade.count < 4 { - cell.gradeLabel.text = grade - } else { - if grade.first == "1" { + var planComponents: [String] + + if indexPath.section == 0 { + planComponents = (userPlan[indexPath.row] as AnyObject).components(separatedBy: "\",\"") + } else { + planComponents = (rows[indexPath.row + 1] as AnyObject).components(separatedBy: "\",\"") + } + + let grade = planComponents[0].replacingOccurrences(of: "\"", with: "") + let lesson = planComponents[1] + let teacher = planComponents[2] + let subject = planComponents[3] + let room = planComponents[4] + let text = planComponents[5] + let comment = planComponents[6].replacingOccurrences(of: "\"", with: "") + + if grade.count < 4 { + cell.gradeLabel.text = grade + } else { + if grade.first == "1" { let index = grade.index(grade.startIndex, offsetBy: 2) - cell.gradeLabel.text = String(grade[.. CGFloat { - return 65 - } - - override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - var titleForHeader: String - - if section == 0 { - titleForHeader = "Eigene Vertretungen" - } else { - titleForHeader = "Alle Vertretungen" - } - - return titleForHeader - } - - override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { - let footerLabel = UILabel() + } + + return cell + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return 65 + } + + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + var titleForHeader: String + + if section == 0 { + titleForHeader = "Eigene Vertretungen" + } else { + titleForHeader = "Alle Vertretungen" + } + + return titleForHeader + } + + override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + let footerLabel = UILabel() footerLabel.textColor = ColorCompatibility.secondaryLabel - - footerLabel.font = .boldSystemFont(ofSize: 18) - footerLabel.textAlignment = .center + + footerLabel.font = .boldSystemFont(ofSize: 18) + footerLabel.textAlignment = .center footerLabel.backgroundColor = ColorCompatibility.systemBackground - - if section == 0 { - if userPlan.count == 0 { - footerLabel.text = "Keine eigenen Vertretungen" - } - } else { - if rows.count < 3 { - footerLabel.text = "Keine Vertretungen" - } - } - - return footerLabel - } - - override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { - var heightForFooter: CGFloat = 0 - - if section == 0 { - if userPlan.count == 0 { - heightForFooter = 44 - } else { - heightForFooter = 0 - } - } else { - if rows.count < 3 { - heightForFooter = 44 - } else { - heightForFooter = 0 - } - } - - return heightForFooter - } - - // MARK: - Private - - private func getUserDefaults() { - selectedGrade = defaults.integer(forKey: "grade") - offlineAvailable = defaults.bool(forKey: "offlineAvailable") - autoSave = defaults.bool(forKey: "autoSave") - teacherMode = defaults.bool(forKey: "teacherMode") - teacherToken = defaults.string(forKey: "teacherToken")! - } - - @objc private func refreshTableView() { - getUserDefaults() + + if section == 0 { + if userPlan.count == 0 { + footerLabel.text = "Keine eigenen Vertretungen" + } + } else { + if rows.count < 3 { + footerLabel.text = "Keine Vertretungen" + } + } + + return footerLabel + } + + override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + var heightForFooter: CGFloat = 0 + + if section == 0 { + if userPlan.count == 0 { + heightForFooter = 44 + } else { + heightForFooter = 0 + } + } else { + if rows.count < 3 { + heightForFooter = 44 + } else { + heightForFooter = 0 + } + } + + return heightForFooter + } + + // MARK: - Private + + private func getUserDefaults() { + selectedGrade = defaults.integer(forKey: "grade") + offlineAvailable = defaults.bool(forKey: "offlineAvailable") + autoSave = defaults.bool(forKey: "autoSave") + teacherMode = defaults.bool(forKey: "teacherMode") + teacherToken = defaults.string(forKey: "teacherToken")! + } + + @objc private func refreshTableView() { + getUserDefaults() downloadPlan() - - tableView.reloadData() - - refreshControl?.endRefreshing() - } - - private func getOfflinePlan() { - rows = defaults.mutableArrayValue(forKey: "offlineOmissions") - userPlan = defaults.mutableArrayValue(forKey: "ownOfflineOmissions") - + + tableView.reloadData() + + refreshControl?.endRefreshing() + } + + private func getOfflinePlan() { + rows = defaults.stringArray(forKey: "offlineOmissions") ?? [] + userPlan = defaults.stringArray(forKey: "ownOfflineOmissions") ?? [] + // Set navigation item title - setTitle(with: rows[0] as! String) - - saveButton.isEnabled = false - } - - private func downloadPlan() { - let reachabilityStatus: NetworkStatus = Reachability.forInternetConnection().currentReachabilityStatus() - - if reachabilityStatus != NotReachable { - var rawPlan = String() - - do { - try rawPlan = String(contentsOf: URL.init(string: "https://elg-halle.de/Aktuell/Intern/Vertretungsplan/vp.csv")!, encoding: String.Encoding.ascii) - } catch { - print(error) - } - - let cleanedPlan = rawPlan.replacingOccurrences(of: "\r", with: "") - - rows = NSMutableArray.init(array: cleanedPlan.components(separatedBy: "\n")) - - userPlan = NSMutableArray() - - for i in 1 ..< rows.count - 1 { - if (rows[i] as AnyObject).range(of: "MIPa").location != NSNotFound { - rows.removeObject(at: i) - } - - let planComponents = (rows[i] as AnyObject).components(separatedBy: "\",\"") - let grade = planComponents[0].replacingOccurrences(of: "\"", with: "") - var teacher = String() - - if planComponents.count >= 3 { - teacher = planComponents[2] - } - - if teacherMode { - if teacher == teacherToken && teacher != "" { - userPlan.add(rows[i]) - } - } else { - if selectedGrade != 0 { - if grade.range(of: grades[selectedGrade]) != nil { - userPlan.add(rows[i]) - } - } - } - } + setTitle(with: rows[0]) + + saveButton.isEnabled = false + } + + private func downloadPlan() { + let reachabilityStatus: NetworkStatus = Reachability.forInternetConnection().currentReachabilityStatus() + + if reachabilityStatus != NotReachable { + var rawPlan = String() + + do { + try rawPlan = String(contentsOf: URL.init(string: "https://elg-halle.de/Aktuell/Intern/Vertretungsplan/vp.csv")!, encoding: String.Encoding.ascii) + } catch { + print(error) + } + + let cleanedPlan = rawPlan.replacingOccurrences(of: "\r", with: "") + + rows = cleanedPlan.components(separatedBy: "\n") + + userPlan = [String]() + + rows.removeAll { $0.contains("MIPa") } + + for i in 1 ..< rows.count - 1 { + let planComponents = (rows[i] as AnyObject).components(separatedBy: "\",\"") + let grade = planComponents[0].replacingOccurrences(of: "\"", with: "") + var teacher = String() + + if planComponents.count >= 3 { + teacher = planComponents[2] + } + + if teacherMode { + if teacher == teacherToken && teacher != "" { + userPlan.append(rows[i]) + } + } else { + if selectedGrade != 0 { + if grade.range(of: grades[selectedGrade]) != nil { + userPlan.append(rows[i]) + } + } + } + } // Set navigation item title - setTitle(with: rows[0] as! String) - - tableView.separatorStyle = .singleLine - - offlineAvailable = false - - defaults.set(offlineAvailable, forKey: "offlineAvailable") - defaults.synchronize() - - if rows.count < 3 { - saveButton.isEnabled = false - } else { - saveButton.isEnabled = true - } - - if autoSave { - saveOmissions() - } - } else { - saveButton.isEnabled = false - - tableView.separatorStyle = .none - } - } - - private func saveOmissions() { - let reachabilityStatus: NetworkStatus = Reachability.forInternetConnection().currentReachabilityStatus() - - if reachabilityStatus != NotReachable { - offlineAvailable = true - - defaults.set(rows, forKey: "offlineOmissions") - defaults.set(userPlan, forKey: "ownOfflineOmissions") - defaults.set(offlineAvailable, forKey: "offlineAvailable") - defaults.synchronize() + setTitle(with: rows[0]) + + tableView.separatorStyle = .singleLine + + offlineAvailable = false + + defaults.set(offlineAvailable, forKey: "offlineAvailable") + defaults.synchronize() + + if rows.count < 3 { + saveButton.isEnabled = false + } else { + saveButton.isEnabled = true + } - saveButton.isEnabled = false - } else { - saveButton.isEnabled = false + if autoSave { + saveOmissions() + } + } else { + saveButton.isEnabled = false + + tableView.separatorStyle = .none + } + } + + private func saveOmissions() { + let reachabilityStatus: NetworkStatus = Reachability.forInternetConnection().currentReachabilityStatus() + + if reachabilityStatus != NotReachable { + offlineAvailable = true + + defaults.set(rows, forKey: "offlineOmissions") + defaults.set(userPlan, forKey: "ownOfflineOmissions") + defaults.set(offlineAvailable, forKey: "offlineAvailable") + defaults.synchronize() + + saveButton.isEnabled = false + } else { + saveButton.isEnabled = false let noConnectionAlertController = UIAlertController(title: "Keine Internetverbindung", message: "Es besteht keine Verbindung zum Internet. Dadurch kann der Vertretungsplan nicht gesichert werden. Bitte überprüfe Deine Einstellungen.", preferredStyle: .alert) noConnectionAlertController.addAction(UIAlertAction(title: "OK", style: .cancel, handler: { _ in @@ -351,8 +349,8 @@ class OmissionsViewController: UITableViewController { })) present(noConnectionAlertController, animated: true, completion: nil) - } - } + } + } /// /// Set navigation item title diff --git a/ELG/ReleaseNotes.html b/ELG/ReleaseNotes.html index 02027d2..2b2039b 100644 --- a/ELG/ReleaseNotes.html +++ b/ELG/ReleaseNotes.html @@ -67,7 +67,7 @@

- Fehlerbehebungen: Diese Version enthält kleine Fehlerbehebungen und Verbesserungen. + Fehlerbehebung: Behebt einen Fehler, der beim Laden des Vertretungsplans zum unerwarteten Beenden der App führen kann.