mirror of
https://github.com/Mueller-Patrick/DHBW-Service-App.git
synced 2026-04-28 18:30:09 +00:00
✨ Added base for lecture plan view
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 []
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user