Что эквивалентно + (void) load {} в Swift 4? [Дубликат]

В вашем примере не выполняется вложенное расширение жизни

В конструкторе

  B (const A & amp; a_): a (  a_) {std :: cout & lt;  "B ()" & lt;  станд :: епсИ;  }  

Здесь a _ (переименованный для изложения) не является временным. Является ли выражение временным синтаксическим свойством выражения, а id-выражение никогда не является временным. Таким образом, здесь не существует расширения продолжительности жизни.

Вот случай, когда произойдет расширение продолжительности жизни:

  B (): a (A ()) {std :: cout & lt  ; & Lt;  "B ()" & lt;  станд :: епсИ;  }  

Однако, поскольку ссылка инициализируется в ctor-инициализаторе, время жизни продолжается только до конца функции. Per [class.temporary] p5:

Временная привязка к ссылочному элементу в конструкторе ctor-initializer (12.6.2) сохраняется до выхода конструктора. [ ! d35]

В вызове конструктора

  B b ((A ()));  // нужны дополнительные скобки!   

Здесь являются , связывающими ссылку на временную. [class.temporary] p5 говорит:

Временная привязка к ссылочному параметру в вызове функции (5.2.2) сохраняется до завершения полного выражения, содержащего вызов.

Поэтому временный файл A уничтожается в конце инструкции. Это происходит до того, как переменная B будет уничтожена в конце блока, объясняя ваш выход в журнал.

Другие случаи выполняют вложенное расширение продолжительности жизни

Агрегатная инициализация переменных

Агрегатная инициализация структуры с помощью элемента-ссылки может продлить жизнь:

  struct X {const A & amp; a;  };  X x = {A ()};   

В этом случае временное время A привязано непосредственно к ссылке, поэтому временное продление на всю жизнь до xa , что совпадает с временем жизни x .

Агрегировать временную инициализацию

В C ++ 11 вы можете использовать агрегатную инициализацию для инициализировать временное и, следовательно, получить рекурсивное расширение продолжительности жизни:

  struct A {A () {std :: cout & lt;  "A ()" & lt;  станд :: епсИ;  } ~ A () {std :: cout & lt;  "~ A ()" & lt;  станд :: епсИ;  }};  struct B {const A & amp; a;  ~ B () {std :: cout & lt;  "~ B ()" & lt;  станд :: епсИ;  }};  int main () {const B & amp; b = B {A ()};  std :: cout & lt;  "-----" & lt;  станд :: епсИ;  }  

С помощью соединительной линии Clang или g ++ это производит следующий вывод:

  A () ----- ~ B () ~ A ()   

Обратите внимание, что временные расширения A временно и B временно продлены. Поскольку сначала выполняется временная постройка A , она уничтожается последним.

В std :: initializer_list & lt; T & gt; инициализация

C ++ 11 std :: initializer_list & lt; T & gt; выполняет расширение продолжительности жизни, как если бы он привязывал ссылку к базовому массиву. Поэтому мы можем выполнить вложенное расширение продолжительности жизни, используя std :: initializer_list . Однако ошибки в компиляторе распространены в этой области:

  struct C {std :: initializer_list & lt; B & gt;  б;  ~ C () {std :: cout & lt;  "~ C ()" & lt;  станд :: епсИ;  }};  int main () {const C & amp; c = C {{{A ()}, {A ()}}};  std :: cout & lt;  "-----" & lt;  станд :: епсИ;  }  

Производится с стволом Clang:

  A () A () ----- ~ C () ~ B () ~ B ()  ~ A () ~ A ()  

и с g ++ trunk:

  A () A () ~ A () ~ A () -  --- ~ C () ~ B () ~ B ()  

Это оба неправильно; правильный выход:

  A () A () ----- ~ C () ~ B () ~ A () ~ B () ~ A ()   
15
задан aryaxt 23 July 2014 в 00:44
поделиться

5 ответов

Найденный сам, оставит вопрос открытым, если кто-то ищет

override class func load() {
   NSLog("sdfsdf");
}

EDIT:

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

21
ответ дан aryaxt 17 August 2018 в 10:13
поделиться
  • 1
    Обратите внимание, что это работает только в том случае, если ваш класс спускается с NSObject. – Jack Lawrence 23 July 2014 в 02:28
  • 2
    @JackLawrence: он работает для любого класса @objc; не обязательно спускаться с NSObject. – newacct 23 July 2014 в 03:02
  • 3
    @newacct Вы это подтвердили? Это не работает для меня (после удаления override). – Jack Lawrence 23 July 2014 в 03:21
  • 4
    @JackLawrence: Это работает для меня. import Foundation @objc class MyClass { class func load() { println("sdfsdf") } } – newacct 23 July 2014 в 03:44
  • 5
    Swift 2.1: internal override class func initialize() { } для подкласса NSObject. Я не нашел, чтобы initialize() разрешался в чистом объекте Swift. – l --marc l 21 November 2015 в 07:28

в Swift 2.0, используйте этот метод

    public override class func initialize()
-1
ответ дан Alix 17 August 2018 в 10:13
поделиться
  • 1
    его никогда не называли ... – Vladimir Kofman 4 January 2016 в 15:07
  • 2
    @VladimirKofman Это будет называться при первом использовании вашего класса, что не обязательно во время загрузки. Класс должен быть @objc. – devios1 3 March 2016 в 22:25

Поддержка переопределения нагрузки была удалена в Swift 1.2

11
ответ дан Eric 17 August 2018 в 10:13
поделиться

Хотя прямой стимул недоступен для Swift, это может быть достигнуто относительно элегантно с Objective-C и категориями. MyClass должен по-прежнему наследоваться от NSObject и иметь метод class / static swiftyLoad, который вызывается из Objective-C в MyClass.m, который вы включаете в источники компиляции рядом с MyClass.swift:

# MyClass.swift

import Foundation
public class MyClass: NSObject
{
    @objc public static func swiftyLoad() {
        Swift.print("Rock 'n' roll!")
    }
}

# MyClass.m

#import "MyProject-Swift.h"
@implementation MyClass (private)
    + (void)load { [self swiftyLoad]; }
@end
]

. Лучшая часть не нужно возиться с перемычками заголовков или чем-нибудь еще, она просто работает. Есть несколько исправлений, особенно при использовании этого подхода в статических библиотеках, ознакомьтесь с полным сообщением на Medium для деталей! ✌️

1
ответ дан Ian Bytchek 17 August 2018 в 10:13
поделиться

Для Swift 2 или 3 (т. е. post-Swift 1.2) вы можете использовать:

class MySwiftClass: NSObject {
    internal override class func initialize() {
        DoStuff()
        super.initialize()
    }
}

Но, как вы можете видеть, ваш класс должен наследовать (прямо или косвенно) форму NSObject. Это необходимо, потому что initialize() вызывается средой выполнения ObjC.

И метод initialize() вызывается только при ссылке MySwiftClass. Так что это не будет так магии, как load().

Но это также будет более безопасным. Например: включая фреймворк (скажем, просто добавив его к вашему Podfile), не позволит таинственным образом начать вести себя, как только ваше приложение запустится, без необходимости добавлять одну строку кода к вашему project ( хотя бы ... Надеюсь!

-1
ответ дан MonsieurDart 17 August 2018 в 10:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: