Ответы пользователя по тегу iOS
  • Изучение iOS-разработки и дизайна мобильных приложений. Как быть?

    doublench21
    @doublench21 Куратор тега Swift
    Привет из Ташкента. Дизайн мобильных приложений или таки разработка мобильных приложений? Разные ипостаси.

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

    Просто пойми, что для новичка не имеет никакого смысла бояться выбрать что-то неправильное или потерять время. Ты сейчас изучаешь языки, конструкции, подходы. В конце концов формируешь своё мышление.

    Если ответ на первый вопрос утвердительный и макбук таки будет, то смело скачивай книжку по Swift от Apple. Устанавливай Swift на Linux и начинай приключение в мир нового для тебя языка.
    Ответ написан
  • Интерактивный drag & drop борд?

    doublench21
    @doublench21
    Самый быстрый и рабочий вариант это коллекция с кастомным лайаутом. Коллекция как и таблица поддерживает встроенный механизм drag and drop.

    Если ничего из этого никогда не делали, можете посмотреть последнии доступные лекции от Стэнфорда по iOS. Под конец там реализуют канвас с перетаскиванием. На русском вроде только в текстовом варианте можно найти.
    Ответ написан
  • Как решить проблему с авто размером collection view?

    doublench21
    @doublench21 Куратор тега Swift
    Потому-что, так никто не делает, ну кроме Вас. Для работы auto layout нужно построить цепочку ограничений сверху вниз.

    Что бы не спрашивать что у Вас есть, а что нет, сразу напишу полный список./

    1) Прописать у layout коллекции:
    // ...
    layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    layout.itemSize = UICollectionViewFlowLayout.automaticSize


    2) Соврал, нужно уточнение.

    pronunciationLabel - Сколько строк должен занимать? (Только одну?) Увеличивается только в ширину?
    wordLabel - Тоже, что и pronunciationLabel? Или увеличивается в высоту?

    3) Этот бред больше никогда не нужно делать.

    contentView.translatesAutoresizingMaskIntoConstraints = false
       
            NSLayoutConstraint.activate([
                contentView.leftAnchor.constraint(equalTo: leftAnchor),
                contentView.rightAnchor.constraint(equalTo: rightAnchor),
                contentView.topAnchor.constraint(equalTo: topAnchor),
                contentView.bottomAnchor.constraint(equalTo: bottomAnchor)
            ])


    Уточнение получены. Продолжим.

    Для начала уточним, как нам добиться динамического размера вьюхи в ширину и высоту. Приведу простой и наглядный пример. Создам вьюхи и помещу туда два лейбла. Пишу всё исключительно кодом, т.к. не использую сториборд, но думаю свести проблем не составит. И так:

    5cab4bce2a9a6308684642.png
    Код текстом
    let v = UIView(frame: .zero)
    
        let l1 = UILabel(frame: .zero)
            l1.translatesAutoresizingMaskIntoConstraints = false
            l1.font = .systemFont(ofSize: 27.0)
            l1.text = "asdlas"
    
        v.addSubview(l1)
        NSLayoutConstraint.activate([
          l1.topAnchor.constraint(equalTo: v.topAnchor),
          l1.leadingAnchor.constraint(equalTo: v.leadingAnchor),
        ])
        l1.setContentHuggingPriority(.required, for: .vertical)
        l1.setContentCompressionResistancePriority(.required, for: .vertical)
    
        let trailing = l1.trailingAnchor.constraint(equalTo: v.trailingAnchor)
            trailing.priority = .defaultHigh
        NSLayoutConstraint.activate([
          trailing
        ])
    
        let l2 = UILabel(frame: .zero)
            l2.translatesAutoresizingMaskIntoConstraints = false
            l2.font = .systemFont(ofSize: 17.0)
            l2.text = ""
    
        v.addSubview(l2)
        NSLayoutConstraint.activate([
          l2.topAnchor.constraint(equalTo: l1.bottomAnchor),
          l2.leadingAnchor.constraint(equalTo: v.leadingAnchor),
        ])
        l2.setContentHuggingPriority(.required, for: .vertical)
        l2.setContentCompressionResistancePriority(.required, for: .vertical)
    
        let trailing_ = l2.trailingAnchor.constraint(equalTo: v.trailingAnchor)
            trailing_.priority = .defaultHigh
        let bottom = l2.bottomAnchor.constraint(equalTo: v.bottomAnchor)
            bottom.priority = .defaultHigh
        NSLayoutConstraint.activate([
          trailing_,
          bottom
        ])
    
    
        let s = v.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
    
        view.addSubview(v)
        v.frame.size = s
        v.center = view.center
        v.layer.borderColor = UIColor.red.cgColor
        v.layer.borderWidth = 1.0


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

    С шириной всё готово. Смотрим на костреинты для высоты. Тут вполне обычно, начинаем с топ. После нижний лейбл крепится к боттом первого. И снова небольшая магия. Последний нижний констрейнт снова с пониженным приоритетом. Кстати, быть может в сториборде приоритет снижать не придется. Проверьте. (Кажись система делаем это за вас)

    Если быть точнее снижая приоритет(по крайне мере если задавать их кодом) такой подход даёт понять системе, что высоту и ширину он прямиком и полностью должен расчитывать исходя из высоты и ширины его сабвьюх, а не назначить свои значения.

    Поглядим на примеры:
    Первая имеет меньший размер шрифта, но больше символов.
    HC2w483.png
    Первая имеет больший размер шрифта, но больше символов.
    5MhP2nj.png
    Первая имеет меньший размер шрифта, но меньше символов.
    V00A7Qc.png
    Первая имеет больший размер шрифта, но меньше символов.
    zXH8glH.png

    Как видимо размер вьюхи система посчитала вольностью верным. То есть мы динамически научились задавать высоту и ширину ячейки.

    Поехали дальше.

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

    Воспользуемся методом:
    5cab50033a6e2506454233.png
    Код текстом
    func preferredLayoutAttributesFitting(
        _ layoutAttributes: UICollectionViewLayoutAttributes
      ) -> UICollectionViewLayoutAttributes
      {
        let layoutAttributes = super.preferredLayoutAttributesFitting(layoutAttributes)
    
        let fittingSize = UIView.layoutFittingCompressedSize
    
        layoutAttributes.frame.size = systemLayoutSizeFitting(
          fittingSize,
          withHorizontalFittingPriority: .fittingSizeLevel,
          verticalFittingPriority: .fittingSizeLevel
        )
    
        return layoutAttributes
      }


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

    И малая ремарка, возможно в метод preferredLayoutAttributesFitting после вызова super. надо будет добавить вызов метода layoutIfNeeded(). А может и не нужно.

    Итого:
    Добавляем то, что в пункте 1.
    Устанавливаем нужные констреинты.
    Удаляем ваш код в пункте 3.
    Добавляем метод preferredLayoutAttributesFitting
    Ответ написан
    3 комментария
  • Как отменить данное действие на Iphone?

    doublench21
    @doublench21
    Нет нельзя. Что бы такого эффекта не было, можно задать цвет подложки такой же, какой и сам скролл. Тогда и заметно не будет. Но это если там вообще есть какой-то фон, если там изображение какое, то тут вариантов нет. Да и не понимаю я, что в этом плохого.

    Может тут есть какой костыль: https://stackoverflow.com/questions/8150191/disabl...
    Ответ написан
    Комментировать
  • Как преобразовать структуру Firebase в объект swift?

    doublench21
    @doublench21 Куратор тега Swift
    Что из перечисленного списка Вас смущает и Вы не умеете это делать: ?
    • Получить JSON данные через URLSession/Alamofire/FirebaseSDK
    • Использование Codable для преобразования JSON в класс/структуру
    Ответ написан
    2 комментария
  • Как передать данные в кастомную ячейку UITableViewCell перед тем, как она будет построена?

    doublench21
    @doublench21 Куратор тега Swift
    Пример из моего проекта. (Код не привожу текстом, ужасный редактор.)

    В делегате:
    5c7bf8b3c0d26725364424.png
    internal override func collectionView(
      _ collectionView: UICollectionView,
        cellForItemAt indexPath: IndexPath
      ) -> UICollectionViewCell
      {
        let cell = collectionView.dequeueReusableCell(
          withReuseIdentifier: CategoriesCollectionViewCell.reuseIdentifier,
          for: indexPath
        ) as! CategoriesCollectionViewCell
    
        let randomIndex = indexPath.item % CategoriesPlaceholder.images.count
    
        cell.configure(
          withImage: UIImage(named: CategoriesPlaceholder.images[randomIndex])!,
          andTitle: CategoriesPlaceholder.titles[randomIndex]
        )
    
        return cell
      }

    Внутри ячейки:
    5c7bf8c1617ce913362365.png
    internal final class CategoriesCollectionViewCell: UICollectionViewCell {
    
     // =====================================
      // MARK: - Configure
      // =====================================
    
      internal func configure(withImage image: UIImage?, andTitle title: String) {
        illustrationCircle.image = image
        self.title.text = title
      }
    Ответ написан
    7 комментариев
  • Как отобразить snapshot в NavigationController с кастомной AnimateTransition?

    doublench21
    @doublench21 Куратор тега Swift
    Что-то мне подсказывает, что Вы совершенно не понимаете логику переходов между VC и ГЛАВНОЕ в каком контексте это происходит.

    Во-первых: Что за Магическая необходимость заставила вас удалять вью контроллера из которого вы переходите - неясно... А как вы перейдете назад? В никуда.

    Во-вторых: Предоставляете ли вы свой класс анимации, тут Важно, не Контроллеру, к которому переходите, а Навигейшн Контроллеру? Что-то мне подсказывает, нет.

    В-третьих: Вот полностью рабочий вариант. (Рабочий в том смысле, что он делает то, что вы хотите. Опущены проверки)

    5c70127785756462005262.png
    .
    Код текстом
    internal final class ModalAnimator: NSObject, UIViewControllerAnimatedTransitioning {
    
      private var isPresenting: Bool
    
      private let duration: TimeInterval = 3
    
      internal init(isPresenting: Bool) {
        self.isPresenting = isPresenting
      }
    
      internal func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        return duration
      }
    
      internal func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from),
          let toVC = transitionContext.viewController(forKey: .to),
          let snapshot = toVC.view.snapshotView(afterScreenUpdates: true)
          else { return }
    
        let containerView = transitionContext.containerView
    
        snapshot.frame = fromVC.view.frame
    
        containerView.addSubview(toVC.view)
        containerView.addSubview(snapshot)
    
        fromVC.view.isHidden = true
    
        UIView.animate(
          withDuration: duration,
          animations: { snapshot.transform = CGAffineTransform(rotationAngle: .pi)},
          completion: { _ in
            fromVC.view.isHidden = false
            snapshot.removeFromSuperview()
            transitionContext.completeTransition(!transitionContext.transitionWasCancelled)
        })
      }
    }
    Ответ написан
  • Как решить лимит с запланированными оповещениями?

    doublench21
    @doublench21 Куратор тега Swift
    А кто Вам мешает поставить задачу в бэкграунд и запрашивать даты каждый день в 00:00 скажем и добавлять оповещение? Или скажем запрашивать новые даты с более длительным периодом. Никто же Вас не заставляет в один день устанавливать 200 оповещений. Получайте новые даты и устанавливайте их по мере необходимости. В приложение для этого заходить не нужно.

    Второй вариант использовать EventKit(Календарь, Напоминания). Там вообще лимитов нет.
    Ответ написан
    2 комментария
  • Какие инструменты для дизайнера мобильных приложений?

    doublench21
    @doublench21
    Душите таких дизайнеров и НИ в коем случаи не делайте за них работу. Заставляйте использовать такие инструменты как Principle, InVision Studio, Adobe XD.
    Ответ написан
    Комментировать
  • Как получить текст смс?

    doublench21
    @doublench21 Куратор тега Swift
    Читать сообщения конечно же нельзя. Но начиная с iOS 12 у Вас есть возможность получить код подтверждения для вашего приложения, присланное смской.

    if #available(iOS 12, *) {
      textField.textContentType = .oneTimeCode
    }
    Ответ написан
    2 комментария
  • Как отключить "Жирный шрифт" в приложении, который включен для всей системы?

    doublench21
    @doublench21 Куратор тега Swift
    Ну вообще говоря отключать это не нужно. Не каждый, кто пользуется вашим приложением видит так же хорошо, как и Вы. Этот ползунок сильно помогает людям с плохим зрением и это нужно учитывать.

    Что бы отключить такое поведение, достаточно отключить свойство adjustsFontForContentSizeCategory у UIFont, которое не зря по умолчанию выставлено в true.

    По умолчанию шрифт полученный методами preferredFont(forTextStyle:), preferredFont(forTextStyle:compatibleWith:) и от UIFontMetrics включает это свойство, для остальных шрифтов - отключён. Вот ваш способ и сработал.
    Ответ написан
    Комментировать
  • Как разблокировать пользователю интерфейс при скроле таблицы?

    doublench21
    @doublench21 Куратор тега Swift
    Проблема(если это вообще можно назвать проблемой) заключается в том, что UITableView не пропускает ивенты UIEvent во время скролла своим сабвьюхам. Поэтому ваш UIDatePicker и не получает никаких касаний(ивентов UIEvent), до тех пор, пока не остановить таблицу.

    Решений тут может быть несколько:
    1) Переопределять метод
    func hitTest(_ point: CGPoint,  with event: UIEvent?) -> UIView?
    у UITableView;
    2) https://stackoverflow.com/questions/16882737/scrol... ;
    Ответ написан
    Комментировать
  • Может ли iOS очистить значения свойств класса?

    doublench21
    @doublench21 Куратор тега Swift
    Если у Вас действительно такой кэш, какой вы показали, то это ужасно.

    По делу: само по себе свойство не может очиститься. Либо система посчитает нужным и полностью выбросит ваше приложение из памяти, либо вы вернётесь, как ни в чем не бывало.
    Ответ написан
    3 комментария
  • Может ли iOS background приложение показать картинку?

    doublench21
    @doublench21
    Вот вы хоть сами понимаете, что такого просто не может быть? НУ кто Вам в здравом уме позволит ни с того ни с сего, по Вашему хотению(имеется ввиду ваше приложение), что-то вообще делать, если Ваше приложение неактивно, а уж тем более показывать картинку ПОВЕРХ. Конечно такого нет, не было и никогда не будет. Всё что Вы можете, это делать переодически, некоторое количество вещей(смотрите документацию), которые обычно связаны с небольшими запросами получения информации из вне.

    То есть Вы ограничены как по времени, так и по перечню действий, который никогда ничего не могут отобразить. Когда Вы закрываете приложение, у Вас есть всего некоторое кол-во времени, которое даётся на то, что бы Вы успели, скажем закрыть коннект к БД или сделать что-то ещё. Если этого времени не хватает, можете запросить у системы ещё. С большой вероятностью система даст добро, но опять таки - это время будет крайне малым. Секунды.
    А что касается периодических действий в фоне по графику, то они крайне скудны и направлены лишь на получение какой-либо информации.

    В общем и целом, это единственный верный и нужный способ взаимодействий приложения в фоне. Это и называется так, потому-что НИКТО не хочет, что бы приложение которое я закрыл, что-то пыталось мне впихнуть. Очевидно этого никогда не будет и ... правильно. Apple в этом плане молодцы!
    Ответ написан
    1 комментарий
  • Возможно ли отправлять push для ios c сайта?

    doublench21
    @doublench21
    Нельзя. Safari iOS не поддерживает "push notification" и "serviceworker". Уведомления могут получать лишь приложения.
    Ответ написан
    Комментировать
  • Какой правильный путь становления iOS developer?

    doublench21
    @doublench21
    Только Swift. Тут даже говорить особо не нужно.

    С - писать что-то на С под iOS в 99% случаев не нужно. Разве что Вам вот срочно нужен какой-то специфичный участок поднять в производительности и Вы пишете его на С. Затем пишите обвязку вашего кода на Swift и собственно вызываете его. Но я таких случаев вспомнить не могу.
    Swift и Obj-c отлично дружат с С, но никак не с С++.

    Obj-c - совершенно не нужен, как новичку который вливается в эту тему. Язык остаётся всё больше в прошлом с каждым днём. Всё возможности с лихвой покрываются языком Swift. Основной фактор - Apple сама продвигает всё к Swift

    Swift - новый/модный/се*суальный. Если серьезно, то язык уже очень сильно вырос, хотя и является довольном молодым. Огромная работа проводится над ним ежедневно, достаточно глянуть на кол-во коммитов в репозитории языка на GitHub. Скоро будет достигнут самый важный рубеж - это ABI.

    Язык имеет выразительный синтаксис. Огромные возможности ПОП и сильную поддержку дженериков во всех проявлениях. Довольно быстрый язык. Тут можно глянуть, что язык на данный момент является самым быстрым ООП языком, не учитывая конечно С/С++ и Rust(хотя Rust в каком то смысле и не ООП)

    Этот язык не зря недавно выбрали разработчики Tensorflow. Тут описано почему именно его, а не другие.

    Немного ушли от темы iOS Dev. Тут однозначно только Swift. Учебник Swift от Apple. Дальше можно взять Стэнфордские курсы iOS 11(есть на русском). А дальше уже от Вас зависит.
    Ответ написан
    2 комментария
  • Как добавить. key value в moya?

    doublench21
    @doublench21 Куратор тега Swift
    Сам чёрт ногу сломит. Наверное тут должно быть как-то так. parameters и есть ваши key=val. Зачем везде писать public? Зачем подключить Foundation, если уже есть UIKit? Тоже самое и с Alamofire?
    public var parameters: [String: Any]? {
            var params:[String: Any] = [:] // for post params
            var query:[String: Any] = [:] // for get params
    }
    
    public var parameterEncoding: ParameterEncoding {
            switch self {
            case .addComment, .uploadReportImage,
                 .addReport, .addFavorite, .getFavorites, .removeFavorite, .uploadAvatar,
                 .getProfile, .updateProfile, .getUserComments:
                return CompositeJsonEncoding()
            default:
                return CompositeEncoding()
            }
    }
    Ответ написан
    Комментировать
  • Как убрать лаги в ScrollView, который пролистывается под прозрачным navBar?

    doublench21
    @doublench21 Куратор тега Swift
    Ну так наверное не нужно цеплять его к SafeArea, а зацепить напрямую к SuperView. Тогда и не нужно писать -44, будет просто 0.
    Ответ написан
    5 комментариев