SWIFTER | Блог про Swift
274 subscribers
4 photos
30 links
Swift для каждого на простом и понятном языке. Уроки программирования с интересными кейсами из реальных проектов, без воды и сложных терминов.
Download Telegram
Как декодировать property list используя Decodable?

Property list
, обычно сокращенно plist, представляет собой XML-файл, содержащий данные в формате "ключ-значение". Вы можете использовать его в своих приложениях для iOS в качестве простого хранилища данных. Эта функция-утилита позволит вам задекодить данные в нужный удобный вам тип, используя Decodable.

Source
#handyExtensions #plist #basic
Как использовать ключевое слово rethrows?

По моему опыту, использовать это ключевое слово вы будете не слишком часто. Тем не менее, понимание принципов его работы поможет вам лучше определять случаи, когда rethrows будет полезным.

Ключевое слово rethrows используется, когда вы пишете функцию (назовем ее A), которая принимает другую функцию в качестве параметра (назовем ее B). Rethrows делает так, что если функция B выбрасывает ошибки, тогда и A будет выбрасывать ошибки. Если функция B не выбрасывает ошибки, тогда и A этого делать не будет.

Какое преимущество мы получаем? Rethrows позволяет убрать лишние try/catch в случаях, где они не нужны.

Возьмем стандартные 'map', 'filter', 'forEach' для массивов. Когда вы внутри замыкания помечаете что-то как try, Swift просит вас добавить try еще и для вызова "Call can throw but is not marked with 'try'". Если внутри замыкания ничего ошибку выбрасывать не будет, тогда и целый вызов помечать try не нужно.

Данное поведение во всех описанных выше методах реализовано‌‌‎ с помощью rethrows‎.‌‌‎​

Source
#languageGuide #rethrows #advanced
Channel photo updated
Привет, будем знакомиться?👋🏻

Меня зовут Ден Андрейчук, и я – iOS разработчик. Работаю в сфере мобильной разработки на Swift уже 4 года, за это время успел стать senior developer, решить множество сложных задач, реализовать десятки проектов и набраться опыта.

Пришло время полученным опытом делиться. В этом телеграм-канале вы сможете найти ответы на ваши многочисленные вопросы о программировании на Swift, получите полезные советы для более эффективного написания кода, а также узнаете о:

– здоровом программировании;
– правильном планировании рабочего времени;
– работе на open-source;
– продвижении разработчика по карьерной лестнице;
– важности грамотно написанного резюме;
– использовании техники помодоро и йоги и многом другом.

Оставайтесь со мной, будет познавательно! 😉

Instagram
LinkedIn
Github
Telegram
Как использовать String в качестве ошибок?

Обычно, чтобы сообщать о том, что операция завершилась с ошибкой, в Swift используется протокол Error. Когда мы проектируем чистое API, обычной практикой для выполнения данной цели является создание собственного error enum, в котором прописываются нужные варианты ошибок под конкретный функционал.

Но что делать, если мы хотим получить простое решение для случаев, когда ошибки единичные и смысла создавать отдельный enum нет?

Тогда можно реализовать LocalizedError для String и использовать строку в качестве ошибки. Такой вариант идеально подойдет для возвращение простых, user-facing ошибок.

Source
#handyExtensions #error #basic
Как легко cделать глубокую копию (deep-copy) объекта в Swift?

В Swift есть два основных типа данных: объекты (reference types) и структуры (value types). Одно из ключевых различий между value и reference типами сводится к копированию: две переменные могут указывать на один и тот же объект, поэтому если вы попытаетесь изменить одну переменную, изменения коснутся и второй. Если вы попытаетесь проделать этот же трюк со структурами, то обнаружите, что здесь изменения копии не влияют на оригинал.

Теперь вопрос: а как сделать так, чтобы изменение в одной части проекта не влияло на другие в reference типах? Для этого нам нужно сделать глубокую копию (deep-copy) объекта. Одним из вариантов решения является использование протокола NSCopying. И хотя этот способ имеет место быть, он создает много шаблонного (boilerplate) кода.

Сегодня я хочу показать вам, как для решения этой задачи можно использовать Codable. Идея достаточно простая: сначала мы кодируем объект в Data, а дальше из Data в нужный нам тип. Поскольку Data является value типом в Swift, при копировании выполняется deep-copy по умолчанию. На выходе мы получим новый объект с теми же данными, что и оригинал.

Ссылка
#tips #codable #intermediate
Как копировать текст в буфер обмена, используя UIPasteboard?

