Как инициализировать свойства, которые зависят друг от друга

Я хочу, чтобы изображение переместилось на дно. Если я нажму кнопку, то pic должен опуститься на 1.

Я добавил изображение и кнопку:

var corX = 0 var corY = 0 var runter: UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton var image = UIImage(named: "panzerBlau.jpg"); var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40)); // override func viewDidLoad() { super.viewDidLoad() panzer.image = image; // self.view.addSubview(panzer); // runter.frame = CGRectMake(100, 30, 10 , 10) runter.backgroundColor = UIColor.redColor() view.addSubview(runter) runter.addTarget(self, action: "fahren", forControlEvents:UIControlEvents.TouchUpInside) } 

По крайней мере, я сказал в функции «fahren», чтобы переместить снимок на 1.

 func fahren(){ corY += 1 panzer.frame = CGRectMake(corX, corY, 30, 40) // self.view.addSubview(panzer); } 

Поэтому моя проблема: я получаю несколько ошибок с этими corX и corY. Без них он работает отлично, а не как одноразовая кнопка. Ошибки: ViewController.Type не имеет члена с именем corX и ViewController.Type не имеет имени участника panzer Где я получаю ошибки, которые я сделал //, чтобы показывать в каких строках.

PS: Я использую Xcode Beta5

Вот полный код без всего остального:

 import UIKit class ViewController: UIViewController { var corX = 0 var corY = 0 var runter: UIButton = UIButton.buttonWithType(UIButtonType.System) as UIButton var image = UIImage(named: "panzerBlau.jpg"); var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40)); override func viewDidLoad() { super.viewDidLoad() panzer.image = image; self.view.addSubview(panzer); runter.frame = CGRectMake(100, 30, 10 , 10) runter.backgroundColor = UIColor.redColor() view.addSubview(runter) runter.addTarget(self, action: "fahren", forControlEvents:UIControlEvents.TouchUpInside) } func fahren(){ corY += 100 panzer.frame = CGRectMake(corX, corY, 30, 40) self.view.addSubview(panzer); } } 

@MartinR указал на главный вопрос:

 var corX = 0 var corY = 0 var panzer = UIImageView(frame: CGRectMake(corX, corY, 30, 40)) 

Проблема в том, что инициализатор по умолчанию Swift не может ссылаться на значение другого свойства, потому что во время инициализации свойство еще не существует (поскольку сам экземпляр еще не существует). В принципе, в инициализаторе по умолчанию для panzer вы неявно ссылаетесь на self.corX и self.corY но нет self потому что self – это именно то, что мы находимся в середине создания.

