По умолчанию ShutdownMode приложения WPF имеет вид OnLastWindowClose. В своем коде вы показываете одно окно, а затем закрываете его. Таким образом, последнее окно закрывается, и приложение закрывается. Затем при закрытии вы показываете другое окно. Поскольку приложение закрывается, окно немедленно закрывается.
Так что все работает так, как вы спроектировали и запрограммировали.
Однако вы хотите сделать что-то другое: окно, которое вы сначала показываете как единственное окно, должно быть «специальным окном», и после его закрытия вы хотите продолжить выполнение, показать свое «главное окно» и затем выйти После закрытия приложения (или всех окон, связанных с приложением).
Самый простой способ: сначала установить режим выключения OnExplicitShutdown, затем, после показа главного окна, установить его в OnLastWindowClose или OnMainWindowClose. В коде:
public static void Main()
{
var app = new App();
app.InitializeComponent();
app.ShutdownMode = ShutdownMode.OnExplicitShutdown;
new DialogWindow().ShowDialog();
var mainWindow = new MainWindow();
app.MainWindow = mainWindow;
app.Run(mainWindow);
// When the window has loaded, it should then set the app.ShutdownMode to what you actually want.
}
РЕДАКТИРОВАТЬ: Я не уверен, что именно вы делаете. Код, который вы дали, не скомпилируется, поскольку при правильном использовании класса приложения WPF (с действием сборки App.xaml в качестве ApplicationDefinition) метод Main уже определен. Если у вас просто есть класс, производный от Application, у вас нет метода InitializeComponent (). Единственный способ получить код для компиляции - вручную изменить действие сборки на Page. Однако в этом случае Application.Current == app.
Итак, происходит следующее:
app.Run(new DialogWindow()); app.Run(new MainWindow());
, у вас было бы исключение при создании MainWindow, так как в этом случае цикл диспетчера работает правильно. Таким образом, он может фактически отключиться, поэтому, когда MainWindow создается, он генерирует исключение, поскольку цикл диспетчера уже отключен. Опять же, без ошибок.
Так что один из способов решить эту проблему - перейти на OnExplicitShutdown. Затем на шаге 4 причина прекращения работы не достигается. Лучше (как в обычном приложении WPF) было бы иметь правильное ApplicationDefinition. Удалите StartupUri из App.xaml и вместо этого обработайте событие Startup:
private void OnStartup(object sender, StartupEventArgs e)
{
this.ShutdownMode = ShutdownMode.OnExplicitShutdown;
new DialogWindow().ShowDialog();
var mainWindow = new MainWindow();
this.ShutdownMode = ShutdownMode.OnLastWindowClose; // or OnMainWindowClose
mainWindow.Show();
}
Так как при закрытии диалогового окна у нас есть OnExplicitShudown, у приложения нет причин начинать закрываться в этой точке. Затем, после создания MainWindow, у нас снова есть окно как главного окна и как одно из окон приложения. Тогда мы можем перейти в режим выключения, который нам действительно нужен, и показать главное окно.
Это ошибка компилятора.
Хотя вы не указали ее полностью, я ожидаю, что ваш код будет выглядеть так:
@interface Foo : NSObject {
NSMutableArray *objects;
}
@property (readonly, copy) NSArray *objects;
@end
@implementation Foo
@synthesize objects;
@end
Компилятор, к сожалению, запутался в объявлении свойство объектов
и объявление переменной экземпляра объектов
. Помните, что в Objective-C свойства и переменные экземпляра - разные вещи; свойство может поддерживаться переменной экземпляра, но на самом деле оно является частью открытого интерфейса класса.
Вы можете обойти это, изменив свой код, чтобы четко отделить определение переменной экземпляра от определения свойства, например, поставив префикс имени переменной экземпляра:
@interface Foo : NSObject {
NSMutableArray *_objects;
}
@property (readonly, copy) NSArray *objects;
@end
@implementation Foo
@synthesize objects = _objects;
@end
Таким образом, компилятор не Я не могу запутаться в сравнении свойства и переменной экземпляра в выражениях типа self.objects
(чего в любом случае не должно быть, но, видимо, есть).
Просто чтобы предотвратить неизбежный ответ: Apple не резервирует префикс подчеркивания для переменных экземпляра. Он зарезервирован для методов. В любом случае, если вам не нравится подчеркивание, используйте другой префикс.
редактировать: Исходный ответ удален после того, как экспертная оценка обнаружила его отсутствие. Пожалуйста, прочтите комментарии Криса Хэнсона по этому поводу. Остальное я оставляю здесь, потому что думаю, что он все еще действителен.
Обратите внимание, что даже если вы объявите тип свойства как NSArray
, возвращаемый объект все равно будет NSMutableArray
, и для него определены изменяемые методы . Объявление свойства таким образом , а не предотвращает случайное изменение массива кем-либо.
Если вы хотите быть уверены, что возвращаемый массив неизменяем, вы можете объявить свойство, как в исходном примере, а затем сверните свой собственный аксессор:
- (NSArray *)myArray { return [NSArray arrayWithArray:myArray]; }
Обратите внимание, что это вернет несохраняемый NSArray
.
Вы видите ошибки, потому что XCode теперь выдает предупреждения и ошибки для вещей, которых он раньше не делал ...
Я бы сказал, что это должно быть в лучшем случае предупреждением о том, что вы делаете делая, я понимаю вашу попытку представить массив как неизменный для внешнего мира, но сделать его изменяемым внутри класса. Вы можете рассмотреть другой метод доступа с другим именем, специально созданный для возврата изменяемого массива.
Это все еще Objective-C 2.0; компилятор, может быть, немного обновлен с учетом такого рода ошибок при изменении типа. Это в значительной степени должно быть ошибкой. По крайней мере, это должно предупредить вас, что вы, вероятно, не имеете в виду то, что написали. Затем вы можете использовать что-то, чтобы он не предупреждал вас, чего нельзя сделать с помощью оператора @synthesize
.
Я просто вставил ваш код и оператор синтеза в свой контроллер, и я не получил ошибки или предупреждения об этом. Он построен отлично. Теперь я установил базовый SDK на «Simulator 3.0», а сборку на «Simulator 3.0 Debug». Этот проект начался с 2.2.1 SDK, и я только вчера установил 3.0 SDK; Xcode - это версия 3.1.3.
Обновление : О, я вижу, что на самом деле при попытке установить свойство вы получаете указанную вами ошибку.
Так что это действительно связано с вызовом @synthesize, который недоволен раскрытием NSMutableArray как NSArray - почему бы просто не реализовать getMethod.
На самом деле, если подумать, это должно быть метод set, который не устраивает - вы не сможете установить NSArray в NSMutableArray.
У вас были следующие вопросы:
Кто-нибудь знает об изменениях в objective-c между OS 2.2.1 и 3.0?
Есть ли какая-либо документация по этим изменениям?
Окончательные ответы таковы:
1) В спецификацию языка не было намеренных изменений, но изменились компилятор и другие инструменты разработчика. Крис и его коллеги являются экспертами по этим изменениям.
2) Вероятно, нет, потому что любые изменения были непреднамеренными или сделаны для лучшего соответствия поведения с документацией.
Вы не должны так быстро отклонять ответ Криса как "догадка." Крис работает над инструментами разработчика Apple.