Interface Builder: co to je, vizuální design v Xcode a storyboardy

Autor: IT Sectr Publikováno: 2026-02-12 Doba čtení: 15 min

Interface Builder — vizuální editor rozhraní integrovaný v Xcode pro vývoj iOS a macOS. Umožňuje vytvářet UI pomocí drag-and-drop, konfigurovat Auto Layout, propojit kód přes IBOutlet a IBAction. Rozebereme, jak IB funguje, čím se liší Storyboard a XIB a k čemu slouží @IBDesignable.

Hlavní body

  • Interface Builder — vizuální editor v Xcode pro UIKit rozhraní bez psaní kódu rozvržení
  • Storyboard popisuje několik obrazovek a přechody mezi nimi; XIB — jednu komponentu nebo obrazovku
  • Auto Layout v IB nastavuje constrainty přes menu Pin, Align a Resolve Issues
  • IBOutlet a IBAction propojují Swift kód s UI prvky přes Ctrl+drag
  • @IBDesignable a @IBInspectable zobrazují vlastní view přímo na plátně IB

Co je Interface Builder?

Interface Builder — komponenta Xcode určená pro vizuální navrhování uživatelských rozhraní. Historie IB začala již v roce 1988 ve společnosti NeXT, dávno před příchodem iOS. Stefan Pope vyvinul první verzi pro NeXTSTEP — operační systém, který se stal základem macOS a iOS. V roce 1996 Apple koupil NeXT a integroval Interface Builder do Xcode.

V moderním Xcode Interface Builder podporuje tři formáty souborů: Storyboard, XIB (Xcode Interface Builder) a XIB soubory pro buňky tabulek a vlastní view. Každý z těchto formátů ukládá XML popis hierarchie UI prvků, jejich vlastností, constraintů a propojení s kódem.

IB pracuje na úrovni UIKit: tlačítka, popisky, textová pole, tabulky, kolekce a constrainty se přetahují myší na plátno. Xcode kompiluje .storyboard a .xib soubory do nib archivů (compiled Interface Builder) ve fázi sestavení, což zmenšuje velikost balíčku a zrychluje načítání.

Podle Apple více než 70% iOS projektů na UIKit používá Interface Builder v různých fázích vývoje. Navzdory růstu SwiftUI zůstává IB standardem pro komerční aplikace s podporou iOS 12 a nižších verzí, stejně jako pro složitá vlastní rozhraní vyžadující jemné doladění Auto Layout.

Jak se Interface Builder dostal do Xcode

Před Xcode 4 byl Interface Builder samostatnou aplikací spouštěnou paralelně s editorem kódu. V Xcode 4 (2011) Apple sjednotil IB a editor kódu do jediného IDE. To umožnilo přepínat mezi kódem a rozvržením bez přepínání oken a také vidět změny vlastností v reálném čase přes panel Attributes Inspector.

Verze XcodeRokZměny v Interface Builder
Xcode 32008IB — samostatná aplikace, podpora iOS 2.0
Xcode 42011IB integrován do IDE, zavedeny Storyboard
Xcode 52013Auto Layout s menu constraintů, náhled obrazovek
Xcode 62014Size Classes, @IBDesignable, Preview Assistant
Xcode 112019SwiftUI Canvas, IB zůstává pro UIKit
Xcode 152023SwiftUI Preview jako hlavní nástroj, IB legacy režim

S příchodem SwiftUI v roce 2019 Apple přesunul zaměření na deklarativní vývoj, nicméně Interface Builder zůstává integrován v Xcode pro podporu UIKit projektů. Tisíce existujících aplikací nadále používají IB a Apple neoznámil jeho odstranění.

Storyboard a XIB: formáty IB souborů

Interface Builder podporuje dva hlavní formáty: Storyboard (.storyboard) a XIB (.xib). Rozdíl mezi nimi spočívá v rozsahu a scénáři použití.

Storyboard — soubor obsahující celou scénu aplikace: několik obrazovek (UIViewController), přechody mezi nimi (segues), navigační kontroléry, tabbary a všechny UI prvky. Storyboard se načítá jednou při spuštění z Info.plist přes klíč UIMainStoryboardFile (k). Je vhodný pro vizualizaci toku obrazovek, ale vytváří problémy při merge konfliktech v git, protože XML popis celé aplikace je uložen v jednom souboru.

