From 857db7501dde5cc349f1748b34f5731adcea19e7 Mon Sep 17 00:00:00 2001 From: Oschly Date: Thu, 21 May 2026 21:15:10 +0200 Subject: [PATCH] finish draft of the implementation chapter --- Thesis/Chapters/3. Implementation.typ | 13 ++++++++++++- Thesis/main.pdf | 4 ++-- Thesis/style.typ | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Thesis/Chapters/3. Implementation.typ b/Thesis/Chapters/3. Implementation.typ index 42cc128..5a721be 100644 --- a/Thesis/Chapters/3. Implementation.typ +++ b/Thesis/Chapters/3. Implementation.typ @@ -435,4 +435,15 @@ Jeśli aplikacja została dopiero zainstalowana, system pokaże też monit użyt ) == Napotkane wyzwania implementacyjne i rozwiązania -== Ograniczenia środowisk iOS/macOS + +W czasie implementacji opisywanej aplikacji natknąłem się na problemy, które były związane z poszczególnymi częściami synchronizacji tekstu. Pierwszym z nich jest zachowanie frameworka Multipeer Connectivity, gdzie nasłuchiwanie na dostępnych użytkowników za pomocą `MCNearbyServiceBrowser` wykrywa także samego siebie jako jednego z dostępnych klientów. Skutkowało to wysyłaniem zmian przez urządzenie do samego siebie oraz otrzymywanie zduplikowanych kopii notatek z innych urządzeń. By temu zapobiec, w metodzie obsługującej wykrywanie dostępnych użytkowników - widocznej w algorytmie 3.7 - zaimplementowałem filtr, który ignoruje użytkowników o takiej samej nazwie użytkownika. + +Następnym problemem związanym z Multipeer Connectivity jest jego ogólna niestabilność. W sytuacjach, gdzie połączenie staje się niestabilne - oddalenie się od siebie użytkowników, gdy do komunikacji jest wykorzystywany Bluetooth; przełączanie się między sieciami Wi-Fi - otrzymywane zdarzenia nie są deterministyczne. Czasem aplikacja otrzymywała na przemian informacje o rozłączeniu i ponownym połączeniu się z zaproszonymi klientami, czasem nigdy nie otrzymywała informacji o tym, że klient się rozłączył. Podobne problemy zostały zauważone w momencie wyjścia z aplikacji - wielokrotnie aplikacja traciła połączenie z innymi klientami, ale metody, które powinny zostać z tego powodu wywołane, czasami nie były wykonywane. + +Ostatnim, najcięższym problemem jest aktualizacja pozycji kursora w edytorze tekstu. W momencie nanoszenia zmian należy rozważyć, czy został wstawiony lub usunięty tekst z części notatki, która znajduje się na wcześniejszej pozycji względem kursora każdego z użytkowników. Jeśli tak, to poprawnym zachowaniem byłoby przeniesienie odpowiednio kursora tak, by żaden z klientów nie spotkał się z sytuacją, gdzie kursor zmienia swoje położenie bez wyraźnej akcji użytkownika. Jest to problematyczne w aktualnej implementacji z dwóch powodów. Pierwszym problemem jest algorytm nanoszenia zmian - ze względu na to, że sposób w jaki ten proces wykonujemy polega na całkowitej podmianie istniejącego tekstu na nowy, powinno się przed jego wykonaniem ustalić wcześniej wspomniane istnienie zmian tekstu na pozycji wcześniejszej od kursora użytkownika. Przez to, że nie wykorzystywane są tutaj struktury CRDT, które mają bardzo dokładne informacje o nanoszonych zmianach, musimy polegać na ręcznej analizie obu ciągów tekstowych. Takie przeliczanie jest też problematyczne w przypadku obsługi wszystkich wspieranych przez system alfabetów. Następnym problemem jest niestabilny interfejs do manipulacji pozycją kursora w edytorze tekstu dostarczanym przez SwiftUI. Proces aktualizacji polega najpierw na wyliczeniu punktu przesunięcia kursora, następnie zamianę tekstu w edytorze na zaktualizowaną wersję i finalnie podmianę pozycji kursora. Testy manualne aplikacji wykazały, że kolejność nanoszenia dwóch ostatnich zmian an interfejs graficzny użytkownika przez SwiftUI jest niedeterministyczne. Zdarzały się sytuacje, gdzie pozycja kursora była aktualizowana przed naniesieniem nowej wersji tekstu. Bardzo często to się zdarzało w przypadku, gdy zawartość tekstowa była wielkości przynajmniej 1000 znaków. Najstabilniejszym rozwiązaniem, które nie wymagało implementacji struktur CRDT oraz implementacji kursora od zera z wykorzystaniem starszego frameworka - UIKit - okazało się pozostawienie domyślnego zachowania podczas zewnętrznej aktualizacji tekstu w edytorze. Niestety nadal można zaobserwować błędy z tym związane, ale nie są one tak częste jak w przypadku, gdy tym kursorem aplikacja próbowała dodatkowo manipulować obok istniejącego mechanizmu dostarczanego przez SwiftUI, którego nie da się wyłączyć. + +== Ograniczenia środowisk iOS/iPadOS + +Ze względu na to, że aplikacja została napisana w pełni z wykorzystaniem natywnych technologii - Swift, SwiftUI, Combine, Multipeer Connectivity - projekt aplikacji jest niemożliwy do zbudowania bez posiadania komputera z najnowszą wersją systemu macOS oraz środowiska programistycznego Xcode. Kolejnym problemem jest obowiązek posiadania konta Apple Developer, który wymaga wyrażenia zgody na regulamin użytkowania oprogramowania dostarczanego przez firmę Apple do rozwoju aplikacji na systemy operacyjne iOS i iPadOS. Wszystkie wspomniane wymogi sprawiają, że kontrybucja do kodu źródłowego aplikacji jak i jej kompilacja we własnym zakresie jest bardzo utrudniona. + +Następnym problemem jest interfejs frameworku Multipeer Connectivity. Opiera się on na przekazywaniu obustronnie specjalnych obiektów oraz narzuca konkretne sposoby wymiany danych między instancjami aplikacji. Sprawia to, że implementacja, bez tworzenia dodatkowych warstw abstrakcji, nie jest możliwa do rozszerzenia o wsparcie innych systemów operacyjnych. Rozważaną alternatywą było użycie frameworku Network, który opiera się na przesyłaniu ramek TCP, ale to znacznie zwiększało złożoność całej implementacji. \ No newline at end of file diff --git a/Thesis/main.pdf b/Thesis/main.pdf index 7c80fe3..02f37ee 100644 --- a/Thesis/main.pdf +++ b/Thesis/main.pdf @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:0b8ba6a610261fed78d45eedb66ebae31ac8326bc09acb606954bdae2e8d750d -size 1418271 +oid sha256:de1f1aa33fd9c2875405a376511e5dbe43b7033289ad563f863964e2c4bf27d1 +size 1428079 diff --git a/Thesis/style.typ b/Thesis/style.typ index 83a0fab..3e77a21 100644 --- a/Thesis/style.typ +++ b/Thesis/style.typ @@ -88,7 +88,7 @@ let pg = counter(page).get().first() let is-odd = calc.odd(pg) - // Czy ta strona otwiera rozdział? (→ plain style: brak nagłówka) + // Czy ta strona otwiera rozdział? (brak nagłówka) let chapter-locs = query(heading.where(level: 1)) let is-chapter-page = chapter-locs.any(h => counter(page).at(h.location()).first() == pg)