Вы можете писать в буфер обмена iOS и читать из него с помощью класса UIPasteboard. Для того, чтобы воспользоваться глобальным системным буфером, нужно использовать константу general. Это позволит обмениваться данными между всеми приложениями. Обычно пользователи взаимодействуют с системным буфером, используя "вырезать", "скопировать", "вставить" на выбранном контенте в UI.

В UIPasteboard можно хранить String, UIImage, URL, UIColors, но чаще всего вы будете использовать именно String. Чтобы записать или прочитать строку, достаточно просто считать или присвоить что-то переменной string.

Ссылка
#tips #pasteboard #basic
Что нового в Xcode 13?

▪️Новый вид значка у файлов в навигационной панели и отсутствие расширения по умолчанию.

▪️Распознавание типа данных и автоматический импорт нужной библиотеки.

▪️Масштабное обновление функционала Git: возможность сравнивать изменения, открывать pull request, выполнять код-ревью и приглашать ревьюеров.

▪️Автоматическое заполнение всех кейсов перечисления при использовании switch, автозаполнение массивов.

▪️Автозаполнение при использовании привязки для опционалов (if let).

▪️ Интеграция Xcode Cloud и поддержка разметки документации DocC, клавиатуры Vim.

▪️Возможность поставить breakpoint в любом месте одной строчки кода (column breakpoint).

▪️Новый способ отображения ошибок с помощью минимизированного режима.

#news #xcode
Взаимозаменяемое использование типов CGFloat и Double

SE-0307 в Swift 5.5 добавляет небольшое, но тем не менее очень полезное нововведение: компилятор будет автоматически уметь конвертировать между CGFloat и Double там где это нужно. Это значит, что мы сможем выполнять такие операции как умножение и деление без приведение типов.

Swift будет всегда отдавать предпочтение Double, чтобы предотвратить потерю точности. Более того, все описанное выше реализовано путем неявного использование нужного инициализатора для конвертации. Это значит, что это нововведение не меняет никакое с существующих API.

Source
#tips #core #basic
Привет, СВИФТЕРЫ👋🏻

Врываемся в ваше воскресенье с крутой новостью! Теперь на нашем канале доступны комментарии к постам.

Задавайте любые вопросы, пишите пожелания к контенту, общайтесь между собой и учите Swift вместе😉

Ну что, пообщаемся?
Как добавить Pull-to-Refresh в UITableView или UICollectionView?

Swift предоставляет нам готовый функционал для этой цели, который реализован с помощью класса UIRefreshControl. Любой наследник UIScrollView имеет свойство refreshControl, а поскольку UITableView и UICollectionView как раз являются наследниками, нам достаточно присвоить экземпляр UIRefreshControl этому свойству.

Если вы хотите получить что-то более уникальное, например добавить свою анимацию, тогда можно обратить внимание на библиотеки как CRRefresh. Правда, по моему опыту, все они работают плохо и имеют те или иные проблемы.

Source
#languageGuide #UIRefreshControl #basic
Используем String в качестве SectionIdentifierType для UITableViewDiffableDataSource

UITableViewDiffableDataSource предоставляет абсолютно новое API для работы с данными таблицы. Если вы уже имеете опыт использования, то знаете, что нам нужно предоставить два дженерика: SectionIdentifierType, ItemIdentifierType.

В качестве ItemIdentifierType обычно выступает модель, которую мы планируем отображать в таблице. SectionIdentifierType же, как следует из названия, описывает секции нашей таблицы. Классическим подходом будет использование отдельного enum для этих задач, если секций несколько. Тем не менее, если мы имеем дело только с одной, то таким образом создадим ненужный шаблонный (boilerplate) код.

Поскольку строки в Swift Hashable по умолчанию, можно использовать String в качестве SectionIdentifierType.

Source
#tips #tableView #intermediate
Как удалить десятичную дробь из числа с плавающей запятой, если она равна 0?

Это простое расширение убирает десятичную дробь из числа с плавающей запятой, если она равна 0. Это пригодится в тех случаях, когда нам нужно сделать красивый вывод числа где-то в пользовательском интерфейсе. Мы используем truncatingRemainder (тот же %), чтобы найти остаток от деления. Если оно равно нулю, то убираем плавающую точку, форматируя строку в виде "%.0f", в противном же случае просто конвертируем Double в String без каких-либо изменений.

Source
#handyExtensions #double #basic
Привет, свифтеры🙂

Сегодня мы вводим на канал новую рубрику #MockInterview, которая даст вам возможность потренироваться отвечать на технические вопросы и даже подготовит к предстоящим собеседованиям.

В этой рубрике мы будем задавать вам вопросы, которые касаются программирования на Swift, чтобы вы в процессе ответа вспомнили давно известную вам информацию, а также могли узнать много нового.

Естественно, мы тоже будем отвечать на заданные вопросы и объясним, почему ответы именно такие. Но постарайтесь не подглядывать в ответ сразу, сначала поразмыслите над вопросом сами😉
#MockInterview

Вопрос: Можно ли получить доступ к private свойству внутри extension? 💬

Ответ:
Да, мы можем получить доступ к private свойству внутри extension, но только при условии, что это extension находится внутри одного и того же файла, что и class, struct или enum. Если мы попытаемся расширить тип данных за пределами файла, private свойства доступны не будут.

Объяснение: Расширения, которые находятся в том же файле, что и class, struct или enum, которые они расширяют, ведут себя так, как если бы код в extension был написан как часть самого исходного типа.

В результате мы можем:
- Объявить private свойство в самом типе и достучаться к этому свойству из расширений в том же файле.
- Объявить private свойство в одном расширении и получите доступ к этому свойству из другого расширения в том же файле.
- Объявить private свойство в расширении и получите доступ к этому свойству из самого типа в том же файле.

#accessControl #basic
lazy теперь работает в локальном контексте (local context)

Используя ключевое слово lazy, мы можем реализовать свойство, начальное значение которого не вычисляется до первого использования. Начиная со Swift 5.5, можно использовать lazy внутри функций. На практике это позволит проводить оптимизацию, когда мы имеем какое-то условия if-else и не хотим проводить затратные вычисления на то, что нам не нужно.

Source
#languageGuide #lazy #intermediate
Как определить, включен ли у пользователя режим энергосбережения?

Когда пользователь включает режим энергосбережения, ваш код должен избегать слишком энергозатратных действий. Например, вы хотите выполнить какую-то миграцию или синхронизацию с облаком, но откладываете её на определенное время, чтобы не нагружать батарею.

Существует два подхода к проверке подключения режима энергосбережения: получить информацию из переменной isLowPowerModeEnabled напрямую или подписаться на изменения подключения, используя NotificationCenter.

Source
#tips #lowPowerMode #basic
Typealiases с дженериками

Мало кто использует эту особенность Swift в своих проектах. Однако она может здорово улучшить некоторые участки кода и убрать ненужный шаблонный (boilerplate) код.

Typealiases могут использоваться в комбинации с generic типами.

Что самое интересное, мы можем явно указать конкретные типы для некоторых (или всех) generic параметров существующего типа. В обратную сторону, кстати, это не работает: новые параметры в typealiase вводить нельзя.

Source
#tips #generics #intermediate
Используем App Group для доступа к Realm из других приложений или расширений

App Group позволяет нескольким приложениям от одного разработчика получить доступ к общему контейнеру, в котором можно хранить и использовать какие-то данные. Поскольку Realm держит базу в файле, мы можем поместить этот файл в общий контейнер и получить доступ к нему из других наших приложений или расширений.

Для этого нужно в конфигурации Realm указать в качестве fileURL ссылку на этот общий контейнер. Получить ее можно, используя:

containerURL(forSecurityApplicationGroupIdentifier:)

Source
#tips #appGroup #advanced
Различия между let и var

Когда в Swift нужно связать имя (например, "username" или "balance") со значением определенного типа (например, строка "Den" или число 96.23), используются константы и переменные.

Чтобы объявить константу, используем ключевое слово let, для переменной – var. Изменить значение константы после того, как мы ее объявили, нельзя, переменную же мы можем менять сколько угодно раз.

На скриншоте видим:

maxPasswordLenght – константа со значением 64, поскольку максимальная длина пароля в приложении фиксированная, и менять ее мы не будем;

currentPasswordLenght – переменная, потому что ее значение напрямую зависит от значения, которое пользователь вводит в текстовом поле.

Source
#languageGuide #properties #basic
Друзья, новость для вас❗️

Swifter расширяет свои границы, и теперь у нас есть аккаунт на Medium. Если среди вас есть активные пользователи данной платформы, будем рады взаимодействовать с вами и там🤗

Ссылка на SWIFTER | Блог про Swift в Medium:
https://medium.com/@BlogSwift

А с подписчиками нашего канала, которые верны Telegram, пообщаемся совсем скоро в новом обучающем посте. Ждите)