XIB (zkratka pro Xcode Interface Builder) — soubor pro jednu komponentu: samostatný UIView, UITableViewCell, UICollectionViewCell nebo jeden ViewController. XIB se načítá na vyžádání přes UINib(nibName:bundle:) (k) nebo metodu Bundle.loadNibNamed (k). XIB soubory se snadněji mergují, jsou kompaktnější a načítají se rychleji, protože neobsahují popis celé aplikace.

KritériumStoryboardXIB
RozsahVíce obrazovek + přechodyJedna obrazovka nebo komponenta
SeguesPodporuje (push, modal, unwind)Nepodporuje
Merge v gitSložitý (jeden velký XML)Jednoduchý (mnoho malých souborů)
NačítáníPři startu aplikaceNa vyžádání (líné)
Opětovné použitíPouze přes storyboard referencesVysoké (buňky, hlavičky, view)
Doporučení AppleNedoporučuje se pro velké projektyDoporučuje se pro komponenty

Od verze Xcode 11 Apple doporučuje používat XIB pro jednotlivé komponenty a vyhýbat se monolitickým Storyboard. Pro navigaci mezi obrazovkami je preferována kódová navigace přes UIStoryboardSegue (k) ručně nebo koordinátory.

XML struktura v IB souborech

.storyboard a .xib soubory ukládají XML ve formátu Interface Builder Cocoa Touch XIB (dt). Příklad zjednodušené struktury:

xml
<!-- XIB soubor s UIView a UILabel -->
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB"
          version="3.0">
  <objects>
    <view id="abc-123"
          userLabel="CustomHeaderView"
          contentMode="scaleToFill">
      <subviews>
        <label id="def-456"
               text="Nadpis"
               textColor="darkTextColor"
               fontDescription="title1"/>
      </subviews>
    </view>
  </objects>
</document>

Každý prvek má unikátní id (an), podle kterého IB propojuje XML uzel s runtime objektem. Při kompilaci Xcode převádí XML do binárního nib formátu (.nib), čímž zmenšuje velikost souboru přibližně o 40%.

Auto Layout a Size Classes v Interface Builder

Auto Layout — systém umísťování prvků na obrazovce pomocí matematických vztahů (constraintů). Interface Builder poskytuje vizuální rozhraní pro vytváření, úpravy a ladění constraintů bez psaní kódu. Každý constraint popisuje závislost: view.leading = superview.leading + 16 (k) nebo view.width = 2 * otherView.height (k).

V IB se constrainty vytvářejí přes menu Pin (upevnění okrajů, šířky, výšky) a Align (zarovnání na střed, okraje, baseline). Panel Size Inspector zobrazuje všechny constrainty vybraného prvku, jejich priority (required/high/low) a umožňuje upravovat multiplikátory a konstanty.

IB také podporuje UIStackView — kontejner, který automaticky spravuje rozmístění podřízených view. Stačí umístit prvky do stack view na plátně a IB automaticky vygeneruje potřebné constrainty. To výrazně zrychluje rozvržení ve srovnání s ručním umísťováním constraintů.

Size Classes: přizpůsobení zařízením

Size Classes — abstrakce sdružující zařízení podle šířky a výšky obrazovky: Compact a Regular. Kombinace (wC hR pro iPhone na výšku, wR hR pro iPad) umožňují nastavit různé constrainty a rozmístění prvků pro různé scénáře. V Interface Builder přepínání mezi size classes mění sadu aktivních constraintů na plátně.

ZařízeníOrientaceWidth ClassHeight Class
iPhone (kromě Max/Plus)Na výškuCompactRegular
iPhone (kromě Max/Plus)Na šířkuCompactCompact
iPhone Plus/MaxNa šířkuRegularCompact
iPadJakákoliRegularRegular
iPad Split View1/3 obrazovkyCompactRegular

Příklad constraintu s variací podle size class:

swift
import UIKit

class AdaptiveViewController: UIViewController {

    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var leadingConstraint: NSLayoutConstraint!

