> Как понять, что файл на сервере изменился при сохранении имени и пути? (iOS, Swift)
Уровень: senior · Роль: mobile · Категория: Технические вопросы
Компании: bnine
Стек: iOS, Swift
> Пример ответа
Короткий ответ
Если имя и путь файла не меняются, но содержимое обновляется, нужно сравнивать метаданные: modification date, file size или content hash. На iOS надёжнее всего использовать FileManager для получения атрибутов (modificationDate, size) и, при необходимости, вычислять hash содержимого. Для постоянного мониторинга - DispatchSourceFileSystemObject с событиями .write или .extend. Важно учитывать кэширование и задержки файловой системы.
Подробное объяснение
Файл на сервере - это абстракция: в мобильном контексте речь обычно идёт о локальной копии, полученной с сервера, либо о файле в sandbox приложения. Если путь и имя неизменны, изменение можно детектировать тремя способами:
- modification date - самый простой и дешёвый. Но дата может не обновиться при записи с тем же размером или при копировании с сохранением атрибутов.
- file size - быстро, но не различает замену содержимого с тем же размером.
- content hash (MD5/SHA) - самый надёжный, но требует чтения всего файла. Для больших файлов - дорого.
На iOS для локального мониторинга изменений используют DispatchSourceFileSystemObject - он слушает события ядра (.write, .extend, .delete, .rename). Это эффективнее polling’а, но требует аккуратного управления жизненным циклом источника.
Для удалённого файла на сервере (HTTP) - задача сводится к сравнению ETag, Last-Modified или Content-Length в заголовках ответа. Если сервер не отдаёт эти заголовки, придётся скачивать файл и сравнивать hash.
Важный нюанс: на iOS файловая система может кэшировать атрибуты, поэтому после записи нужно сбрасывать кэш (FileManager не кэширует, но URLResourceValues могут быть устаревшими). Также стоит учитывать, что modificationDate имеет точность до секунды - при быстрых последовательных записях можно пропустить изменение.
На практике
Для локального файла в приложении:
- Получить атрибуты через
FileManager.attributesOfItem(atPath:). - Сравнить
modificationDateиsizeс сохранёнными значениями. - Если нужна гарантия - вычислить hash (например, SHA256) и сравнить.
- Для непрерывного наблюдения - создать
DispatchSourceFileSystemObjectна дескрипторе файла.
Для удалённого файла:
- Использовать
URLSessionс conditional GET: отправлятьIf-Modified-SinceилиIf-None-Matchи проверять статус304 Not Modified. - Если сервер не поддерживает - скачивать и сравнивать hash.
Типичный сценарий в iOS: приложение хранит кэш файла, и при каждом запуске проверяет, не изменился ли он на сервере. Здесь лучше полагаться на ETag/Last-Modified, а не на локальные атрибуты.
Пример кода
SWIFTimport Foundationfunc fileChanged(atPath path: String,previousDate: Date?,previousSize: Int?) -> Bool {let attrs = try? FileManager.default.attributesOfItem(atPath: path)guard let attrs else { return true }let currentDate = attrs[.modificationDate] as? Datelet currentSize = (attrs[.size] as? NSNumber)?.intValueif let previousDate, let currentDate,let previousSize, let currentSize {return currentDate != previousDate || currentSize != previousSize}return true}// Мониторинг через DispatchSourcefunc watchFile(atPath path: String, onChange: @escaping () -> Void) -> DispatchSourceFileSystemObject? {let fd = open(path, O_EVTONLY)guard fd >= 0 else { return nil }let source = DispatchSource.makeFileSystemObjectSource(fileDescriptor: fd,eventMask: [.write, .extend, .delete, .rename],queue: .main)source.setEventHandler {onChange()}source.setCancelHandler {close(fd)}source.resume()return source}
Как отвечать на собеседовании
Начни с уточнения: "Речь о локальном файле или удалённом?" - это покажет системное мышление. Затем перечисли три подхода (дата, размер, hash) и объясни trade-off между ними. Для локального - упомяни DispatchSourceFileSystemObject, для удалённого - ETag/Last-Modified. Подчеркни, что выбор зависит от требований к надёжности и производительности. Приведи пример, когда дата и размер недостаточны (замена содержимого с тем же размером). Если спросят про кэширование - скажи, что на iOS атрибуты читаются напрямую из файловой системы, но стоит избегать частого чтения больших файлов.
Что проверяет интервьюер
- Понимание разницы между метаданными и содержимым файла.
- Знание механизмов мониторинга файловой системы на iOS.
- Умение оценивать надёжность и стоимость каждого подхода.
- Понимание сетевых протоколов для удалённых файлов (HTTP conditional requests).
- Способность предложить решение под конкретный сценарий, а не универсальный ответ.
Типичные ошибки
- Предложение только сравнивать
modificationDateбез учёта ограничений точности. - Игнорирование случая, когда файл заменяется целиком (rename + write) - событие
.deleteили.renameможет не прийти. - Использование
FileManagerдля постоянного мониторинга через polling - это неэффективно. - Забывают про
O_EVTONLYпри открытии файла для наблюдения - иначе дескриптор блокирует запись. - Для удалённого файла предлагают скачивать целиком каждый раз, не упоминая conditional GET.
- Не учитывают, что hash всего файла - дорогая операция для больших файлов, и предлагают её как единственный вариант.
> Похожие задачи по mobile
Как работает reduce в Swift
В чем разница между actors и менеджером памяти с пулом объектов в Swift?
Что такое диплинкинг в iOS
Что такое паттерн use case
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью