Connect with us

Программирование

Протокол Identifiable в SwiftUI с примерами

Хотя этот протокол выглядит простым и имеет всего одно свойство, в нем легко допустить распространенную ошибку, которая может привести к неожиданному поведению вашего представления.

Фото аватара

Опубликовано

/

     
     

Протокол Identifiable в SwiftUI позволяет добавить уникальную идентификацию объекта. Протокол требует единственного свойства ID любого хэшируемого типа, что делает его гибким протоколом для любых экземпляров.

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

Приведение объекта в соответствие с Identifiable

Создавая новые экземпляры (инстансы) в Swift, вы, скорее всего, не думаете о том, чтобы сразу добавить соответствие протоколу Identifiable. Чаще всего вы сталкиваетесь с ошибками сборки, связанными с SwiftUI, такими как:

Ссылка на инициализатор ‘init(_:content:)’ в ‘ForEach’ требует, чтобы ‘Article’ соответствовал ‘Identifiable’.

Эта ошибка сборки возникает, когда вы используете неидентифицируемую коллекцию объектов внутри элемента ForEach:

Протокол Identifiable в SwiftUI с примерами

Объекты должны быть идентифицируемыми, чтобы выполнять итерации по коллекции с помощью ForEach.

SwiftUI требует идентификации для каждого объекта, поскольку иначе он не смог бы определить, нужно ли перерисовывать представление после изменения коллекции. Другими словами, добавление идентификации влияет на поведение ваших представлений.

Мы можем продемонстрировать это, добавив соответствие протоколу Identifiable в структуру статьи:

struct Article {
    let title: String
    let url: URL
}

extension Article: Identifiable {
    var id: String {
        url.absoluteString
    }
}

На первый взгляд, этот код кажется вполне нормальным, поскольку мы можем успешно скомпилировать и запустить наш проект. Однако, как только мы встречаем две статьи с одинаковым URL, результирующий вывод становится неожиданным:

Протокол Identifiable в SwiftUI с примерами

Несмотря на то что мы привели структуру статьи в соответствие с Identifiable, просмотр результатов показывает неожиданные результаты.

Хотя обе статьи имеют уникальное название, URL остается неизменным. В представлении результатов дважды отображается один и тот же заголовок, поскольку оно считает, что обе статьи идентичны на основе идентификации. Это показывает, почему следует тщательно добавлять идентификаторы к объектам и проверять, является ли используемый идентификатор уникальным во всех случаях.

В этом примере мы можем правильно добавить поддержку идентификации, введя новое уникальное свойство ID поста:

struct Article {
    let postID: Int
    let title: String
    let url: URL
}

extension Article: Identifiable {
    var id: Int {
        postID
    }
}

Полагание на реализацию по умолчанию для классов

Вы могли заметить, что от вас не требуется добавлять какое-либо свойство ID в классы, которым вы добавили соответствие Identifiable. Протокол Identifiable предоставляет реализацию по умолчанию для типов классов, которые гарантированно остаются уникальными только на время жизни объекта.

Типом идентификатора по умолчанию будет ObjectIdentifier, уникальный идентификатор для экземпляра класса или метатипа. Мы можем продемонстрировать это поведение, создав версию класса для нашей статьи:

class ArticleClass: Identifiable {
    let postID: Int
    let title: String
    let url: URL
    
    init(postID: Int, title: String, url: URL) {
        self.postID = postID
        self.title = title
        self.url = url
    }
}

Добавлять новое свойство ID не требуется, а распечатка реализации по умолчанию показывает что-то вроде:

print("\(articleClass.id)")
/// Prints: ObjectIdentifier(0x0000600000be0810)

Идентификатор равен указателю объекта, поэтому он гарантированно будет уникальным только в течение всего времени жизни объекта.

Примечание: важно понимать, что для статей в этом примере нужно использовать struct. Может показаться, что это решение — изменить все типы на классы, но это не так. Подробнее об этом вы можете узнать из моей статьи “Структуры и классы в Swift: различия”.

Заключение

Протокол Identifiable позволяет выполнять итерации по коллекции объектов внутри ForEach в SwiftUI. Хотя этот протокол выглядит простым и имеет всего одно свойство, в нем легко допустить распространенную ошибку, которая может привести к неожиданному поведению вашего представления. Классы могут полагаться на реализацию по умолчанию, но не стоит превращать все свои структуры в классы только для того, чтобы они соответствовали Identifiable.

Спасибо!

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Advertisement

Наши партнеры:

LEGALBET

Мобильные приложения для ставок на спорт
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: