...

вторник, 29 июля 2014 г.

[recovery mode] iOS vs WPF — сложное против мелкомягкого

Друзья, ничего умнее этого заголовка не придумал, так что небольшая предыстория.

Как и все программисты, я не мог не услышать про новый язык Swift, на который тут же посыпались разнообразные «хелловорлды»-обучалки. Однако, простые с виду приложения создаются (на мой WPF-ный взгляд) как-то уж слишком сложно даже после введения «упрощённого» языка. Это действительно необходимая сложность или их можно создавать как-то попроще?? Наткнулся на вот такой пример iOS-приложения (что-то вроде браузера приложений в аппсторе) и решил создать его полный аналог на «родном» WPF'е. Цель — сравнить сложность разработки и возможно кто-то поделится более простым методом для iOS (если он есть). Обилия скринов не будет, зато кода — … да и его, в общем-то, кот наплакал. :) Итак,

Задача: показывать список приложений из АппСтора, найденных по указанному фильтру. Должны быть иконка, заголовок и цена каждого приложения. WPF'ный пример делается абсолютно идентичным оригинальному, вплоть до таких же косяков-задержек при загрузке иконок.



  1. Запускаем Студию, создаём WPF приложение — два клика мышью + дать имя приложению.

  2. Подключаем в references библиотеку Newtonsoft.Json.dll — она нам поможет разбирать JSON

  3. Дополняем XAML-код главной формы нашим списком приложений и полем ввода с кнопкой вверху.

    Разметка формы


    <Window x:Class="StoreBrowser.MainWindow"
    xmlns="http://ift.tt/o66D3f"
    xmlns:x="http://ift.tt/mPTqtT"
    Title="MainWindow" Height="300" Width="600" SnapsToDevicePixels="True" TextOptions.TextFormattingMode="Display" UseLayoutRounding="True">
    <DockPanel LastChildFill="True">
    <DockPanel LastChildFill="True" DockPanel.Dock="Top">
    <Button DockPanel.Dock="Right" Padding="10,5" Click="SearchButton_Clicked">Search</Button>
    <TextBox Name="txtFilter"/>
    </DockPanel>

    <ListView Name="lstApps"><!-- наш список приложений -->
    <ListView.ItemTemplate>
    <DataTemplate><!-- здесь мы можем настраивать вид элементов -->
    <DockPanel LastChildFill="True">
    <Grid Width="70">
    <Image DockPanel.Dock="Left" Source="{Binding artworkUrl60}" /><!-- никакой ручной работы - изображение загрузится само! -->
    </Grid>

    <StackPanel Orientation="Vertical">
    <TextBlock Text="{Binding trackName}" FontWeight="Bold" FontSize="20" Padding="4"/>
    <TextBlock Text="{Binding formattedPrice}" FontSize="16" Padding="4" />
    <Rectangle Stroke="LightGray" Height="2" Width="250" HorizontalAlignment="Center" />
    </StackPanel>
    </DockPanel>
    </DataTemplate>
    </ListView.ItemTemplate>
    </ListView>
    </DockPanel>
    </Window>







    Как видно, код весьма прост — даже шаблон элементов описывается в привычных терминах.

  4. Встаём курсором на SearchButton_Clicked и жмём F12 — студия прыгнула в код и создала для нас обработчик, ну а мы допишем нужное.

    Немного C# магии


    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.Net;
    using System.Windows;

    namespace StoreBrowser
    {
    public partial class MainWindow : Window
    {
    public MainWindow()
    {
    InitializeComponent();
    }

    private void SearchButton_Clicked(object sender, RoutedEventArgs e)
    {
    var filter = txtFilter.Text.Trim();// подготовили фильтр
    if (string.IsNullOrEmpty(filter)) return;
    filter = Uri.EscapeUriString(filter.Replace(' ', '+'));

    using (var wc = new WebClient()) {
    // вот так двумя вызовами мы скачали JSON-ответ сервера и тут же распарсили в наши заготовленные классы
    var res = JsonConvert.DeserializeObject<StoreReply>(wc.DownloadString(@"http://ift.tt/1pyysv7" + filter));
    lstApps.ItemsSource = res.results;// показываем результат
    }
    }
    }

    class StoreReply
    {
    public int resultCount;
    public List<AppInfo> results;// тут сидит список наших приложений
    }

    class AppInfo
    { // обратите внимание - здесь далеко не все свойства приложения, мы указали только нужные нам.
    public string trackName { get; set; }// title
    public string formattedPrice { get; set; }// price
    public string artworkUrl60 { get; set; }// icon
    }
    }





    Думаю, тут даже излишне объяснять, насколько этот код лаконичнее тех Swift простыней, на двух страницах загружающих ответ.



  5. Ну и чего сидим? Жмите F5! Вот результат по фильтру «angrybirds»:


    Ещё раз обращу внимание, если вы не заметили: в коде нет ни строчки для загрузки картинок — они загружаются сами по мере прокрутки списка, мы только обеспечили их URL.




Итого, 30 строчек XAML + 44 C# кода. Я нарочно не стал делать всякую асинхронщину, т.к. глупо жать кнопку и тут же что-то менять — нужно дождаться результата, но если кому чешется, можете для async/await прибавить ещё 4 строчки.

В любом случае, полученный код явно компактнее и проще Swift-оригинала, да и сам проект — всего одна форма:


Ну и обратите внимание на сам стиль работы — не нужно ничего никуда перетаскивать, подстраиваться под чей-то «взгляд на жизнь» (см. главу «Подключение интерфейса» в оригинале) — мы сами творим что хотим, хоть в XAML, хоть в C#.

Итог — «побырому» написанное приложение, которое я не напрягаясь сваял минут за 20 (это вместе с разбором JSON-ответа от Apple, который я впервые вижу). При этом одно только чтение iOS варианта вывихнуло мне весь мозг — там создай, туда перетащи, тут обеспечь функции… Чего ж так сложно, господа? С таким инструментом точно не возникнет желания наполнять аппстор чем-то полезным — слишком уж дорого эта польза даётся. Напомню, это мнение программиста на WPF/WinForms, так что ждём ответов из стана Apple!


PS

Критика — велкам; сначала читаем свои слова, думаем, потом постим. Спасибо!


This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.


Комментариев нет:

Отправить комментарий