Added base for lecture plan view

This commit is contained in:
2021-01-30 23:05:44 +01:00
committed by Patrick Müller
parent 81f9e8706c
commit 95f06cc87d
8 changed files with 323 additions and 4 deletions
+89
View File
@@ -0,0 +1,89 @@
//
// ApiService.swift
// DHBW-Service
//
// Created by Patrick Müller on 29.01.21.
//
import Foundation
class ApiService {
// MARK: HTTP POST Request
public class func callPost(url: URL, parameters: [String:Any], finish: @escaping ((message: String, data: Data?)) -> Void) {
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
// Set params
let postString = self.getPostString(params: parameters)
request.httpBody = postString.data(using: .utf8)
var result: (message: String, data:Data?) = (message: "Fail", data: nil)
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
do {
guard error == nil else {
throw HttpFetchError.fetchError
}
guard let data = data else {
throw HttpFetchError.noDataReceivedError
}
result.message = "Success"
result.data = data
} catch let error {
print(error.localizedDescription)
}
finish(result)
}
task.resume()
}
// MARK: HTTP GET Request
public class func callGet(url: URL, finish: @escaping ((message: String, data: Data?)) -> Void) {
var request = URLRequest(url: url)
request.httpMethod = "GET"
//request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
//request.addValue("application/json", forHTTPHeaderField: "Accept")
var result: (message: String, data:Data?) = (message: "Fail", data: nil)
let task = URLSession.shared.dataTask(with: request as URLRequest) { data, response, error in
do {
guard error == nil else {
throw HttpFetchError.fetchError
}
guard let data = data else {
throw HttpFetchError.noDataReceivedError
}
result.message = "Success"
result.data = data
} catch let error {
print(error.localizedDescription)
}
finish(result)
}
task.resume()
}
// MARK: Data preparation
private class func getPostString(params: [String:Any]) -> String {
var data = [String]()
for(key, value) in params{
data.append(key + "=\(value)")
}
return data.map{String($0)}.joined(separator: "&")
}
// MARK: Error enum
private enum HttpFetchError: Error {
case fetchError
case noDataReceivedError
}
}
+138
View File
@@ -0,0 +1,138 @@
//
// RaPlaFetcher.swift
// DHBW-Service
//
// Created by Patrick Müller on 29.01.21.
//
import Foundation
import CoreData
class RaPlaFetcher {
public class iCalEvent {
var startDate: Date = Date() //DTSTART
var endDate: Date = Date() //DTEND
var summary: String = "" //SUMMARY
var description: String = "" //DESCRIPTION
var location: String = "" //LOCATION
var category: String = "" //CATEGORIES
}
// Get the RaPla file from the given URL and save the events to CoreData
public class func getRaplaFileAndSaveToCoreData(from urlString: String) -> Bool {
let file = getFileAsString(from: urlString)
let eventStrings = splitIntoEvents(file: file)
let eventObjects = convertStringsToObjects(eventStrings: eventStrings)
return saveToCoreData(eventObjects: eventObjects)
}
// Get the RaPla files from the given URL and return the event objects
public class func getRaplaFileAndReturnEvents(from urlString: String) -> [iCalEvent] {
let file = getFileAsString(from: urlString)
let eventStrings = splitIntoEvents(file: file)
return convertStringsToObjects(eventStrings: eventStrings)
}
// GET the file from the given URL and convert it to a String that is then returned
private class func getFileAsString(from urlString: String) -> String {
let url = URL(string: urlString)!
var file: String = ""
do {
file = try String(contentsOf: url, encoding: .utf8)
} catch let error {
print(error.localizedDescription)
}
return file
}
// Split the given ical file string into individual event strings and return them as a list
private class func splitIntoEvents(file: String) -> [String] {
let regexOptions: NSRegularExpression.Options = [.dotMatchesLineSeparators]
// Regex explanation: Matches BEGIN:VEVENT "Any character" END:VEVENT across multiple lines. The *? assures that we receive the
// maximum amount of matches, i.e. it makes the regex non-greedy as we would otherwise just receive one giant match
let eventStrings = UtilityFunctions.regexMatches(for: "BEGIN:VEVENT.*?END:VEVENT", with: regexOptions, in: file)
return eventStrings
}
// Convert an ical event String into an iCalEvent Codable object as defined above
private class func convertStringsToObjects(eventStrings: [String]) -> [iCalEvent] {
var events: [iCalEvent] = []
for eventString in eventStrings {
let lines = eventString.components(separatedBy: .newlines)
let evt = iCalEvent()
for line in lines {
var lineWithoutPrefix = line
if(!line.contains(":")) {
continue
}
lineWithoutPrefix.removeSubrange(lineWithoutPrefix.startIndex...lineWithoutPrefix.firstIndex(of: ":")!)
if(line.hasPrefix("DTSTART")){
//Date format: 20181101T080000
let dateFormatter = DateFormatter()
if(lineWithoutPrefix.contains("Z")){
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmssZ"
} else {
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss"
}
let date = dateFormatter.date(from: lineWithoutPrefix)!
evt.startDate = date
} else if(line.hasPrefix("DTEND")){
let dateFormatter = DateFormatter()
if(lineWithoutPrefix.contains("Z")){
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmssZ"
} else {
dateFormatter.dateFormat = "yyyyMMdd'T'HHmmss"
}
let date = dateFormatter.date(from: lineWithoutPrefix)!
evt.endDate = date
} else if(line.hasPrefix("SUMMARY")){
evt.summary = lineWithoutPrefix
} else if(line.hasPrefix("DESCRIPTION")){
evt.description = lineWithoutPrefix
} else if(line.hasPrefix("LOCATION")){
evt.location = lineWithoutPrefix
} else if(line.hasPrefix("CATEGORIES")){
evt.category = lineWithoutPrefix
}
}
events.append(evt)
}
return events
}
// Save the given iCalEvent objects to CoreData
private class func saveToCoreData(eventObjects: [iCalEvent]) -> Bool{
// Delete old data
if(UtilityFunctions.deleteAllCoreDataEntitiesOfType(type: "RaPlaEvent")){
for event in eventObjects {
let entity = NSEntityDescription.entity(forEntityName: "RaPlaEvent", in: PersistenceController.shared.context)!
let evt = NSManagedObject(entity: entity, insertInto: PersistenceController.shared.context)
evt.setValue(event.startDate, forKey: "startDate")
evt.setValue(event.endDate, forKey: "endDate")
evt.setValue(event.summary, forKey: "summary")
evt.setValue(event.description, forKey: "descr")
evt.setValue(event.location, forKey: "location")
evt.setValue(event.category, forKey: "category")
}
PersistenceController.shared.save()
return true
} else {
return false
}
}
}
+18 -1
View File
@@ -9,12 +9,13 @@ import Foundation
import CoreData
class UtilityFunctions {
public class func getCoreDataObject(entity: String) -> [NSManagedObject]{
public class func getCoreDataObject(entity: String, sortDescriptors: [NSSortDescriptor]) -> [NSManagedObject]{
let managedContext =
PersistenceController.shared.context
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: entity)
fetchRequest.sortDescriptors = sortDescriptors
do {
return try managedContext.fetch(fetchRequest)
@@ -60,4 +61,20 @@ class UtilityFunctions {
return allSuccessful
}
// MARK: Find matches in the given text for the given regex string.
public class func regexMatches(for regex: String, with options: NSRegularExpression.Options, in text: String) -> [String] {
do {
let regex = try NSRegularExpression(pattern: regex, options: options)
let results = regex.matches(in: text,
range: NSRange(text.startIndex..., in: text))
return results.map {
String(text[Range($0.range, in: text)!])
}
} catch let error {
print("invalid regex: \(error.localizedDescription)")
return []
}
}
}