    private func updateConstraints() {
        let isRegular = traitCollection.horizontalSizeClass == .regular
        leadingConstraint.constant = isRegular ? 40 : 16
        titleLabel.font = isRegular
            ? UIFont.preferredFont(forTextStyle: .largeTitle)
            : UIFont.preferredFont(forTextStyle: .title1)
    }

    override func traitCollectionDidChange(
        _ previousTraitCollection: UITraitCollection?
    ) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.horizontalSizeClass != previousTraitCollection?.horizontalSizeClass {
            updateConstraints()
        }
    }
}

Ve výše uvedeném kódu traitCollectionDidChange reaguje na změnu size class a aktualizuje constraint a font. Interface Builder umožňuje nastavit výchozí hodnoty pro každou size class přes inspektor a kód se používá pro dynamické scénáře, které nelze popsat staticky.

IBOutlet, IBAction a propojení kódu s UI

Propojení mezi vizuálním rozhraním v Interface Builder a kódem Swift/Objective-C probíhá prostřednictvím dvou mechanismů: IBOutlet (Interface Builder Outlet) a IBAction (Interface Builder Action). Oba se vytvářejí přetažením se stisknutou klávesou Ctrl z plátna IB do souboru kontroléru.

IBOutlet — anotace deklarující odkaz na UI prvek. Xcode ji automaticky připojí k odpovídajícímu objektu v nib archivu při načítání. Pokud se spojení přeruší (například při přejmenování prvku), aplikace spadne s chybou NSUnknownKeyException (k). IBOutlet se označuje jako weak (k), protože nib vlastní objekt a kontrolér je pouze pozorovatel.

IBAction — metoda volaná při události UI prvku: stisknutí tlačítka, změna textu, přepnutí přepínače. IB propojuje UIControlEvent (k) s metodou přes addTarget:action:forControlEvents: (k). V kódu vypadá IBAction jako běžná metoda s návratovým typem IBAction (dt).

swift
import UIKit

final class LoginViewController: UIViewController {

    @IBOutlet weak var emailTextField: UITextField!
    @IBOutlet weak var passwordTextField: UITextField!
    @IBOutlet weak var loginButton: UIButton!
    @IBOutlet weak var spinner: UIActivityIndicatorView!

    @IBAction private func loginButtonTapped(_ sender: UIButton) {
        guard let email = emailTextField.text, !email.isEmpty,
              let password = passwordTextField.text, !password.isEmpty
        else {
            showAlert(message: "Vyplňte všechna pole")
            return
        }
        loginButton.isEnabled = false
        spinner.startAnimating()
        performLogin(email: email, password: password)
    }

    private func performLogin(email: String, password: String) {
        /// API volání přes URLSession
        let request = LoginRequest(email: email, password: password)
        APIClient.shared.login(request) { [weak self] result in
            DispatchQueue.main.async {
                guard let self else { return }
                self.spinner.stopAnimating()
                self.loginButton.isEnabled = true
                switch result {
                case .success:
                    self.navigateToMainScreen()
                case .failure(let error):
                    self.showAlert(message: error.localizedDescription)
                }
            }
        }
    }

    private func showAlert(message: String) {
        let alert = UIAlertController(
            title: "Chyba",
            message: message,
            preferredStyle: .alert
        )
        alert.addAction(UIAlertAction(title: "OK", style: .default))
        present(alert, animated: true)
    }
}

V příkladu je zobrazeno standardní propojení: IBOutlet pro textová pole, tlačítko a spinner, IBAction pro zpracování stisknutí tlačítka. Všechna tato propojení se nastavují v Interface Builder přes Ctrl+drag. Pokud propojení není nakonfigurováno, bude IBOutlet při běhu nil (v), což způsobí pád při přístupu — proto se IBOutlet deklaruje jako weak var (k s) s implicit unwrap.

@IBDesignable a @IBInspectable: vlastní komponenty

@IBDesignable — Swift anotace umožňující zobrazit vlastní UIView přímo na plátně Interface Builder v reálném čase. Vývojář vidí výsledek změn kódu bez spouštění aplikace. @IBInspectable — anotace pro vlastnosti, která je přidává do panelu Attributes Inspector IB, kde lze hodnoty interaktivně měnit.

Tyto anotace jsou užitečné zejména při vytváření knihoven UI komponent: vlastní tlačítka, vstupní pole s maskou, animované indikátory. IBDesignable používá prepareForInterfaceBuilder() (fn) pro samostatnou kompilaci kódu sestavení, která neovlivňuje hlavní binární soubor aplikace.

swift
import UIKit

@IBDesignable
final class GradientButton: UIButton {

    @IBInspectable var startColor: UIColor = .systemBlue {
        didSet { updateGradient() }
    }

    @IBInspectable var endColor: UIColor = .systemPurple {
        didSet { updateGradient() }
    }

    @IBInspectable var cornerRadius: CGFloat = 12 {
        didSet {
            layer.cornerRadius = cornerRadius
            layer.masksToBounds = true
        }
    }

    private let gradientLayer = CAGradientLayer()

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupGradient()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupGradient()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
    }

    private func setupGradient() {
        layer.insertSublayer(gradientLayer, at: 0)
        updateGradient()
    }

    private func updateGradient() {
        gradientLayer.colors = [startColor.cgColor, endColor.cgColor]
        gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
        gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setupGradient()
    }
}

Ve výše uvedeném kódu je GradientButton IBDesignable komponenta s IBInspectable vlastnostmi startColor (v), endColor (v) a cornerRadius (v). Při přetažení UIView na plátno IB a změně třídy na GradientButton v Identity Inspector se na plátně zobrazí tlačítko s gradientem v reálném čase. Všechny IBInspectable vlastnosti se objeví v panelu Attributes Inspector vpravo.

Důležité: @IBDesignable kompiluje kód celý pro zobrazení v IB, proto by se v něm neměly provádět síťové požadavky ani dlouhé operace. Pro rozlišení se používá #if TARGET_INTERFACE_BUILDER (k) — podmíněná kompilace vylučující kód, který není určen pro IB.

Životní cyklus IB souborů při kompilaci

Proces transformace souborů Interface Builder od vytvoření nib po zobrazení na obrazovce zahrnuje několik fází. Pochopení tohoto cyklu pomáhá diagnostikovat problémy s IB.

Ve fázi sestavení Xcode spouští nástroj ibtool (k, fn) — příkazovou utilitu pro kompilaci .storyboard a .xib souborů do binárního nib formátu. ibtool také provádí validaci: kontroluje správnost constraintů, existenci všech tříd, typy připojení IBOutlet/IBAction. Chyby validace se zobrazují v Issue Navigator Xcode.

Výsledný .nib archiv je umístěn v balíčku aplikace ve složce .nib (s). Velikost nib souboru je výrazně menší než původní XML: binární formát používá optimalizovanou reprezentaci s nahrazením řetězců tokeny a kompresí číselných hodnot. Typická komprese je 50–60% původní velikosti XML.

Za běhu se nib načítá přes UINib(nibName:bundle:) (k) nebo automaticky přes UIStoryboard.instantiateViewController(withIdentifier:) (k). Proces načítání zahrnuje:

  • Deserializaci binárního nib do grafu Objective-C/Swift objektů
  • Vytvoření instancí všech UI prvků z archivu
  • Obnovení propojení IBOutlet a IBAction (outletCollection pro skupiny)
  • Aplikaci Auto Layout constraintů z archivu s ohledem na size class
  • Volání awakeFromNib() (fn) pro každý objekt — vstupní bod pro konfiguraci po načtení

Metoda awakeFromNib() (fn) se volá poté, co jsou všechny IBOutlet již nastaveny, ale před prvním layoutSubviews. To je vhodné pro počáteční konfiguraci: nastavení zaoblení, přidání stínů, lokalizaci textu. Všechny IBOutlet jsou již zaručeně nenulové v awakeFromNib.

Interface Builder vs SwiftUI Preview

S vydáním SwiftUI v roce 2019 získali iOS vývojáři alternativu k Interface Builder — deklarativní framework s Canvas Preview v reálném čase. Rozeberme klíčové rozdíly obou přístupů.

