💊 PillMemo
PillMemo is an easy-to-use application that helps users remember to take their medicine 🏥
The application allows users to set reminders for different types of medicine and at different times of the day/week/month 📅
👨💻 Technology Used
- SwiftUI
- Core Data
- CloudKit
- User Notifications
- UICalendarView
📌 What Changed In The Repo
🎥 PillMemo In Action
🏆 Standout Success
Distinguish to save pill data with and without notifications.
Sounds trivial, but the real challenge was to create functionality to save pill data in Core Data and be read correctly by app, where each pill needed to be unique. Why? Because earlier, every next pill was saved, but remembered with the same reference, for the same date, where for the same date can be taken more than one pill. Without this change, app crashed every time when I wanted to save new pill with the same exact date.
func addMedicine(context: NSManagedObjectContext) async -> Bool {
// MARK: Editing Data
var medicine: Medicine!
if let editMedicines = editMedicines {
await context.perform {
medicine = editMedicines
// MARK: Remove All Pending Notifications
UNUserNotificationCenter.current()
.removePendingNotificationRequests(withIdentifiers: medicine.medicineNotificationIDs ?? [])
medicine.medicineTitle = self.title
medicine.medicineColor = self.medicineColor
medicine.medicineWeekdays = self.weekDays
medicine.medicineType = self.medicineType
medicine.medicineTakePartOne = self.takeMedicinePartOne
medicine.medicineTakePartTwo = self.takeMedicinePartTwo
medicine.medicineIsReminderOn = self.isReminderOn
medicine.medicineReminderText = self.title
medicine.medicineNotificationDate = self.reminderDate
medicine.medicineNotificationIDs = []
medicine.medicineQuantity = self.quantityMedicine
medicine.medicineCalendarIcon = self.calendarIcon
}
// Check if reminder is turn on here
if isReminderOn {
// MARK: Notifications Are Going To Be Scheduled
if let ids = try? await scheduleNotification() {
await context.perform {
medicine.medicineNotificationIDs = ids
try? context.save()
TelemetryManager.send("Edited medicine with reminder", with: ["Name": self.title])
}
return true
}
} else {
// MARK: Add Data To Be Saved Without Reminder
await context.perform {
try? context.save()
TelemetryManager.send("Edited medicine without reminder", with: ["Name": self.title])
}
return true
}
} else {
await context.perform {
// MARK: Fetch Existing Event Records
let fetchRequest: NSFetchRequest<Medicine> = Medicine.fetchRequest()
do {
let existingMedicines = try self.moc.fetch(fetchRequest)
// Determine the count of existing medicine
let medicineCount = existingMedicines.count
print(medicineCount)
medicine = Medicine(context: context)
// Add a number to be as a uniqal reference for each medicine
medicine.medicineNumber = Int32(medicineCount + 1)
medicine.medicineTitle = self.title
medicine.medicineColor = self.medicineColor
medicine.medicineWeekdays = self.weekDays
medicine.medicineType = self.medicineType
medicine.medicineTakePartOne = self.takeMedicinePartOne
medicine.medicineTakePartTwo = self.takeMedicinePartTwo
medicine.medicineIsReminderOn = self.isReminderOn
medicine.medicineReminderText = self.title
medicine.medicineNotificationDate = self.reminderDate
medicine.medicineNotificationIDs = []
medicine.medicineQuantity = self.quantityMedicine
medicine.medicineCalendarIcon = self.calendarIcon
} catch {
print("Failed to insert event: \\(error.localizedDescription)")
}
}
// Check if reminder is turn on here
if isReminderOn {
// MARK: Notifications Are Going To Be Scheduled
if let ids = try? await scheduleNotification() {
await context.perform {
medicine.medicineNotificationIDs = ids
try? context.save()
self.medicines.append(medicine)
self.changedMedicine = medicine
TelemetryManager.send("Added medicine with reminder", with: ["Name": self.title])
}
return true
}
} else {
// MARK: Add Data To Be Saved Without Reminder
await context.perform {
try? context.save()
self.medicines.append(medicine)
self.changedMedicine = medicine
TelemetryManager.send("Added medicine without reminder", with: ["Name": self.title])
}
return true
}
}
return false
}
🧩 Entireness
Nevertheless, while creating this simple medicine reminder app, I have also included the following:
- In-App Purchases
- TipKit
- WishKit
- Concurrency
- Error handling & alerts
- Onboarding
- PDF Generator
- Unit Tests
- UI Tests
- CI/CD (Xcode Cloud)
- Project organization (VOODO Architecture)
- Privacy Manifest
- Published in App Store (04/2024)
ℹ️ License
The PillMemo is the property of Marcin Jędrzejak. Unauthorized copying, distribution, or modification of this application is strictly prohibited.