Swift: защо все пак имам нужда от опции?

Прочетох няколко статии за това и разбирам основния принцип и съм съгласен, че може да бъде полезно в някои случаи. През повечето време обаче бих искал програмата ми да се срине, ако получавах nil някъде, където не би трябвало да бъда -- така разбрах, че има проблем!

Освен това прочетох, че използването на опции може да доведе до по-кратък код. Как е възможно това?? От това, което съм виждал, цялата идея зад тях е, че те могат или да имат стойност, или nil, така че трябва да направите допълнителна проверка, докато преди това не беше необходимо!

И какво става с необходимостта да използвате "като" през цялото време? Това просто прави всичко по-многословно и дълго. Например, сравнете следния код в Objective-C и Swift

Обектив-C:

UIViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"Home"];
AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
appDelegate.window.rootViewController = vc;
[UIView transitionWithView:appDelegate.window
                          duration:0.2
                          options:UIViewAnimationOptionTransitionCrossDissolve
                          animations:^{ appDelegate.window.rootViewController = vc; }
                          completion:nil];

Swift:

//have to check if self.storyboard != nil
let viewController:UIViewController = self.storyboard?.instantiateViewControllerWithIdentifier("Home") as UIViewController; //Isn't the view controller returned by instantiateViewControllerWithIdentifier() already of type UIViewController?
let appDelegate:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate; //Isn't the delegate returned by sharedApplication() already of type AppDelegate?
//have to check if appDelegate.window != nil
appDelegate.window!.rootViewController = viewController as UIViewController; //Why cast viewController as UIViewController if the type has already been explicitly set above?

UIView.transitionWithView(
    appDelegate.window!,
    duration: 0.2,
    options: UIViewAnimationOptions.TransitionCrossDissolve,
    animations:{appDelegate.window!.rootViewController = viewController as UIViewController},
    completion: nil
);

Правя ли нещо нередно? Или това наистина е начинът, по който е планирано да бъде?


person null pointer exception    schedule 15.03.2015    source източник
comment
As в края замества типа в началото в Objective-C, така че това е почти измиване, що се отнася до многословието. Също така не се нуждаете както от :ClassName, така и от as ClassName -- нямате нужда от :ClassName преди =. Също така не трябва да имате точка и запетая в края на реда в Swift   -  person rdelmar    schedule 15.03.2015
comment
Проверете документите за видове връщане. Не, върнатият тип за instantiateViewControllerWithIdentifier не е UIViewController, това е id. Ето защо имате нужда от as   -  person rdelmar    schedule 15.03.2015
comment
Вероятно защото Суифт е тъп. Няма да принуждава автоматично. Трябва изрично да прехвърлите един в друг. Ups - къде е вашият коментар?   -  person qwerty_so    schedule 15.03.2015
comment
А, това обяснява това. Благодаря. Все още наистина не разбирам защо да използвам опции. Разбира се, че искате да уловите, когато нещо е nil, но с цената на това, че трябва винаги да проверявате за nil? Изглежда ми като много повече код   -  person null pointer exception    schedule 15.03.2015
comment
Колкото и да си струва, кодът на Objective-C би бил също толкова многословен, ако не и повече, ако всъщност включвате проверки, за да сте сигурни, че променливите ви са от типовете, които предполагате, че са, и respondsToSelector: проверки на извикванията на методите и свойствата достъп.   -  person Mick MacCallum    schedule 15.03.2015
comment
Също така не съм много убеден в незадължителната концепция. Но това е дискусия, основана на мнение, която не е добре дошла тук в SO.   -  person qwerty_so    schedule 15.03.2015


Отговори (1)


По избор

Ако знаете със сигурност, че дадена променлива никога не трябва да е нула, можете да принудите да разопаковате опция с помощта на ! или да декларирате като имплицитно разопакована с String!. Това ще доведе до срив, когато е нула, точно както искате.

Но при някои променливи е разумно те да са нула. Например модел User, чиято променлива age не е зададена, защото потребителят не я е предоставил.

Изричното им маркиране като незадължителни и разгръщането им с помощта на if let ви принуждава да мислите за нищожност. В крайна сметка това създава по-стабилен код.

Не мисля, че води до съкратен код. Където в Objective-C бихте използвали if var != nil, вие използвате if let var = var в Swift. Изпращането на съобщение до nil в Obj-C е noop, можете да получите същото поведение в Swift, като използвате var?.method(). В крайна сметка е някак си същото.

Предаване (като)

Голяма причина да се нуждаете от кастинги точно сега в Swift е, че някои Objective-C методи връщат id, което не беше проблем в Obj-C, но причинява проблеми в Swift. Очаквам това да намалее, когато Swift стане по-популярен и рамките се адаптират.

Актуализиран код

Бързо прегледах кода ви и изглежда, че нямате нужда от половината от тези отливки. Това е от върха на главата ми:

if let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("Home") as? UIViewController {
    if let window = UIApplication.sharedApplication().delegate?.window {
        window.rootViewController = viewController

        UIView.transitionWithView(window, duration: 0.2, options: .TransitionCrossDissolve, animations: {
            window.rootViewController = viewController
        }, completion: nil);
    }
}
person Rengers    schedule 15.03.2015
comment
А, благодаря, перфектно обяснение защо е необходимо. Що се отнася до опциите, изглежда, че като цяло е по-добре просто да бъдете малко по-подробни и да използвате if let var = var, вместо просто принудително разопаковане? Просто ме убива да добавям всички тези проверки, когато self.storyboard например така или иначе никога не трябва да бъде nil. Но ако беше така, не бихте ли искали програмата ви да се срине, за да знаете точно какъв е проблемът? Това изглежда почти затруднява отстраняването на грешки.. - person null pointer exception; 15.03.2015
comment
Току-що пуснах вашия код в Xcode и window.rootViewController = viewController ми дава грешката „UIWindow?“ няма член с име „rootViewController“ - person null pointer exception; 15.03.2015
comment
Зависи от ситуацията. За разкадровките принуждавам да разопаковам, защото знам, че не е нула. И дори да беше нула, приложението ми нямаше да може да продължи, така че нямам проблем да се срине в този момент. - person Rengers; 15.03.2015
comment
Добре е да знам, това е по-скоро в съответствие с това как бих очаквал да изглежда. Що се отнася до горната грешка, просто принудително разопаковам прозореца if let window = UIApplication.sharedApplication().delegate?.window! - person null pointer exception; 15.03.2015
comment
Изглежда, че е обяснено тук: stackoverflow.com/questions/28901893/ - person Rengers; 15.03.2015