• Как передать данные в кастомную ячейку 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 комментариев
  • Как сделать, чтобы при закрытии крышки ноута компьютер продолжал работать?

    @kristenstewartdadada
    Frontend Developer
    подключить к внешнему монитору
    Ответ написан
    Комментировать
  • Где найти кофаундера для разработки iOS приложения?

    @stratosmi
    Ответьте для начала себе на вопрос:

    А зачем вы ему нужны?
    Ответ написан
    6 комментариев
  • Как переместить файл из Assets в Documents?

    @badtrips Автор вопроса
    Получилось,

    let asset = NSDataAsset(name: "KanjiDataBase", bundle: Bundle.main)
            // получаем полный путь к каталогу Documents
            // объект класса NSURL
            let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
            if let documentUrl = urls.first {
                try! asset?.data.write(to: documentUrl.appendingPathComponent("KanjiDataBase.s3db"), options: [.atomic])
            }
    Ответ написан
    Комментировать
  • Как сделать чтобы при повороте экрана Gradient был на весь экран?

    Vovanys
    @Vovanys
    просто размер вьюхи (self.view.bounds) надо изменять и перезапускать функцию

    нужно чтобы при перевороте экрана происходила перерисовка из-за изменений размеров вью
    if UIDevice.current.orientation.isPortrait {
    //тут перерисовка
    }
    Ответ написан
    Комментировать
  • Как динамически обновлять размеры CAGradientLayer?

    ManWithBear
    @ManWithBear
    Swift Adept, Prague
    Изменение размеров CALayer'a лежит полностью на его пользователе.
    Поэтому вам нужно при каждом изменении frame у вью, менять положиние / размер слоя
    Пример:
    class MyView: UIView {
        let gradient: CALayer 
        ...
        override func layoutSubviews() {
            super.layoutSubviews()
            gradient.frame = self.bounds
        }
    }


    Если прям очень хочется через экстеншн, то примерно так:
    private var gradientPropertyKey: UInt8 = 0
    extension UIView {
        func addNiceGradient() {
            let gradient =  < тут ваш слой >
            layer.addSublayer(gradient)
            let observation = layer.observe(\.bounds) { [weak gradient] layer, _ in
                gradient?.frame = layer.bounds
            }
            objc_setAssociatedObject(self, &gradientPropertyKey, observation, .OBJC_ASSOCIATION_RETAIN)
        }
    }

    Но будет работать хуже, да и уверены что хотите в ObjC Runtime без причины лезть?
    Ответ написан
    2 комментария
  • Как реализовать только один выбранный чекбокс?

    @freeg0r
    .. some dude ..
    кладёте все кнопки в массив, в метод нажатия кнопок вставляете для этого массива
    func actionMethod(_ sender: UIButton) {
          buttonsArray.forEach { $.isSelected = $ == sender }
          .
          .
    }
    Ответ написан
    1 комментарий
  • Как реализовать только один выбранный чекбокс?

    tsklab
    @tsklab
    Здесь отвечаю на вопросы.
    Есть 7 кнопок в виде чекбокса хочу сделать, что бы выбрать можно было только одну.
    Это называется RADIOBUTTON.
    Ответ написан
    Комментировать
  • Стоит ли сейчас в Objective-c?

    YeahGarage
    @YeahGarage
    Developer
    В идеале знать Swift и Obj. Но если посмотришь вакансии от иностранных агентов/компаний/задач на upwork и т.д. то преобладает swift, и с каждым годом его процент увеличивывается. Его развивает сама компания, выходят обновления. Лучше изучи его и потом пройдись по основам Obj. Тогда ты дорогой гость в любой компании и лучший сон рекрутера
    Ответ написан
    1 комментарий
  • Может ли iOS очистить значения свойств класса?

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

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

    smanioso
    @smanioso
    Отмечайте ответы на свои вопросы!
    В любом случае вам необходимо сохранять данные для последующего отображения в отсутствие доступа к серверу. Если используется Realm/Firebase, то достаточно несложно найти уже описанные методы решения данной задачи. В любом другом случае придется придется думать и решать самому.

    https://firebase.google.com/docs/database/ios/offl...
    https://realm.io/solutions/offline-first/
    Ответ написан
    1 комментарий
  • Как прочитать данные из файла?

    maximglobak
    @maximglobak
    iOS developer
    Можно пойти двумя путями, использовать файлы, удобнее всего json или .plist или использовать целые БД, такие как SQL или Realm например.
    Для первого сюжета файлы обычно полностью загружаются в оперативную память (полностью считываются) и ковертируются в стандартную структуру типа словаря или массива. В таком случае ты сам методами языка достаешь случайное значение.
    Как читать файлы можно найти здесь stackoverflow.com
    Но со вторым вариантом, на мой взгляд, удобнее работать, но сложнее интегрировать, там ты уже запихиваешь все данные в базу, а в приложении подключаешься к базе и средствами базы достаешь случайные значения. Если у тебя большие данные, то лучше использовать второй вариант, но для простоты лучше использовать первый вариант.
    Ответ написан
    Комментировать
  • Как работают вложенные функции?

    doublench21
    @doublench21 Куратор тега Swift
    Доброго времени суток. Вопрос немного странный.

    Вопрос 1
    Достаточно зайти вот сюда и обнаружить, что метод auth всего лишь возвращает инстанц класса FIRAuth Собственно все ваши currentUser тут присутствуют. Думаю теперь вопросов быть не должно.
    spoiler
    @implementation FIRAuth {
      /** @var _currentUser
          @brief The current user.
       */
      FIRUser *_currentUser;
    
      /** @var _firebaseAppName
          @brief The Firebase app name.
       */
      NSString *_firebaseAppName;
    
      /** @var _listenerHandles
          @brief Handles returned from @c NSNotificationCenter for blocks which are "auth state did
              change" notification listeners.
          @remarks Mutations should occur within a @syncronized(self) context.
       */
      NSMutableArray<FIRAuthStateDidChangeListenerHandle> *_listenerHandles;
    
      /** @var _keychain
          @brief The keychain service.
       */
      FIRAuthKeychain *_keychain;
    
      /** @var _lastNotifiedUserToken
          @brief The user access (ID) token used last time for posting auth state changed notification.
       */
      NSString *_lastNotifiedUserToken;
    
      /** @var _autoRefreshTokens
          @brief This flag denotes whether or not tokens should be automatically refreshed.
          @remarks Will only be set to @YES if the another Firebase service is included (additionally to
            Firebase Auth).
       */
      BOOL _autoRefreshTokens;
    
      /** @var _autoRefreshScheduled
          @brief Whether or not token auto-refresh is currently scheduled.
       */
      BOOL _autoRefreshScheduled;
    
      /** @var _isAppInBackground
          @brief A flag that is set to YES if the app is put in the background and no when the app is
              returned to the foreground.
       */
      BOOL _isAppInBackground;
    
      /** @var _applicationDidBecomeActiveObserver
          @brief An opaque object to act as the observer for UIApplicationDidBecomeActiveNotification.
       */
      id<NSObject> _applicationDidBecomeActiveObserver;
    
      /** @var _applicationDidBecomeActiveObserver
          @brief An opaque object to act as the observer for
              UIApplicationDidEnterBackgroundNotification.
       */
      id<NSObject> _applicationDidEnterBackgroundObserver;
    }

    Представить это можно так:
    class Auth {
     class func auth() -> FIRAuth { ... }
     ...
    }
    
    class FIRAuth {
      var currentUser: FIRUser?
      ...
    }
    
    class FIRUser {
     var providerData: [Int : {что-то}]
     ...
    }
    
    Auth.auth().currentUser?.providerData[indexPath.row]


    Вопрос 2
    Кажется ещё более странным. Вы ведь знаете что такое опционал?! Тогда неужели Вы забыли, что метод может возвращать любое значение, в том числе и опционал. Теперь становится ясно, что с любым опционалом мы также можем применить опциональную цепочку, что собственно тут и было сделано.
    FUIAuth.defaultAuthUI() возвращает опционал. Почему бы и не продолжить цепочку. Продолжаем:
    FUIAuth.defaultAuthUI()?.handleOpen(url, sourceApplication: sourceApplication)
    Но как не странно этот метод тоже возвращает опционал и мы просто хотим себя от этого обезопасить и сказать, что если на последнем методе тоже будет опционал, то верни правую часть, то бишь false. В итоге получаем общую картину:
    FUIAuth.defaultAuthUI()?.handleOpen(url, sourceApplication: sourceApplication) ?? false
    Ответ написан
    2 комментария
  • Как сделать выпадающий список?

    SnapSh0t
    @SnapSh0t
    iOS-Developer
    Я создавал 2 динамические ячейки в TableView и на нажатие добавлял кастомную ячейку ниже.
    TabelView
    5b5efcca68b1c646755063.png5b5efd0a45f87893330570.png
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            if (destinationData?[indexPath.row]) != nil {
                if(indexPath.row + 1 >= (destinationData?.count)!) {
                    expandCell(tableView: tableView, index: indexPath.row)
                }
                else {
                    if(destinationData?[indexPath.row+1] != nil) {
                        expandCell(tableView: tableView, index: indexPath.row)
                        // Close Cell (remove ExpansionCells)
                    } else {
                        contractCell(tableView: tableView, index: indexPath.row)
                    }
                }
            }
        }
        
        /*  Expand cell at given index  */
        private func expandCell(tableView: UITableView, index: Int) {
            if let infoMain = destinationData?[index]?.infoMain {
                var indexesToInsert = [IndexPath]()
                for i in 1...infoMain.count {
                    destinationData?.insert(nil, at: index + 1)
                    indexesToInsert.append(IndexPath(row: index + i, section: 0))
                }
                tableView.insertRows(at: indexesToInsert , with: .left)
                tableView.scrollToRow(at: IndexPath(row: index + 1, section: 0), at: .bottom, animated: true)
            }
        }
        
        /*  Contract cell at given index    */
        private func contractCell(tableView: UITableView, index: Int) {
            if let infoMain = destinationData?[index]?.infoMain {
                var indexesToDelete = [IndexPath]()
                for i in 1...infoMain.count {
                    destinationData?.remove(at: index + 1)
                    indexesToDelete.append(IndexPath(row: index + i, section: 0))
                }
                tableView.deleteRows(at: indexesToDelete, with: .left)
            }
        }
    Ответ написан
    Комментировать
  • Как сделать выпадающий список?

    NSA-bot
    @NSA-bot
    Насколько я знаю, стандартного элемента нет.
    Гуглите (или яндексите :) ) "swift dropdown list" или "swift dropdown menu"
    Ответ написан
    Комментировать
  • Как писать чистое разветвление кода?

    EgorkZe
    @EgorkZe
    iOS (Swift), GoLang
    Почитай книгу Clean Architecture, посмотри на архитектуры Clean Swift, Viper.
    Ответ написан
    Комментировать
  • Не совсем понимаю принцип вычисляемых свойств?

    @freeg0r
    .. some dude ..
    Каждая переменная класса имеет выделенных для нее память, а computed properties не имеют. В геттере и сеттере вы просто определяете какое то выражение, которое выполняется в при соответствующей операции. Хороший пример со временем:
    class Time {
        var seconds:Double = 0
        
        init(seconds: Double) {
            self.seconds = seconds
        }
        
        var minutes: Double {
            get {
                return (seconds / 60)
            }
            set {
                self.seconds = (newValue * 60)
            }
        }
        
        var hours: Double {
            get {
                return (seconds / (60 * 60))
            }
            set {
                self.seconds = (newValue * (60 * 60))
            }
        }
        
        var days:  Double {
            get {
                return (seconds / (60 * 60 * 24))
            }
            set {
                self.seconds = (newValue * (60 * 60 * 24))
            }
        }
    }


    Просто абстракция, можно использовать конечно и функцию вместо этого, но так в некоторых случаях более "элегантно" что ли..
    Хороший промер есть ещё в iBook Swift книге с прямоугольником.
    Ответ написан
    4 комментария
  • Как исправить прыгающие ячейки в TableView?

    @andrew8712
    Оберните содержимое expandCell и contractCell в вызовы tableView.beginUpdate() и tableView.endUpdate()
    И лучше конечно вызывать tableView.insertRows.... один раз, а не каждую итерацию. Советую сначала построить массив индексов, и с ними уже вызывать этот метод
    Ответ написан
    2 комментария
  • Как вызвать функцию из другого класса, которая без типа?

    doublench21
    @doublench21 Куратор тега Swift
    А Вы уверенны что знаете язык Swift? Судя по коду и вопросу - нет.
    Нужно понимать, что такое метод типа, а что такое инстанц метод.

    Метод типа определяется так. Ключевое слово static может быть заменено на class(но это не важно)
    class Printer {
      static func mustprint() {
        print ("was printed")
      }
    }


    И вызывается так
    Printer.mustprint()

    ----------

    А то что Вы написали, это инстанц метод
    class Printer {
       func mustprint() {
        print ("was printed")
      }
    }


    И вызывается он сначала путём создание инстанца этого класса, а затем вызова функции.
    let printer = Printer(); printer.mustprint()

    ----------

    О чём Вам тут и говорят: "Instance member 'mustprint' cannot be used on type 'Printer'; "
    Ответ написан
    3 комментария