{"id":3522,"date":"2024-05-28T23:49:24","date_gmt":"2024-05-28T20:49:24","guid":{"rendered":"https:\/\/demensdeum.com\/blog\/?p=3522"},"modified":"2024-12-16T22:32:13","modified_gmt":"2024-12-16T19:32:13","slug":"crud-repository","status":"publish","type":"post","link":"https:\/\/demensdeum.com\/blog\/ru\/2024\/05\/28\/crud-repository\/","title":{"rendered":"CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439"},"content":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0435 \u044f \u043e\u043f\u0438\u0448\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 CRUD, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Swift. Swift \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c, \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u041e\u0421 Windows, Linux, macOS, iOS, Android.<\/p>\n<p>\u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0445\u043e\u0434 CRUD, \u044d\u0442\u043e \u0430\u043a\u0440\u043e\u043d\u0438\u043c \u043e\u0442 C &#8211; Create, R -Read, U &#8211; Update, D &#8211; Delete.<br \/>\u041e\u0431\u044b\u0447\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u0430 \u043a \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0440\u0430\u0431\u043e\u0442\u0430 \u0441 \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 id. \u0421\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043f\u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u0431\u0443\u043a\u0432\u0435 CRUD &#8211; Create(object, id), Read(id), Update(object, id), Delete(object, id).<br \/>\u0415\u0441\u043b\u0438 \u043e\u0431\u044a\u0435\u043a\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 id \u0432\u043d\u0443\u0442\u0440\u0438 \u0441\u0435\u0431\u044f, \u0442\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442 id \u043c\u043e\u0436\u043d\u043e \u0443\u043f\u0443\u0441\u0442\u0438\u0442\u044c \u0432 \u0447\u0430\u0441\u0442\u0438 \u043c\u0435\u0442\u043e\u0434\u043e\u0432 (Create, Update, Delete), \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0443\u0434\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442 \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0432\u043c\u0435\u0441\u0442\u0435 \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u043f\u043e\u043b\u0435\u043c &#8211; id. \u0410 \u0432\u043e\u0442 \u0434\u043b\u044f &#8211; Read \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f id, \u0442\u0430\u043a \u043a\u0430\u043a \u043c\u044b \u0445\u043e\u0442\u0438\u043c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0438\u0437 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0443.<\/p>\n<p>\u0412\u0441\u0435 \u0438\u043c\u0435\u043d\u0430 \u0432\u044b\u043c\u044b\u0448\u043b\u0435\u043d\u044b<\/p>\n<p>\u041f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u043c \u0447\u0442\u043e \u0433\u0438\u043f\u043e\u0442\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 AssistantAI \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u043b\u043e\u0441\u044c \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u0439 SDK \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 EtherRelm, \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u044f \u0431\u044b\u043b\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, API \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u044b\u043c, \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0432\u044b\u043f\u0443\u0449\u0435\u043d\u043e \u0432 \u043c\u0430\u0440\u043a\u0435\u0442\u044b.<br \/>\u0412\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f-\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a SDK EtherRelm \u0440\u0435\u0448\u0430\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0451 \u043f\u043b\u0430\u0442\u043d\u043e\u0439, \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u044f \u0446\u0435\u043d\u0443 \u0432 100$ \u0432 \u0433\u043e\u0434 \u0437\u0430 \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<br \/>\u0427\u0442\u043e? \u0414\u0430! \u0427\u0442\u043e \u0436\u0435 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0438\u0437 AssistantAI, \u0432\u0435\u0434\u044c \u0443 \u043d\u0438\u0445 \u0443\u0436\u0435 1\u043c\u043b\u043d \u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439! \u041f\u043b\u0430\u0442\u0438\u0442\u044c 100 \u043c\u043b\u043d \u0434\u043e\u043b\u043b\u0430\u0440\u043e\u0432?<br \/>\u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0446\u0435\u043d\u0438\u0442\u044c \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0430 \u043d\u0430\u0442\u0438\u0432\u043d\u0443\u044e \u0434\u043b\u044f \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 RootData, \u043f\u043e \u043e\u0446\u0435\u043d\u043a\u0435 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u043e\u0432 \u0442\u0430\u043a\u043e\u0439 \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0437\u0430\u0439\u043c\u0435\u0442 \u043e\u043a\u043e\u043b\u043e \u043f\u043e\u043b\u0443\u0433\u043e\u0434\u0430, \u044d\u0442\u043e \u0431\u0435\u0437 \u0443\u0447\u0435\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043d\u043e\u0432\u044b\u0445 \u0444\u0438\u0447 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438. \u041f\u043e\u0441\u043b\u0435 \u043d\u0435\u0434\u043e\u043b\u0433\u0438\u0445 \u0440\u0430\u0437\u0434\u0443\u043c\u0438\u0439, \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0443\u0431\u0440\u0430\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u0437 \u043c\u0430\u0440\u043a\u0435\u0442\u043e\u0432, \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e\u043c \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u043e\u043c \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0435 \u0441\u043e \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 BueMS, \u044d\u0442\u043e \u0440\u0435\u0448\u0438\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443 \u0441 \u043f\u043b\u0430\u0442\u043d\u043e\u0441\u0442\u044c\u044e \u0411\u0414 + \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0430 \u0434\u0440\u0443\u0433\u0438\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b.<br \/>\u0427\u0435\u0440\u0435\u0437 \u0433\u043e\u0434 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043f\u0438\u0441\u0430\u043d\u043e \u043d\u0430 BueMS, \u043d\u043e \u0442\u0443\u0442 \u0432\u043d\u0435\u0437\u0430\u043f\u043d\u043e \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0444\u0440\u0435\u0439\u043c\u0432\u043e\u0440\u043a\u0430 \u0440\u0435\u0448\u0430\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u043b\u0430\u0442\u043d\u044b\u043c. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u0447\u0442\u043e \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u043f\u043e\u043f\u0430\u043b\u0430 \u0432 \u043e\u0434\u043d\u0443 \u0438 \u0442\u0443 \u0436\u0435 \u043b\u043e\u0432\u0443\u0448\u043a\u0443 \u0434\u0432\u0430\u0436\u0434\u044b, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u0441\u044f \u043b\u0438 \u0443 \u043d\u0438\u0445 \u0432\u044b\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u0432\u043e \u0432\u0442\u043e\u0440\u043e\u0439 \u0440\u0430\u0437, \u044d\u0442\u043e \u0443\u0436\u0435 \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u0434\u0440\u0443\u0433\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f.<\/p>\n<p>\u0410\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c<\/p>\n<p>\u042d\u0442\u0438\u0445 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0431\u044b \u0438\u0437\u0431\u0435\u0436\u0430\u0442\u044c, \u0435\u0441\u043b\u0438 \u0431\u044b \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u0432\u043d\u0443\u0442\u0440\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041a \u0442\u0440\u0435\u043c \u043a\u0438\u0442\u0430\u043c \u041e\u041e\u041f &#8211; \u043f\u043e\u043b\u0438\u043c\u043e\u0440\u0444\u0438\u0437\u043c\u0443, \u0438\u043d\u043a\u0430\u043f\u0441\u0443\u043b\u044f\u0446\u0438\u0438, \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044e, \u043d\u0435 \u0442\u0430\u043a \u0434\u0430\u0432\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 \u0435\u0449\u0435 \u043e\u0434\u043d\u043e\u0433\u043e &#8211; \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e.<br \/>\u0410\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u0438\u0434\u0435\u0438, \u043c\u043e\u0434\u0435\u043b\u0438 \u0432 \u043e\u0431\u0449\u0438\u0445 \u0447\u0435\u0440\u0442\u0430\u0445, \u0441 \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u0435\u0442\u0430\u043b\u0435\u0439, \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u043e\u0447\u043d\u043e\u0439 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0445 \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0439, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0434\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u0437\u0430\u0434\u0430\u0447.<br \/>\u041a\u0430\u043a \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445, \u0447\u0442\u043e\u0431\u044b \u043b\u043e\u0433\u0438\u043a\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0435\u043b\u0430 \u043e\u0442 \u043d\u0435\u0435? \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043f\u043e\u0434\u0445\u043e\u0434 CRUD!<\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e UML \u0441\u0445\u0435\u043c\u0430 CRUD \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2024\/05\/image3.png\" alt=\"\" width=\"263\" height=\"118\" class=\"alignnone size-full wp-image-3537\" \/><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u0432\u044b\u043c\u044b\u0448\u043b\u0435\u043d\u043d\u043e\u0439 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 EtherRelm:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2024\/05\/image2.png\" alt=\"\" width=\"272\" height=\"118\" class=\"alignnone size-full wp-image-3538\" \/><\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u0441 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0439 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 SQLite:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/demensdeum.com\/blog\/wp-content\/uploads\/2024\/05\/image1.png\" alt=\"\" width=\"243\" height=\"118\" class=\"alignnone size-full wp-image-3539\" \/><\/p>\n<p>\u041a\u0430\u043a \u0432\u044b \u0443\u0436\u0435 \u0437\u0430\u043c\u0435\u0442\u0438\u043b\u0438, \u043f\u0440\u0438 \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0438 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u043c\u0435\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u043d\u0430, \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 CRUD \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u043d\u0435\u0438\u0437\u043c\u0435\u043d\u043d\u044b\u043c. CRUD \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 GoF &#8211; \u0410\u0434\u0430\u043f\u0442\u0435\u0440, \u0442.\u043a. \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043d\u0435\u0433\u043e \u043c\u044b \u0430\u0434\u0430\u043f\u0442\u0438\u0440\u0443\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u043a \u043b\u044e\u0431\u043e\u0439 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445, \u0441\u043e\u0432\u043c\u0435\u0449\u0430\u0435\u043c \u043d\u0435\u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u043c\u044b\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b.<br \/>\u0421\u043b\u043e\u0432\u0430 \u044d\u0442\u043e \u043f\u0443\u0441\u0442\u043e\u0435, \u043f\u043e\u043a\u0430\u0436\u0438 \u043c\u043d\u0435 \u043a\u043e\u0434<br \/>\u0414\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0439 \u0432 \u044f\u0437\u044b\u043a\u0430\u0445 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b\/\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b\/\u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0435 \u043a\u043b\u0430\u0441\u0441\u044b. \u0412\u0441\u0435 \u044d\u0442\u043e \u044f\u0432\u043b\u0435\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0430, \u043e\u0434\u043d\u0430\u043a\u043e \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u044f\u0445 \u0432\u0430\u0441 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u0438\u0446\u0443 \u043c\u0435\u0436\u0434\u0443 \u043d\u0438\u043c\u0438, \u044f \u043b\u0438\u0447\u043d\u043e \u0441\u0447\u0438\u0442\u0430\u044e \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u043e\u0441\u043e\u0431\u043e\u0433\u043e \u0441\u043c\u044b\u0441\u043b\u0430 \u043d\u0435\u0442 \u0442.\u043a. \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0446\u0435\u043b\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044d\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445, \u0432 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u043c \u044d\u0442\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u044c\u044e\u0438\u0440\u0443\u0435\u043c\u043e\u0433\u043e.<br \/>CRUD \u0447\u0430\u0441\u0442\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 \u0420\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439, \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u043e\u0434\u043d\u0430\u043a\u043e \u043c\u043e\u0436\u0435\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 CRUD, \u0430 \u043c\u043e\u0436\u0435\u0442 \u0438 \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c, \u0432\u0441\u0451 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430.<\/p>\n<p>\u0420\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0442\u0438\u043f\u0438\u0447\u043d\u044b\u0439 Swift \u043a\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 Book, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 UserDefaults:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nstruct Book: Codable {\n\tlet title: String\n\tlet author: String\n}\n\nclass BookRepository {\n\tfunc save(book: Book) {\n    \t\tlet record = try! JSONEncoder().encode(book)\n    \t\tUserDefaults.standard.set(record, forKey: book.title)\n\t}\n    \n\tfunc get(bookWithTitle title: String) -&gt; Book? {\n    \t\tguard let data = UserDefaults.standard.data(forKey: title) else { return nil }\n    \t\tlet book = try! JSONDecoder().decode(Book.self, from: data)\n    \t\treturn book\n\t}\n    \n\tfunc delete(book: Book) {\n    \t\tUserDefaults.standard.removeObject(forKey: book.title)\n\t}\n}\n\nlet book = Book(title: \"Fear and Loathing in COBOL\", author: \"Sir Edsger ZX Spectrum\")\nlet repository = BookRepository()\nrepository.save(book: book)\nprint(repository.get(bookWithTitle: book.title)!)\nrepository.delete(book: book)\nguard repository.get(bookWithTitle: book.title) == nil else {\n\tprint(\"Error: can't delete Book from repository!\")\n\texit(1)\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u041a\u043e\u0434 \u0432\u044b\u0448\u0435 \u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u0442\u044b\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0439 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0430 DRY (Do not Repeat Yourself) \u0438 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u043a\u043e\u0434\u0430:<br \/>\u0421\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 UserDefaults<br \/>\u0421\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441 \u044d\u043d\u043a\u043e\u0434\u0435\u0440\u0430\u043c\u0438 \u0438 \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430\u043c\u0438 JSON &#8211; JSONEncoder, JSONDecoder<br \/>\u0421\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0441\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 Book, \u0430 \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0442\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u043e \u043a\u043b\u0430\u0441\u0441\u0443 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u044b \u0431\u0443\u0434\u0435\u043c \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 (\u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435 DRY)<\/p>\n<p>\u0422\u0430\u043a\u043e\u0439 \u043a\u043e\u0434 CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u044f \u0432\u0441\u0442\u0440\u0435\u0447\u0430\u044e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0447\u0430\u0441\u0442\u043e, \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0438\u043c \u043c\u043e\u0436\u043d\u043e, \u043e\u0434\u043d\u0430\u043a\u043e \u0432\u044b\u0441\u043e\u043a\u0430\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043a\u043e\u0434\u0430, \u043f\u0440\u0438\u0432\u043e\u0434\u044f\u0442 \u043a \u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u0441\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0435\u0433\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u0438\u0442\u0441\u044f. \u041e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u043e\u0449\u0443\u0449\u0430\u0442\u044c\u0441\u044f \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u043b\u0438\u0431\u043e \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0439 \u043b\u043e\u0433\u0438\u043a\u0438 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0434 \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f\u0445.<br \/>\u0412\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e \u0447\u0442\u043e\u0431\u044b \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u0434, \u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432\u044b\u0441\u043e\u043a\u0443\u044e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c &#8211; \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b \u0434\u043b\u044f CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u0443\u044f \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f, \u0441\u043e\u0431\u043b\u044e\u0434\u0430\u044f DRY, \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044f \u043d\u0438\u0437\u043a\u0443\u044e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>    typealias Item = Codable\n    typealias ItemIdentifier = String\n    \n    func create&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws\n    func read&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier) async throws -&gt; T\n    func update&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws\n    func delete(id: CRUDRepository.ItemIdentifier) async throws\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u041f\u0440\u043e\u0442\u043e\u043a\u043e\u043b CRUDRepository \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u044b \u0438 \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0434\u0430\u043b\u044c\u043d\u0435\u0439\u0448\u0435\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u0434\u043b\u044f \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 UserDefaults:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>    private typealias RecordIdentifier = String\n    \n    let tableName: String\n    let dataTransformer: DataTransformer\n    \n    init(\n   \t tableName: String = \"\",\n   \t dataTransformer: DataTransformer = JSONDataTransformer()\n    ) {\n   \t self.tableName = tableName\n   \t self.dataTransformer = dataTransformer\n    }\n    \n    private func key(id: CRUDRepository.ItemIdentifier) -&gt; RecordIdentifier {\n   \t \"database_\\(tableName)_item_\\(id)\"\n    }\n   \t \n    private func isExists(id: CRUDRepository.ItemIdentifier) async throws -&gt; Bool {\n   \t UserDefaults.standard.data(forKey: key(id: id)) != nil\n    }\n    \n    func create&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws {\n   \t let data = try await dataTransformer.encode(item)\n   \t UserDefaults.standard.set(data, forKey: key(id: id))\n   \t UserDefaults.standard.synchronize()\n    }\n    \n    func read&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier) async throws -&gt; T {\n   \t guard let data = UserDefaults.standard.data(forKey: key(id: id)) else {\n   \t\t throw CRUDRepositoryError.recordNotFound(id: id)\n   \t }\n   \t let item: T = try await dataTransformer.decode(data: data)\n   \t return item\n    }\n    \n    func update&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws {\n   \t guard try await isExists(id: id) else {\n   \t\t throw CRUDRepositoryError.recordNotFound(id: id)\n   \t }\n   \t let data = try await dataTransformer.encode(item)\n   \t UserDefaults.standard.set(data, forKey: key(id: id))\n   \t UserDefaults.standard.synchronize()\n    }\n    \n    func delete(id: CRUDRepository.ItemIdentifier) async throws {\n   \t guard try await isExists(id: id) else {\n   \t\t throw CRUDRepositoryError.recordNotFound(id: id)\n   \t }\n   \t UserDefaults.standard.removeObject(forKey: key(id: id))\n   \t UserDefaults.standard.synchronize()\n    }\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u041a\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u043b\u0438\u043d\u043d\u044b\u043c, \u043e\u0434\u043d\u0430\u043a\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 \u043f\u043e\u043b\u043d\u0443\u044e \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u0443\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u043c \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c, \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e\u0441\u0442\u0438 \u0434\u0430\u043b\u0435\u0435.<br \/>typealias\u2019\u044b \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u043b\u044f \u0441\u0430\u043c\u043e\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u0434\u0430.<br \/>\u0421\u043b\u0430\u0431\u0430\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0441\u0438\u043b\u044c\u043d\u0430\u044f \u0441\u0432\u044f\u0437\u043d\u043e\u0441\u0442\u044c<br \/>\u041e\u0442\u0432\u044f\u0437\u043a\u0430 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b (struct) \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0433\u0435\u043d\u0435\u0440\u0438\u043a\u0430 T, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432 \u0441\u0432\u043e\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b Codable. Codable \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u044c \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043b\u0430\u0441\u0441\u043e\u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u044b TopLevelEncoder \u0438 TopLevelDecoder, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 JSONEncoder \u0438 JSONDecoder, \u043f\u0440\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0431\u0430\u0437\u043e\u0432\u044b\u0445 \u0442\u0438\u043f\u043e\u0432 (Int, String, Float \u0438 \u0442.\u0434.) \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0438\u0441\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434 \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440.<\/p>\n<p>\u041e\u0442\u0432\u044f\u0437\u043a\u0430 \u043e\u0442 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u044d\u043d\u043a\u043e\u0434\u0435\u0440\u0430 \u0438 \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0435 DataTransformer:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\tfunc encode&lt;T: Encodable&gt;(_ object: T) async throws -&gt; Data\n\tfunc decode&lt;T: Decodable&gt;(data: Data) async throws -&gt; T\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u0421 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u0430\u0442\u0430-\u0442\u0440\u0430\u043d\u0441\u0444\u043e\u0440\u043c\u0435\u0440\u0430 \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b\u0438 \u0430\u0431\u0441\u0442\u0440\u0430\u043a\u0446\u0438\u044e \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432 \u044d\u043d\u043a\u043e\u0434\u0435\u0440\u0430 \u0438 \u0434\u0435\u043a\u043e\u0434\u0435\u0440\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0432 \u0441\u043b\u0430\u0431\u0443\u044e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u043c\u0438 \u0442\u0438\u043f\u0430\u043c\u0438 \u0444\u043e\u0440\u043c\u0430\u0442\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e DataTransformer, \u0430 \u0438\u043c\u0435\u043d\u043d\u043e \u0434\u043b\u044f JSON:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\tfunc encode&lt;T&gt;(_ object: T) async throws -&gt; Data where T : Encodable {\n    \t\tlet data = try JSONEncoder().encode(object)\n    \t\treturn data\n\t}\n    \n\tfunc decode&lt;T&gt;(data: Data) async throws -&gt; T where T : Decodable {\n    \t\tlet item: T = try JSONDecoder().decode(T.self, from: data)\n    \t\treturn item\n\t}\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u0410 \u0442\u0430\u043a \u043c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e?<\/p>\n<p>\u0427\u0442\u043e \u0436\u0435 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c? \u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u043b\u044e\u0431\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043c\u043f\u043b\u0435\u043c\u0435\u043d\u0442\u0438\u0440\u0443\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b Codable, \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0438\u0441\u0447\u0435\u0437\u0430\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u0432 \u0434\u0443\u0431\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043a\u043e\u0434\u0430, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442\u0441\u044f \u0441\u043b\u0430\u0431\u0430\u044f \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f.<\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 CRUD \u0441 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u043c, \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0441\u0442\u0443\u043f\u0430\u0435\u0442 UserDefaults, \u0444\u043e\u0440\u043c\u0430\u0442 \u0434\u0430\u043d\u043d\u044b\u0445 JSON, \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 Client, \u0442\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u043c\u0435\u0440 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0441\u0447\u0438\u0442\u044b\u0432\u0430\u043d\u0438\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u0430:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nprint(\"One item access example\")\n\ndo {\n\tlet clientRecordIdentifier = \"client\"\n\tlet clientOne = Client(name: \"Chill Client\")\n\tlet repository = UserDefaultsRepository(\n    \ttableName: \"Clients Database\",\n    \tdataTransformer: JSONDataTransformer()\n\t)\n\ttry await repository.create(id: clientRecordIdentifier, item: clientOne)\n\tvar clientRecord: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(\"Client Name: \\(clientRecord.name)\")\n\tclientRecord.name = \"Busy Client\"\n\ttry await repository.update(id: clientRecordIdentifier, item: clientRecord)\n\tlet updatedClient: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(\"Updated Client Name: \\(updatedClient.name)\")\n\ttry await repository.delete(id: clientRecordIdentifier)\n\tlet removedClientRecord: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(removedClientRecord)\n}\ncatch {\n\tprint(error.localizedDescription)\n}\n\nprint(\"Array access example\")\n\nlet clientArrayRecordIdentifier = \"clientArray\"\nlet clientOne = Client(name: \"Chill Client\")\nlet repository = UserDefaultsRepository(\n\ttableName: \"Clients Database\",\n\tdataTransformer: JSONDataTransformer()\n)\nlet array = [clientOne]\ntry await repository.create(id: clientArrayRecordIdentifier, item: array)\nlet savedArray: [Client] = try await repository.read(id: clientArrayRecordIdentifier)\nprint(savedArray.first!)\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0435 CRUD \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f, \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0447\u0442\u0435\u043d\u0438\u0435 \u0443\u0434\u0430\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0430\u0439\u0442\u0435\u043c\u0430 \u0431\u0443\u0434\u0435\u0442 \u0443\u0436\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u044f \u043f\u043e\u043a\u0430\u0436\u0443 \u043a\u0430\u043a \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0442\u0435\u043a\u0443\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 \u0434\u0440\u0443\u0433\u0443\u044e \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u0414\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0443 \u043a\u043e\u0434 \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f SQLite \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u043b ChatGPT:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nclass SQLiteRepository: CRUDRepository {\n    private typealias RecordIdentifier = String\n    \n    let tableName: String\n    let dataTransformer: DataTransformer\n    private var db: OpaquePointer?\n\n    init(\n   \t tableName: String,\n   \t dataTransformer: DataTransformer = JSONDataTransformer()\n    ) {\n   \t self.tableName = tableName\n   \t self.dataTransformer = dataTransformer\n   \t self.db = openDatabase()\n   \t createTableIfNeeded()\n    }\n    \n    private func openDatabase() -&gt; OpaquePointer? {\n   \t var db: OpaquePointer? = nil\n   \t let fileURL = try! FileManager.default\n   \t\t .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)\n   \t\t .appendingPathComponent(\"\\(tableName).sqlite\")\n   \t if sqlite3_open(fileURL.path, &amp;db) != SQLITE_OK {\n   \t\t print(\"error opening database\")\n   \t\t return nil\n   \t }\n   \t return db\n    }\n    \n    private func createTableIfNeeded() {\n   \t let createTableString = \"\"\"\n   \t CREATE TABLE IF NOT EXISTS \\(tableName) (\n   \t id TEXT PRIMARY KEY NOT NULL,\n   \t data BLOB NOT NULL\n   \t );\n   \t \"\"\"\n   \t var createTableStatement: OpaquePointer? = nil\n   \t if sqlite3_prepare_v2(db, createTableString, -1, &amp;createTableStatement, nil) == SQLITE_OK {\n   \t\t if sqlite3_step(createTableStatement) == SQLITE_DONE {\n       \t\t print(\"\\(tableName) table created.\")\n   \t\t } else {\n       \t\t print(\"\\(tableName) table could not be created.\")\n   \t\t }\n   \t } else {\n   \t\t print(\"CREATE TABLE statement could not be prepared.\")\n   \t }\n   \t sqlite3_finalize(createTableStatement)\n    }\n    \n    private func isExists(id: CRUDRepository.ItemIdentifier) async throws -&gt; Bool {\n   \t let queryStatementString = \"SELECT data FROM \\(tableName) WHERE id = ?;\"\n   \t var queryStatement: OpaquePointer? = nil\n   \t if sqlite3_prepare_v2(db, queryStatementString, -1, &amp;queryStatement, nil) == SQLITE_OK {\n   \t\t sqlite3_bind_text(queryStatement, 1, id, -1, nil)\n   \t\t if sqlite3_step(queryStatement) == SQLITE_ROW {\n       \t\t sqlite3_finalize(queryStatement)\n       \t\t return true\n   \t\t } else {\n       \t\t sqlite3_finalize(queryStatement)\n       \t\t return false\n   \t\t }\n   \t } else {\n   \t\t print(\"SELECT statement could not be prepared.\")\n   \t\t throw CRUDRepositoryError.databaseError\n   \t }\n    }\n    \n    func create&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws {\n   \t let insertStatementString = \"INSERT INTO \\(tableName) (id, data) VALUES (?, ?);\"\n   \t var insertStatement: OpaquePointer? = nil\n   \t if sqlite3_prepare_v2(db, insertStatementString, -1, &amp;insertStatement, nil) == SQLITE_OK {\n   \t\t let data = try await dataTransformer.encode(item)\n   \t\t sqlite3_bind_text(insertStatement, 1, id, -1, nil)\n   \t\t sqlite3_bind_blob(insertStatement, 2, (data as NSData).bytes, Int32(data.count), nil)\n   \t\t if sqlite3_step(insertStatement) == SQLITE_DONE {\n       \t\t print(\"Successfully inserted row.\")\n   \t\t } else {\n       \t\t print(\"Could not insert row.\")\n       \t\t throw CRUDRepositoryError.databaseError\n   \t\t }\n   \t } else {\n   \t\t print(\"INSERT statement could not be prepared.\")\n   \t\t throw CRUDRepositoryError.databaseError\n   \t }\n   \t sqlite3_finalize(insertStatement)\n    }\n    \n    func read&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier) async throws -&gt; T {\n   \t let queryStatementString = \"SELECT data FROM \\(tableName) WHERE id = ?;\"\n   \t var queryStatement: OpaquePointer? = nil\n   \t var item: T?\n   \t if sqlite3_prepare_v2(db, queryStatementString, -1, &amp;queryStatement, nil) == SQLITE_OK {\n   \t\t sqlite3_bind_text(queryStatement, 1, id, -1, nil)\n   \t\t if sqlite3_step(queryStatement) == SQLITE_ROW {\n       \t\t let queryResultCol1 = sqlite3_column_blob(queryStatement, 0)\n       \t\t let queryResultCol1Length = sqlite3_column_bytes(queryStatement, 0)\n       \t\t let data = Data(bytes: queryResultCol1, count: Int(queryResultCol1Length))\n       \t\t item = try await dataTransformer.decode(data: data)\n   \t\t } else {\n       \t\t throw CRUDRepositoryError.recordNotFound(id: id)\n   \t\t }\n   \t } else {\n   \t\t print(\"SELECT statement could not be prepared\")\n   \t\t throw CRUDRepositoryError.databaseError\n   \t }\n   \t sqlite3_finalize(queryStatement)\n   \t return item!\n    }\n    \n    func update&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws {\n   \t guard try await isExists(id: id) else {\n   \t\t throw CRUDRepositoryError.recordNotFound(id: id)\n   \t }\n   \t let updateStatementString = \"UPDATE \\(tableName) SET data = ? WHERE id = ?;\"\n   \t var updateStatement: OpaquePointer? = nil\n   \t if sqlite3_prepare_v2(db, updateStatementString, -1, &amp;updateStatement, nil) == SQLITE_OK {\n   \t\t let data = try await dataTransformer.encode(item)\n   \t\t sqlite3_bind_blob(updateStatement, 1, (data as NSData).bytes, Int32(data.count), nil)\n   \t\t sqlite3_bind_text(updateStatement, 2, id, -1, nil)\n   \t\t if sqlite3_step(updateStatement) == SQLITE_DONE {\n       \t\t print(\"Successfully updated row.\")\n   \t\t } else {\n       \t\t print(\"Could not update row.\")\n       \t\t throw CRUDRepositoryError.databaseError\n   \t\t }\n   \t } else {\n   \t\t print(\"UPDATE statement could not be prepared.\")\n   \t\t throw CRUDRepositoryError.databaseError\n   \t }\n   \t sqlite3_finalize(updateStatement)\n    }\n    \n    func delete(id: CRUDRepository.ItemIdentifier) async throws {\n   \t guard try await isExists(id: id) else {\n   \t\t throw CRUDRepositoryError.recordNotFound(id: id)\n   \t }\n   \t let deleteStatementString = \"DELETE FROM \\(tableName) WHERE id = ?;\"\n   \t var deleteStatement: OpaquePointer? = nil\n   \t if sqlite3_prepare_v2(db, deleteStatementString, -1, &amp;deleteStatement, nil) == SQLITE_OK {\n   \t\t sqlite3_bind_text(deleteStatement, 1, id, -1, nil)\n   \t\t if sqlite3_step(deleteStatement) == SQLITE_DONE {\n       \t\t print(\"Successfully deleted row.\")\n   \t\t } else {\n       \t\t print(\"Could not delete row.\")\n       \t\t throw CRUDRepositoryError.databaseError\n   \t\t }\n   \t } else {\n   \t\t print(\"DELETE statement could not be prepared.\")\n   \t\t throw CRUDRepositoryError.databaseError\n   \t }\n   \t sqlite3_finalize(deleteStatement)\n    }\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u0418\u043b\u0438 \u043a\u043e\u0434 CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u044f \u0434\u043b\u044f \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0442\u043e\u0436\u0435 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u043b\u0430 ChatGPT:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nclass FileSystemRepository: CRUDRepository {\n\tprivate typealias RecordIdentifier = String\n    \n\tlet directoryName: String\n\tlet dataTransformer: DataTransformer\n\tprivate let fileManager = FileManager.default\n\tprivate var directoryURL: URL\n    \n\tinit(\n    \tdirectoryName: String = \"Database\",\n    \tdataTransformer: DataTransformer = JSONDataTransformer()\n\t) {\n    \tself.directoryName = directoryName\n    \tself.dataTransformer = dataTransformer\n   \t \n    \tlet paths = fileManager.urls(for: .documentDirectory, in: .userDomainMask)\n    \tdirectoryURL = paths.first!.appendingPathComponent(directoryName)\n   \t \n    \tif !fileManager.fileExists(atPath: directoryURL.path) {\n        \ttry? fileManager.createDirectory(at: directoryURL, withIntermediateDirectories: true, attributes: nil)\n    \t}\n\t}\n    \n\tprivate func fileURL(id: CRUDRepository.ItemIdentifier) -&gt; URL {\n    \treturn directoryURL.appendingPathComponent(\"item_\\(id).json\")\n\t}\n    \n\tprivate func isExists(id: CRUDRepository.ItemIdentifier) async throws -&gt; Bool {\n    \treturn fileManager.fileExists(atPath: fileURL(id: id).path)\n\t}\n    \n\tfunc create&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws {\n    \tlet data = try await dataTransformer.encode(item)\n    \tlet url = fileURL(id: id)\n    \ttry data.write(to: url)\n\t}\n    \n\tfunc read&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier) async throws -&gt; T {\n    \tlet url = fileURL(id: id)\n    \tguard let data = fileManager.contents(atPath: url.path) else {\n        \tthrow CRUDRepositoryError.recordNotFound(id: id)\n    \t}\n    \tlet item: T = try await dataTransformer.decode(data: data)\n    \treturn item\n\t}\n    \n\tfunc update&lt;T: CRUDRepository.Item&gt;(id: CRUDRepository.ItemIdentifier, item: T) async throws {\n    \tguard try await isExists(id: id) else {\n        \tthrow CRUDRepositoryError.recordNotFound(id: id)\n    \t}\n    \tlet data = try await dataTransformer.encode(item)\n    \tlet url = fileURL(id: id)\n    \ttry data.write(to: url)\n\t}\n    \n\tfunc delete(id: CRUDRepository.ItemIdentifier) async throws {\n    \tguard try await isExists(id: id) else {\n        \tthrow CRUDRepositoryError.recordNotFound(id: id)\n    \t}\n    \tlet url = fileURL(id: id)\n    \ttry fileManager.removeItem(at: url)\n\t}\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439 \u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u043c \u043a\u043e\u0434\u0435:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nprint(\"One item access example\")\n\ndo {\n\tlet clientRecordIdentifier = \"client\"\n\tlet clientOne = Client(name: \"Chill Client\")\n\tlet repository = FileSystemRepository(\n    \tdirectoryName: \"Clients Database\",\n    \tdataTransformer: JSONDataTransformer()\n\t)\n\ttry await repository.create(id: clientRecordIdentifier, item: clientOne)\n\tvar clientRecord: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(\"Client Name: \\(clientRecord.name)\")\n\tclientRecord.name = \"Busy Client\"\n\ttry await repository.update(id: clientRecordIdentifier, item: clientRecord)\n\tlet updatedClient: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(\"Updated Client Name: \\(updatedClient.name)\")\n\ttry await repository.delete(id: clientRecordIdentifier)\n\tlet removedClientRecord: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(removedClientRecord)\n}\ncatch {\n\tprint(error.localizedDescription)\n}\n\nprint(\"Array access example\")\n\nlet clientArrayRecordIdentifier = \"clientArray\"\nlet clientOne = Client(name: \"Chill Client\")\nlet repository = FileSystemRepository(\n\tdirectoryName: \"Clients Database\",\n\tdataTransformer: JSONDataTransformer()\n)\nlet array = [clientOne]\ntry await repository.create(id: clientArrayRecordIdentifier, item: array)\nlet savedArray: [Client] = try await repository.read(id: clientArrayRecordIdentifier)\nprint(savedArray.first!)\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u0418\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f UserDefaultsRepository \u0437\u0430\u043c\u0435\u043d\u0435\u043d\u0430 \u043d\u0430 FileSystemRepository, \u0441 \u0441\u043e\u043e\u0442\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u043c\u0438 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438.<br \/>\u041f\u043e\u0441\u043b\u0435 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0433\u043e \u043a\u043e\u0434\u0430, \u0432\u044b \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0438\u0442\u0435 \u0432 \u043f\u0430\u043f\u043a\u0435 \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043e\u0432 \u0434\u0438\u0440\u0435\u043a\u0442\u043e\u0440\u0438\u044e \u201cClients Database\u201d, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0432 \u0441\u0435\u0431\u0435 \u0444\u0430\u0439\u043b \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0432 JSON \u043c\u0430\u0441\u0441\u0438\u0432\u0430 \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u043e\u0439 Client.<\/p>\n<p>\u041f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0444\u043e\u0440\u043c\u0430\u0442 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043f\u0440\u043e\u0441\u0438\u043c ChatGPT \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0442\u044c \u044d\u043d\u043a\u043e\u0434\u0435\u0440 \u0438 \u0434\u0435\u043a\u043e\u0434\u0435\u0440 \u0434\u043b\u044f XML:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\tlet formatExtension = \"xml\"\n    \n\tfunc encode&lt;T: Encodable&gt;(_ item: T) async throws -&gt; Data {\n    \tlet encoder = PropertyListEncoder()\n    \tencoder.outputFormat = .xml\n    \treturn try encoder.encode(item)\n\t}\n    \n\tfunc decode&lt;T: Decodable&gt;(data: Data) async throws -&gt; T {\n    \tlet decoder = PropertyListDecoder()\n    \treturn try decoder.decode(T.self, from: data)\n\t}\n}\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u0411\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u043c \u0442\u0438\u043f\u0430\u043c \u0432 Swift, \u0437\u0430\u0434\u0430\u0447\u0430 \u0434\u043b\u044f \u043d\u0435\u0439\u0440\u043e\u0441\u0435\u0442\u0438 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u044d\u043b\u0435\u043c\u0435\u043d\u0442\u0430\u0440\u043d\u043e\u0439.<\/p>\n<p>\u0417\u0430\u043c\u0435\u043d\u044f\u0435\u043c JSON \u043d\u0430 XML \u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u043c \u043a\u043e\u0434\u0435:<\/p>\n<div class=\"hcb_wrap\">\n<div class=\"hcb_wrap\">\n<pre class=\"prism line-numbers lang-unknown\" data-lang=\"unknown\"><code>\nprint(\"One item access example\")\n\ndo {\n\tlet clientRecordIdentifier = \"client\"\n\tlet clientOne = Client(name: \"Chill Client\")\n\tlet repository = FileSystemRepository(\n    \tdirectoryName: \"Clients Database\",\n    \tdataTransformer: XMLDataTransformer()\n\t)\n\ttry await repository.create(id: clientRecordIdentifier, item: clientOne)\n\tvar clientRecord: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(\"Client Name: \\(clientRecord.name)\")\n\tclientRecord.name = \"Busy Client\"\n\ttry await repository.update(id: clientRecordIdentifier, item: clientRecord)\n\tlet updatedClient: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(\"Updated Client Name: \\(updatedClient.name)\")\n\ttry await repository.delete(id: clientRecordIdentifier)\n\tlet removedClientRecord: Client = try await repository.read(id: clientRecordIdentifier)\n\tprint(removedClientRecord)\n}\ncatch {\n\tprint(error.localizedDescription)\n}\n\nprint(\"Array access example\")\n\nlet clientArrayRecordIdentifier = \"clientArray\"\nlet clientOne = Client(name: \"Chill Client\")\nlet repository = FileSystemRepository(\n\tdirectoryName: \"Clients Database\",\n\tdataTransformer: XMLDataTransformer()\n)\nlet array = [clientOne]\ntry await repository.create(id: clientArrayRecordIdentifier, item: array)\nlet savedArray: [Client] = try await repository.read(id: clientArrayRecordIdentifier)\nprint(savedArray.first!)\n<\/code><\/pre>\n<\/div>\n<\/div>\n<p>\u041a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u0438\u0439 \u043a\u043e\u0434 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0430 \u043e\u0434\u043d\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 JSONDataTransformer -&gt; XMLDataTransformer<\/p>\n<p>\u0418\u0442\u043e\u0433<\/p>\n<p>CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0438 \u043e\u0434\u0438\u043d \u0438\u0437 \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u043e\u0432 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u043b\u0430\u0431\u043e\u0439 \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u043e\u0441\u0442\u0438 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u0415\u0449\u0435 \u043e\u0434\u043d\u043e \u0438\u0437 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 &#8211; \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 ORM (\u041e\u0431\u044a\u0435\u043a\u0442\u043d\u043e-\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u043c\u0430\u043f\u043f\u0438\u043d\u0433), \u0435\u0441\u043b\u0438 \u0432\u043a\u0440\u0430\u0442\u0446\u0435 \u0442\u043e \u0432 \u041e\u0420\u041c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0445\u043e\u0434 \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u043c\u0430\u043f\u044f\u0442\u0441\u044f \u043d\u0430 \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445, \u0438 \u0437\u0430\u0442\u0435\u043c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441 \u043c\u043e\u0434\u0435\u043b\u044f\u043c\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0430\u0442\u044c\u0441\u044f (\u043c\u0430\u043f\u043f\u0438\u0442\u044c\u0441\u044f(!)) \u043d\u0430 \u0431\u0434.<br \/>\u041d\u043e \u044d\u0442\u043e \u0443\u0436\u0435 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u0430\u044f \u0438\u0441\u0442\u043e\u0440\u0438\u044f.<\/p>\n<p>\u041f\u043e\u043b\u043d\u0430\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0435\u0432 CRUD \u0434\u043b\u044f Swift \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430 \u043f\u043e \u0441\u0441\u044b\u043b\u043a\u0435:<br \/><a href=\"https:\/\/gitlab.com\/demensdeum\/crud-example\" rel=\"noopener\" target=\"_blank\">https:\/\/gitlab.com\/demensdeum\/crud-example<\/a><\/p>\n<p>\u041a\u0441\u0442\u0430\u0442\u0438 Swift \u0434\u0430\u0432\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0432\u043d\u0435 macOS, \u043a\u043e\u0434 \u0438\u0437 \u0441\u0442\u0430\u0442\u044c\u0438 \u0431\u044b\u043b \u043f\u043e\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0430\u043f\u0438\u0441\u0430\u043d \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d \u043d\u0430 Arch Linux.<\/p>\n<p>\u0418\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438<\/p>\n<p><a href=\"https:\/\/developer.apple.com\/documentation\/combine\/topleveldecoder\" rel=\"noopener\" target=\"_blank\">https:\/\/developer.apple.com\/documentation\/combine\/topleveldecoder<\/a><br \/><a href=\"https:\/\/developer.apple.com\/documentation\/combine\/toplevelencoder\" rel=\"noopener\" target=\"_blank\">https:\/\/developer.apple.com\/documentation\/combine\/toplevelencoder<\/a><br \/>\n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Create,_read,_update_and_delete\" rel=\"noopener\" target=\"_blank\">https:\/\/en.wikipedia.org\/wiki\/Create,_read,_update_and_delete<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u043c\u0435\u0442\u043a\u0435 \u044f \u043e\u043f\u0438\u0448\u0443 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u044b \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u043f\u0430\u0442\u0442\u0435\u0440\u043d\u0430 CRUD, \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 Swift. Swift \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u043a\u0440\u044b\u0442\u044b\u043c, \u043a\u0440\u043e\u0441\u0441\u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u0435\u043d\u043d\u044b\u043c \u044f\u0437\u044b\u043a\u043e\u043c, \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u043c \u0434\u043b\u044f \u041e\u0421 Windows, Linux, macOS, iOS, Android. \u0421\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u0435\u0442 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0430\u0431\u0441\u0442\u0440\u0430\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u043b\u043e\u0433\u0438\u043a\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f. \u041e\u0434\u043d\u0438\u043c \u0438\u0437 \u0442\u0430\u043a\u0438\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u0445\u043e\u0434 CRUD, \u044d\u0442\u043e \u0430\u043a\u0440\u043e\u043d\u0438\u043c \u043e\u0442 C &#8211; Create, R -Read, U &#8211; Update,<a class=\"more-link\" href=\"https:\/\/demensdeum.com\/blog\/ru\/2024\/05\/28\/crud-repository\/\">Continue reading <span class=\"screen-reader-text\">&#8220;CRUD \u0440\u0435\u043f\u043e\u0437\u0438\u0442\u043e\u0440\u0438\u0439&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[61],"tags":[224,223,225],"class_list":["post-3522","post","type-post","status-publish","format-standard","hentry","category-techie","tag-crud","tag-swift","tag-225","entry"],"translation":{"provider":"WPGlobus","version":"3.0.2","language":"ru","enabled_languages":["en","ru","zh","de","fr","ja","pt"],"languages":{"en":{"title":true,"content":true,"excerpt":false},"ru":{"title":true,"content":true,"excerpt":false},"zh":{"title":true,"content":true,"excerpt":false},"de":{"title":true,"content":true,"excerpt":false},"fr":{"title":true,"content":true,"excerpt":false},"ja":{"title":true,"content":true,"excerpt":false},"pt":{"title":true,"content":true,"excerpt":false}}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/posts\/3522","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/comments?post=3522"}],"version-history":[{"count":33,"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/posts\/3522\/revisions"}],"predecessor-version":[{"id":3867,"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/posts\/3522\/revisions\/3867"}],"wp:attachment":[{"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/media?parent=3522"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/categories?post=3522"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demensdeum.com\/blog\/ru\/wp-json\/wp\/v2\/tags?post=3522"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}