Один из способов – сделать инициализатор ленивым:

 class ViewController: UIViewController { var corX : CGFloat = 0 var corY : CGFloat = 0 lazy var panzer : UIImageView = UIImageView(frame: CGRectMake(self.corX, self.corY, 30, 40)) // ... } 

Это законно, потому что panzer не инициализируется до более позднего времени, когда его сначала называют вашим фактическим кодом. К этому времени существует self и ее свойства.

Ваше зависимое имущество должно быть:

  1. lazy
  2. Имейте явное : Type
  3. Используйте self. доступ к другим свойствам

Пример:

 let original = "foo" // Good: lazy var depend: String = self.original // Error: var noLazy: String = self.original // Error: Value of type '(NSObject) -> () -> URLData' has no member 'original' lazy var noType = self.original // Error: Value of type '(NSObject) -> () -> URLData' has no member 'original' lazy var noSelf: String = original // Error: Instance member 'original' cannot be used on type 'YourClass' 

Я обращаюсь к названию вопроса:

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

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

Но если вам нужно постоянно менять переменную на основе другой, то вам нужно вычислить свойство, которое будет работать в обоих направлениях :

  • если вычисленное свойство установлено, оно устанавливает переменные связанные с ним хранимые свойства
  • если сохраненные свойства установлены (или снова сбрасываются), тогда он вызывает изменение тогда вычисленного свойства.

если вы измените значение lazy property, это не повлияет на этажные свойства, на которых оно было основано. см. здесь


Хорошим примером использования ленивого свойства было бы то, что, как только у вас будет firstName & lastName вы лениво создадите fullName и, вероятно, вы никогда не измените имя firstName lastName вашего объекта, ваше полное имя будет только одно время … Или, возможно, что-то, что может делать только lazy свойства – до тех пор, пока вы не получите доступ к свойству, он никогда не будет инициализирован , поэтому это уменьшит нагрузку инициализации вашего classа. Загрузка тяжелого расчета.

Кроме того, использование lazy сигналов будет сигнализировать другим разработчикам: «Эй сначала прочитайте о других свойствах и поймите, что они … затем приходят к этому ленивому свойству … поскольку ценность этого основана на них +, это, вероятно, тяжелые вычисления, к которым нельзя получить доступ слишком рано … ”

Что касается вычисленного свойства, хорошим примером может быть, если вы установите температуру в Фаренгейт, тогда вы также хотите, чтобы ваша температура objectiveсия изменила его значение … и если вы установите температуру objectiveсия, то снова вы хотите изменить значение по Фаренгейту .

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

 // // ViewController.swift // // Created by Shivank Agarwal on 19/05/18. // Copyright © 2018 Shivank Agarwal. All rights reserved. // import UIKit class ViewController: UIViewController { var corX = 0 var corY = 0 var runter: UIButton = UIButton() var image = UIImage(named: "panzerBlau.jpg") var panzer = UIImageView() override func viewDidLoad() { super.viewDidLoad() panzer.image = image; self.view.addSubview(panzer); panzer.frame = CGRect(x: CGFloat(corX), y: CGFloat(corY), width: 30, height: 40) runter.backgroundColor = UIColor.red view.addSubview(runter) view.addSubview(panzer) runter.addTarget(self, action: Selector(("fahren")), for:UIControlEvents.touchUpInside) } private func fahren(){ corY += 100 } private func updatePanzerFrame(){ panzer.frame = CGRect(x: CGFloat(corX), y: CGFloat(corY), width: 30, height: 40) } } Note: Do not add panzer imageView every time when user tap only add it on viewDidLoad() 

Пример Xcode

  • Расположение профилей XCode Provisioning
  • Не удается найти исполняемый файл для CFBundle CertUIFramework.axbundle
  • Полная трассировка стека Xcode
  • Xcode - Предупреждение: неявное объявление функции недействительно в C99
  • Как я могу использовать файлы .xcconfig в Xcode 4?
  • Ошибка Xcode 6: Неизвестный class в файле Interface Builder
  • Как я могу рассчитать разницу между двумя датами?
  • На mac, g ++ (clang) не удается выполнить поиск / usr / local / include и / usr / local / lib по умолчанию
  • Как я могу пропустить сжатие одного PNG?
  • C ++ не показывает cout в консоли Xcode, но отлично работает в терминале
  • Что такое простой способ разбить NSArray с 4000+ объектами в нем на несколько массивов с 30 объектами каждый?
  • Interesting Posts

    ПК в одной сети не могут связываться

    Удаленный доступ к PowerShell с ip-адресом в качестве целевого

    Выбор того IP-адреса, который используется HTTP-запросом при наличии нескольких IP-адресов (.NET)

    Что такое правило синтаксиса для наличия запятых в определениях кортежей?

    Когда использовать Xamarin.Forms vs Xamarin Native?

    Слияние нескольких строк

    Почему int указатель «++» увеличивается на 4, а не на 1?

    Как я могу прерывать текущий код в R с помощью команды клавиатуры?

    Как установить форвардную декларацию с помощью общих типов в Delphi 2010?

    Dapper.Rainbow VS Dapper.Contrib

    Передача параметра через службу отчетов URL-адресов в sql-сервер

    MATLAB, заполнение области между двумя наборами данных, строк на одном рисунке

    Как установить одинаковый масштаб для осей домена и диапазона JFreeChart

    MS Word Find Style, охватывающий 2 строки, которые содержат текст и заменяют часть

    Как скопировать DLL-файлы в ту же папку, что и исполняемый файл, используя CMake?

    Давайте будем гением компьютера.