{"id":18756236,"url":"https://github.com/simonberner/calendar-widget","last_synced_at":"2025-04-13T01:58:32.523Z","repository":{"id":106072850,"uuid":"577778218","full_name":"simonberner/calendar-widget","owner":"simonberner","description":"Swift Calendar Widget - Core Data","archived":false,"fork":false,"pushed_at":"2024-02-06T21:04:10.000Z","size":6166,"stargazers_count":16,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-13T01:58:11.735Z","etag":null,"topics":["appintents","coredata","swift","swiftui","widgetkit"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonberner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-12-13T14:00:26.000Z","updated_at":"2025-02-13T09:45:37.000Z","dependencies_parsed_at":"2024-02-06T22:24:36.074Z","dependency_job_id":"123c7ccc-ef18-4295-9f1b-2f01e11a0037","html_url":"https://github.com/simonberner/calendar-widget","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonberner%2Fcalendar-widget","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonberner%2Fcalendar-widget/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonberner%2Fcalendar-widget/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonberner%2Fcalendar-widget/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonberner","download_url":"https://codeload.github.com/simonberner/calendar-widget/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248654048,"owners_count":21140235,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appintents","coredata","swift","swiftui","widgetkit"],"created_at":"2024-11-07T17:35:44.363Z","updated_at":"2025-04-13T01:58:32.491Z","avatar_url":"https://github.com/simonberner.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=center\u003eCalendar Widget - Core Data\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://en.wikipedia.org/wiki/IOS\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/iOS-17.2+-blue.svg?style=for-the-badge\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.swift.org/\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Swift-5.9.2-brightgreen.svg?style=for-the-badge\u0026logo=swift\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://developer.apple.com/xcode/swiftui\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/SwiftUI-blue.svg?style=for-the-badge\u0026logo=swift\u0026logoColor=black\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://developer.apple.com/xcode\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Xcode-15.2-blue.svg?style=for-the-badge\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://mastodon.green/@simonberner\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Contact-@simonberner-orange?style=for-the-badge\" alt=\"mastodon.green/@simonberner\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://gitmoji.dev\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/gitmoji-%20😜%20😍-FFDD67.svg?style=for-the-badge\" alt=\"Gitmoji\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/conventional-commits/conventionalcommits.org\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Conventional%20Commits-📝-lightgrey.svg?style=for-the-badge\" alt=\"Conventional Commits\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/license-MIT-black.svg?style=for-the-badge\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nThis App shows how one can migrate an existing App which is using a Core Data App container, to an App with a Widget Extension and a shared Core Data\ncontainer for both parts in place.\n\n---\n\n## Contents\n* [Functionality](#functionality)\n* [Definitions](#definitions)\n* [Tech Stack](#tech-stack)\n* [Frameworks](#frameworks)\n* [Device Compatibility](#device-compatibility)\n* [Screenshots](#screenshots)\n* [Learnings](#learnings)\n* [Testing](#testing)\n* [Code Comments](#code-comments)\n* [Pull Requests](#pull-requests)\n* [Credits](#credits)\n\n---\n\n## Functionality\n### App\n- In the calendar view the user can define/select days of study in the current month.\n- The streak view shows the user for how many days they have studied in a row. As streak days count only those days, where the user has studied for at least the current or past day (from the current day) descending.\n### Widget Extension\n- The Widget updates in real time to the changes made in the App and automatically at the end of each day.\n- As it is a medium sized Widget, there are two touch targets on it. One that deep links into the StreakView and the other into the CalendarView of the App.\n\n## Definitions\n- [First day of the week](https://www.timeanddate.com/calendar/days/first-day-of-the-week.html) is Monday.\n\n## Tech Stack\n- Xcode 15.2\n- Swift 5.9.2\n\n## Frameworks\n- SwiftUI\n- WidgetKit\n- CoreData\n\n## Device Compatibility\n- iPhone iOS 17.2+\n- iPad iOS 17.2+\n\n## Screenshots\n| Calendar View | Streak View | Widget View |\n| :---: | :---: | :---: |\n| \u003cimg src=\"AppScreenshots/SwiftCalendarApp.png\" height=\"100%\" width=\"100%\" \u003e | \u003cimg src=\"AppScreenshots/SwiftCalendarAppStreakView.png\" height=\"100%\" width=\"100%\" \u003e | \u003cimg src=\"AppScreenshots/SwiftCalendarWidget.png\" height=\"100%\" width=\"100%\" \u003e |\n\n| Lock Screen Widgets |\n| :---: |\n| \u003cimg src=\"AppScreenshots/Lock-Screen-Widgets.gif\" height=\"80%\" width=\"80%\" \u003e |\n\n\n## Learnings\n### Widget\n- In a Widget we should NOT make async network calls (according to Apple), because of that we can't use the property wrapper '@FetchRequest' in a Widget.\n#### Touch Targets (Deep linking into the App)\n- Deep linking from the Widget into the App can be made by wrapping a view with ```Link()```. This is only available on a medium and a large Widget. We can not have more than one touch targets on a small widget. The only touch target on a small widget is the whole widget.\n- On a small widget, we would use the view modifier ```.widgetURL()```\n- SwiftCalendarApp: here we have to tag the views for deep-linking\n### Calendar\n- [The first day of the week](https://www.timeanddate.com/calendar/days/first-day-of-the-week.html) depends on where you are in the world.\n- Calendar.Component.weekday -\u003e The weekday units are the numbers 1 through N (where for the Gregorian calendar N=7 and 1 is Sunday).\n### Core Data\n- [Core Data](https://en.wikipedia.org/wiki/Core_Data) is a persistence framework.\n- [SQLite](https://www.sqlite.org) is the CoreData database engine\n- An AppGroup allows us to share one or more CoreData containers among multiple apps.\n- If you already have an existing App with a CoreData container in place, you have to do a data migration to share that container with\nanother App, Widget Extension or App Clip.\n### SwiftData\n- [SwiftData](https://codewithchris.com/swift-data/)\n- Same as CoreData, SwifttData uses SQLite as its database engine.\n### SwiftUI Preview\n- The benefit of having previews is to help you building your UI quickly.\n- Don't invest too much time in maintaining your previews.\n- It probably doesn't make sense to fetch some data in the preview code.\n### How to make code available or unavailable for different platform versions\n- [@available and #available](https://www.avanderlee.com/swift/available-deprecated-renamed/#the-difference-between-available-and-available)\n- @available: is used when a class or method shall only be [made available](https://www.avanderlee.com/swift/available-deprecated-renamed/#setting-the-availability-for-a-class-or-method) to specific iOS versions.\n- #available: is used to execute pieces of code in your flow (if #available(...) else {}) only for specific iOS versions.\n- There are also attributes values for: deprecated, obsoleted, renamed, unavailable\n### Other cool stuff\n- [A Tour through Swift Attributes - Marco Eidinger](https://watch.softinio.com/w/d6jiJFm5hEFrzmKw9kdgXC)\n- [Create your own Xcode code snippets](https://www.youtube.com/watch?v=GaV8iLGeVrc)\n\n## Testing\nI use the [Arrange, Act and Assert Pattern](https://automationpanda.com/2020/07/07/arrange-act-assert-a-pattern-for-writing-good-tests/) for Unit Testing.\n\n## Code Comments\nI like putting in the effort of adding comments to my code, [here is why](https://www.youtube.com/watch?v=1NEa-OcsTow).\n\n## Pull Requests\nWhen I create PRs I stick to [this guideline](https://www.youtube.com/watch?v=_sfzAOfY8uc).\n\n## Credits\n🙏🏽 Sean Allen\n\n\u003chr\u003e\n\u003cp align=\"center\"\u003e\nMade with a 🙂 \u003ca href=\"https://simonberner.dev\"\u003eSimon Berner\n\u003c/p\u003e\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonberner%2Fcalendar-widget","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonberner%2Fcalendar-widget","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonberner%2Fcalendar-widget/lists"}