Interface Builder generuje XML popis, který se kompiluje do nib. Rozhraní se vytváří vizuálně, kód odpovídá pouze za logiku. IB vyžaduje nižší práh vstupu pro designéry bez programátorských dovedností, ale je složitý pro revizi kódu (změny XML nejsou vidět v diffu).

SwiftUI Preview — plně kódový vývoj. Rozhraní se popisuje ve Swiftu, náhled se aktualizuje při každém uložení. Žádné XML, žádný nib, žádné riziko přerušení IBOutlet spojení. SwiftUI Preview pracuje rychleji než IB, protože nevyžaduje kompilaci samostatného souboru.

KritériumInterface Builder (UIKit)SwiftUI Preview
Formát souboruXML (.storyboard / .xib) → binární nibSwift kód (bez mezi-souboru)
NáhledIB plátno se zpožděním u složitých viewCanvas Preview v reálném čase
Podpora iOS verzíiOS 2.0+ (všechny verze)iOS 13+
Merge v gitProblémový (jeden XML soubor)Jednoduchý (běžný Swift kód)
Dynamická dataPřes IBOutlet + kód@State (k), @Observable (k)
Vlastní view@IBDesignable (kompilace)SwiftUI View s PreviewProvider
VýkonRychlé načítání nibKompilace Swift za běhu

V praxi výběr mezi IB a SwiftUI Preview závisí na požadavcích projektu. Interface Builder je nepostradatelný pro UIKit aplikace s podporou starých iOS a pro komerční projekty, kde designéři pracují v Xcode bez dovedností Swift. SwiftUI je preferován pro nové projekty cílené na iOS 17+, kde je důležitá rychlost vývoje a reaktivita.

Apple neplánuje odstranit Interface Builder z Xcode. Navíc v Xcode 16 společnost zlepšila výkon plátna IB a přidala podporu pro SwiftUI komponenty přes UIViewRepresentable Bridge. Očekává se, že IB bude podporován nejméně do roku 2030.

Nejlepší postupy práce s Interface Builder

Dlouholeté zkušenosti s iOS vývojem vytvořily sadu doporučení, která snižují počet problémů při používání Interface Builder v komerčních projektech.

Používejte XIB místo Storyboard pro znovupoužitelné komponenty. Každá vlastní buňka tabulky, hlavička nebo zápatí by měly být v samostatném XIB. To usnadňuje merge, zrychluje načítání a umožňuje znovupoužití komponent mezi projekty přes Swift Package Manager nebo CocoaPods.

Nastavte Storyboard References pro rozdělení velkých storyboardů do modulů. Místo jednoho Main.storyboard se 100 obrazovkami vytvořte storyboard pro každý modul (Auth, Profile, Feed) a propojte je přes Storyboard Reference. To zkrátí dobu kompilace ibtool a zjednoduší týmovou práci.

Vyhněte se IBOutlet propojením k File's Owner (k) bez kontroly. Každé propojení by mělo být weak (k) a volitelné (implicitly unwrapped optional je skvělý jen v playground). Při přejmenování IBOutlet ve view Xcode automaticky aktualizuje propojení, ale při ruční úpravě XML je snadné udělat chybu.

  • Po úpravě IB souboru vždy zkontrolujte Show Connection Panel (k) — červené indikátory ukazují přerušená propojení
  • Používejte User Defined Runtime Attributes (k) pro nastavení vlastností bez kódu: layer.cornerRadius, layer.borderWidth, tintColor
  • Seskupujte constrainty v IB podle účelu: constrainty pro velikosti, constrainty pro okraje, constrainty pro poměry
  • Přiřaďte Identifier (k) každému constraintu v Size Inspector — pomáhá při ladění konfliktů
  • Neumísťujte business logiku do awakeFromNib — pouze UI konfiguraci. Logiku — do viewDidLoad nebo samostatných služeb
swift
import UIKit

final class ProfileHeaderView: UIView {

    @IBOutlet weak var avatarImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var bioLabel: UILabel!
    @IBOutlet weak var editButton: UIButton!

    override func awakeFromNib() {
        super.awakeFromNib()
        avatarImageView.layer.cornerRadius = avatarImageView.bounds.width / 2
        avatarImageView.layer.masksToBounds = true
        nameLabel.font = UIFont.preferredFont(forTextStyle: .headline)
        bioLabel.font = UIFont.preferredFont(forTextStyle: .subheadline)
    }

    func configure(with profile: UserProfile) {
        nameLabel.text = profile.fullName
        bioLabel.text = profile.bio
        /// Načtení avatara přes SDWebImage nebo Kingfisher
    }

    static func instantiateFromNib() -> ProfileHeaderView {
        let nib = UINib(nibName: String(describing: self), bundle: nil)
        return nib.instantiate(withOwner: nil).first as! ProfileHeaderView
    }
}

V příkladu je ukázán best practice pro XIB view: statická metoda instantiateFromNib (fn) načítá view z XIB se stejným názvem jako třída. Metoda awakeFromNib (fn) konfiguruje UI (zaoblení, fonty) a metoda configure(with:) (fn) přijímá datový model pro vyplnění. Rozdělení odpovědností usnadňuje testování a znovupoužití.

Často kladené otázky

Čím se Interface Builder liší od SwiftUI Preview?

Interface Builder — vizuální editor pro UIKit s formátem Storyboard/XIB, pracující přes drag-and-drop. SwiftUI Preview — deklarativní náhled v reálném čase, kde se rozhraní popisuje kódem Swift. Oba nástroje jsou integrovány v Xcode, ale IB generuje XML, zatímco SwiftUI kompiluje Swift přímo. IB podporuje iOS 2.0+, SwiftUI — iOS 13+.

Lze použít Interface Builder se SwiftUI?

Ne, Interface Builder není přímo kompatibilní se SwiftUI. SwiftUI používá vlastní deklarativní syntaxi a Canvas Preview. Nicméně UIKit projekty vytvořené přes IB lze integrovat do SwiftUI přes UIViewRepresentable a SwiftUI view lze vložit do UIKit přes UIHostingController. To umožňuje postupnou migraci z IB na SwiftUI.

Co jsou @IBDesignable a @IBInspectable?

@IBDesignable — Swift anotace, která zobrazuje vlastní UIView přímo v Interface Builder v reálném čase bez spouštění aplikace. @IBInspectable — anotace pro vlastnosti, přidávající je do panelu Attributes Inspector IB. Obě anotace urychlují vývoj vlastních UI komponent: stačí změnit vlastnost v inspektoru — změna je okamžitě vidět na plátně.

Jak funguje Auto Layout v Interface Builder?

Auto Layout v Interface Builder nastavuje constrainty přes menu Pin (okraje, šířka, výška) a Align (centrování, baseline). Každý constraint je matematický vztah mezi view. IB zobrazuje chyby červenými čarami, konflikty žlutými varováními. Size Classes v IB umožňují nastavit různé constrainty pro různá zařízení a orientace bez psaní kódu.

Jak propojit kód s Interface Builder přes IBOutlet a IBAction?

IBOutlet — anotace pro odkaz na UI prvek z kódu (například @IBOutlet weak var label: UILabel!). IBAction — anotace pro metodu volanou při události (například @IBAction func buttonTapped(_ sender: UIButton)). Propojení se vytváří přes Ctrl+drag z plátna IB do souboru kontroléru. Xcode automaticky generuje kód propojení při puštění myši.

Shrnutí

  • Interface Builder — vizuální editor v Xcode pro UIKit s historií od 1988 (NeXTSTEP)
  • Storyboard je vhodný pro prototypování, XIB — pro znovupoužitelné komponenty a produkční projekty
  • Auto Layout a Size Classes v IB umožňují vytvářet adaptivní rozhraní bez kódu
  • IBOutlet a IBAction propojují kód s UI přes Ctrl+drag s automatickým generováním Swift vlastností
  • @IBDesignable a @IBInspectable urychlují vývoj vlastních view s náhledem v IB
  • SwiftUI Preview nahrazuje IB pro nové projekty, ale IB zůstává standardem pro UIKit legacy
  • Nejlepší postupy: XIB místo Storyboard, weak IBOutlet, identifikace constraintů, oddělení awakeFromNib a konfigurace

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také