Rozšíření pro iOS v Xamarin.iOS
Video o vytváření rozšíření v iOSu
Rozšíření, jak je představeno v iOSu 8, jsou specializovaná a prezentovaná iOSem ve standardních kontextech, jako je centrum oznámení, jako vlastní typy klávesnice, které uživatel požaduje k provádění specializovaných vstupů nebo jiných kontextů, jako je úprava fotky, kde rozšíření může poskytovat filtry se UIViewControllers speciálními efekty. UIViewControllers
Všechna rozšíření se instaluje ve spojení s aplikací typu kontejner (s oběma elementy napsanými pomocí 64bitových sjednocených rozhraní API) a aktivují se z konkrétního bodu rozšíření v hostitelské aplikaci. A vzhledem k tomu, že se budou používat jako doplňky stávajících systémových funkcí, musí být vysoce výkonné, výkonné a robustní.
Ná přípony
| Typ | Description | Bod rozšíření | Hostitelská aplikace |
|---|---|---|---|
| Akce | Specializovaný editor nebo prohlížeč pro konkrétní typ média | com.apple.ui-services |
Všechny |
| Poskytovatel dokumentů | Umožňuje aplikaci používat vzdálené úložiště dokumentů. | com.apple.fileprovider-ui |
Aplikace používající UIDocumentPickerViewController |
| Klávesnice | Alternativní klávesnice | com.apple.keyboard-service |
Všechny |
| Úpravy fotek | Manipulace s fotkami a úpravy | com.apple.photo-editing |
Photos.app editoru |
| Sdílení | Sdílí data se sociálními sítěmi, službami zasílání zpráv atd. | com.apple.share-services |
Všechny |
| Dnes | Widgety, které se zobrazují na obrazovce Dnes nebo v Centru oznámení | com.apple.widget-extensions |
Dnes a Centrum oznámení |
V iOSu 10 a iOSu 12 byly přidány další extension body. Kompletní tabulku všech podporovaných typů najdete v Průvodci programováním rozšíření aplikace pro iOS.
Omezení
Rozšíření mají řadu omezení, z nichž některá jsou univerzální pro všechny typy (například žádný typ rozšíření nemá přístup k fotoaparátům nebo mikrofonům), zatímco jiné typy rozšíření mohou mít specifická omezení týkající se jejich použití (například vlastní klávesnice nelze použít pro zabezpečená pole pro zadávání dat, například pro hesla).
Univerzální omezení jsou následující:
- Rozhraní uživatelského rozhraní sady Health Kit a sady Event Kit nejsou k dispozici
- Rozšíření nemohou používat rozšířené režimy pozadí.
- Rozšíření nemají přístup k fotoaparátům nebo mikrofonům zařízení (i když mohou přistupovat ke stávajícím mediálním souborům).
- Rozšíření nemohou přijímat data Air Dropu (i když mohou přenášet data přes Air Drop).
- UIActionSheeta UIAlertView nejsou k dispozici. Rozšíření musí používat UIAlertController
- Několik členů UIApplication není k dispozici: UIApplication.SharedApplication, UIApplication.OpenUrl,UIApplication.BeginIgnoringInteractionEventsa UIApplication.EndIgnoringInteractionEvents
- Pro dnešní rozšíření iOS vynucuje limit využití paměti 16 MB.
- Rozšíření klávesnice ve výchozím nastavení nemají přístup k síti. To má vliv na ladění na zařízení (toto omezení se v simulátoru nevynucuje), protože Xamarin.iOS vyžaduje síťový přístup, aby ladění fungovalo. Je možné požádat o přístup k síti nastavením hodnoty v souboru
Requests Open AccessInfo.plist projektu naYes. Další informace o omezeních rozšíření klávesnice najdete v průvodci vlastní klávesnicí společnosti Apple.
Individuální omezení najdete v Průvodci programováním rozšíření aplikací společnostiApple.
Distribuce, instalace a spouštění rozšíření
Rozšíření se distribuují z aplikace kontejneru, která se pak odesíí a distribuuje přes App Store. Rozšíření distribuovaná s aplikací se v tomto okamžiku instalují, ale uživatel musí každé rozšíření explicitně povolit. Různé typy rozšíření jsou povolené různými způsoby. Některé vyžadují, aby uživatel přecházet do Nastavení aplikace a povolit je odtud. Zatímco jiné jsou povolené v místě použití, jako je například povolení rozšíření pro sdílení při odesílání fotky.
Aplikace, ve které se rozšíření používá (kde se uživatel setká s bodem rozšíření), se označuje jako hostitelská aplikace,protože rozšíření hostuje aplikace po spuštění. Aplikace, která instaluje rozšíření, je aplikace typu Kontejner,protože rozšíření obsahovala aplikace, když bylo nainstalováno.
Aplikace typu kontejner obvykle popisuje rozšíření a provede uživatele procesem jeho povolení.
Ladění a vydání verzí rozšíření
Limity paměti pro spouštění rozšíření aplikací jsou výrazně nižší než limity paměti uplatněné na aplikaci v popředí. Simulátory se systémem iOS mají méně omezení, která platí pro rozšíření, a rozšíření můžete spouštět bez jakýchkoli problémů. Spuštění stejného rozšíření v zařízení ale může vést k neočekávaným výsledkům, včetně toho, že rozšíření havaruje nebo ho systém agresivně ukončí. Proto se před odesláním ujistěte, že jste rozšíření sestavíte a otestujte na zařízení.
Měli byste zajistit, aby se pro projekt kontejneru a všechna odkazovaná rozšíření použila následující nastavení:
- Sestavte balíček aplikace v konfiguraci vydání.
- V nastavení projektu sestavení pro iOS nastavte možnost chování Linkeru na Možnost propojení sady Framework SDK pouze nebo Propojit vše.
- V nastavení projektu ladění pro iOS zrušte zaškrtnutí možnosti Povolit ladění a Povolit profilaci.
Životní cyklus rozšíření
Rozšíření může být jednoduché jako jeden UIViewController nebo složitější rozšíření, která prezentuje více obrazovek uživatelského rozhraní. Když se uživatel setká s ná příponami (například při sdílení obrázku), bude mít možnost si vybrat z rozšíření registrovaných pro tento extension point.
Pokud si zvolí jedno z rozšíření vaší aplikace, vytvoří se její instance a zahájí normální životní cyklus UIViewController kontroleru zobrazení. Na rozdíl od normální aplikace, která je pozastavená, ale není obecně ukončena, když s nimi uživatel skončí, se rozšíření načítá, spouštějí a ukončují opakovaně.
Rozšíření mohou komunikovat se svými hostitelskými aplikacemi prostřednictvím objektu NSExtensionContext. Některá rozšíření mají operace, které přijímají asynchronní zpětná volání s výsledky. Tato zpětná volání se budou provádět na vláknech na pozadí a rozšíření to musí vzít v úvahu. například pomocí NSObject.InvokeOnMainThread, pokud chtějí aktualizovat uživatelské rozhraní. Další podrobnosti najdete níže v části Komunikace s hostitelskou aplikací.
Rozšíření a jejich kontejnerové aplikace ve výchozím nastavení spolu nekomunikují, přestože se instalují společně. V některých případech je aplikace Typu kontejner v podstatě prázdný kontejner pro "expedici", jehož účel se po instalaci rozšíření zsloužil. Pokud to ale vyžadují okolnosti, může aplikace Kontejner a rozšíření sdílet prostředky ze společné oblasti. Kromě toho může rozšíření Today požádat svou aplikaci typu Kontejner o otevření adresy URL. Toto chování se zobrazuje ve widgetu odpočítávání událostí.
Vytvoření rozšíření
Rozšíření (a jejich kontejnerové aplikace) musí být 64bitové binární soubory vytvořené pomocí sjednocených rozhraní APIXamarin.iOS. Při vývoji rozšíření budou vaše řešení obsahovat alespoň dva projekty: aplikaci typu kontejner a jeden projekt pro každé rozšíření, které kontejner poskytuje.
Požadavky na projekt aplikace kontejneru
Aplikace typu kontejner použitá k instalaci rozšíření má následující požadavky:
- Musí udržovat odkaz na projekt rozšíření.
- Musí to být úplná aplikace (musí být schopná spustit a úspěšně spustit) i v případě, že neproběhá nic jiného než poskytuje způsob instalace rozšíření.
- Musí mít identifikátor sady prostředků, který je základem identifikátoru sady prostředků projektu rozšíření (další podrobnosti najdete v části níže).
Požadavky na projekt rozšíření
Projekt rozšíření má navíc následující požadavky:
Musí mít identifikátor sady prostředků, který začíná identifikátorem sady kontejnerové aplikace. Pokud má například aplikace kontejneru identifikátor sady prostředků , identifikátor rozšíření může
com.myCompany.ContainerAppbýtcom.myCompany.ContainerApp.MyExtension:
Musí definovat klíč s příslušnou
NSExtensionPointIdentifierhodnotou (například widget Centra oznámenícom.apple.widget-extensionNSExtensionPointIdentifierve svémInfo.plistsouboru.Musí také definovat klíč nebo klíč v souboru s odpovídající
NSExtensionPrincipalClassInfo.plisthodnotou:- Pomocí klíče zadejte název scénáře, který představuje hlavní uživatelské rozhraní
NSExtensionMainStoryboardrozšíření (minus.storyboard). NapříkladMainproMain.storyboardsoubor . - Pomocí klíče
NSExtensionPrincipalClassurčete třídu, která se inicializuje při spuštění rozšíření. Hodnota musí odpovídat hodnotě Register vašeho :

- Pomocí klíče zadejte název scénáře, který představuje hlavní uživatelské rozhraní
Konkrétní typy rozšíření mohou mít další požadavky. Například hlavní třída rozšíření Today nebo Notification Center musí implementovat INCWidgetProviding.
Důležité
Pokud projekt spustíte pomocí jedné ze šablon rozšíření poskytovaných Visual Studio pro Mac, většina (ne-li všechny) tyto požadavky bude poskytnuta a automaticky vám je vyhodí.
Názorný postup
V následujícím názorném postupu vytvoříte příklad widgetu Today, který vypočítá den a počet dní zbývajících v roce:
Vytvoření řešení
Požadované řešení vytvoříte takto:
Nejprve vytvořte nový projekt aplikace pro iOS s jedním zobrazením a klikněte na tlačítko Další:
Zavolejte projekt
TodayContainera klikněte naTodayContainerDalší:Ověřte název Project anázev řešení a kliknutím na tlačítko Vytvořit vytvořte řešení:
V dalším kroku Průzkumník řešeníklikněte pravým tlačítkem na Řešení a přidejte nový projekt rozšíření pro iOS ze šablony Today Extension (Dnes rozšíření):
Zavolejte projekt
DaysRemaininga klikněte naDaysRemainingDalší:Zkontrolujte projekt a kliknutím na tlačítko Vytvořit ho vytvořte:
Výsledné řešení by teď mělo mít dva projekty, jak je vidět tady:
Vytvoření uživatelského rozhraní rozšíření
Dále budete muset navrhnout rozhraní pro widget Today. Můžete to udělat buď pomocí scénáře, nebo vytvořením uživatelského rozhraní v kódu. Obě metody jsou podrobně popsány níže.
Použití scénářů
Pokud chcete vytvořit uživatelské rozhraní pomocí scénáře, proveďte následující:
V Průzkumník řešenípoklikejte na soubor projektu rozšíření a otevřete ho pro úpravy:
Vyberte popisek, který byl automaticky přidán do uživatelského rozhraní pomocí šablony, a na kartě Widget v Průzkumníku vlastnostízadejte Název:
Uložte změny do scénáře.
Použití kódu
Pokud chcete vytvořit uživatelské rozhraní v kódu, proveďte následující:
V Průzkumník řešenívyberte projekt DaysRemaining, přidejte novou třídu a volejte ji :
V části Průzkumník řešenípoklikejte na soubor rozšíření a otevřete ho pro úpravy:
Vyberte zobrazení zdroje (v dolní části obrazovky) a otevřete uzel:
Odeberte
NSExtensionMainStoryboardklíč aNSExtensionPrincipalClasspřidejte s hodnotouCodeBasedViewController:Uložte provedené změny.
V dalším kroku upravte CodeBasedViewController.cs soubor tak, aby vypadal takto:
using System;
using Foundation;
using UIKit;
using NotificationCenter;
using CoreGraphics;
namespace DaysRemaining
{
[Register("CodeBasedViewController")]
public class CodeBasedViewController : UIViewController, INCWidgetProviding
{
public CodeBasedViewController ()
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Add label to view
var TodayMessage = new UILabel (new CGRect (0, 0, View.Frame.Width, View.Frame.Height)) {
TextAlignment = UITextAlignment.Center
};
View.AddSubview (TodayMessage);
// Insert code to power extension here...
}
}
}
Všimněte [Register("CodeBasedViewController")] si, že odpovídá hodnotě, kterou jste zadali pro NSExtensionPrincipalClass výše uvedenou hodnotu.
Kódování rozšíření
Po Uživatelské rozhraní souboru otevřete soubor nebo (na základě metody použité k vytvoření výše uvedeného Uživatelské rozhraní), změňte metodu TodayViewController.csCodeBasedViewController.csTodayViewController.cs a vytvořte ji takto:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Calculate the values
var dayOfYear = DateTime.Now.DayOfYear;
var leapYearExtra = DateTime.IsLeapYear (DateTime.Now.Year) ? 1 : 0;
var daysRemaining = 365 + leapYearExtra - dayOfYear;
// Display the message
if (daysRemaining == 1) {
TodayMessage.Text = String.Format ("Today is day {0}. There is one day remaining in the year.", dayOfYear);
} else {
TodayMessage.Text = String.Format ("Today is day {0}. There are {1} days remaining in the year.", dayOfYear, daysRemaining);
}
}
Pokud používáte metodu založenou Uživatelské rozhraní kódu, nahraďte // Insert code to power extension here... komentář novým kódem z výše uvedeného příkladu. Po volání základní implementace (a vložení popisku pro verzi založenou na kódu) tento kód jednoduchým výpočtem pro získání dne v roce a zbývajícího dne. Pak se zobrazí zpráva v popisku ( TodayMessage ), který jste vytvořili v návrhu uživatelského rozhraní.
Všimněte si, jak se tento proces podobá normálnímu procesu psaní aplikace. Rozšíření má stejný životní cyklus jako kontroler zobrazení v aplikaci s tím rozdílem, že rozšíření nemají režimy pozadí a po dokončení jejich používání uživatelem UIViewController nejsou pozastavená. Rozšíření se místo toho podle potřeby opakovaně inicializovala a zrušte jejich přidělení.
Vytvoření uživatelského rozhraní aplikace typu kontejner
V tomto názorném postupu se aplikace kontejneru jednoduše používá jako metoda k odeslání a instalaci rozšíření a poskytuje žádné vlastní funkce. Upravte soubor TodayContainer a přidejte text definující funkci Rozšíření a Main.storyboard postup jeho instalace:
Uložte změny do scénáře.
Testování rozšíření
Pokud chcete rozšíření otestovat v simulátoru iOS, spusťte aplikaci TodayContainer. Zobrazí se hlavní zobrazení kontejneru:
Potom v simulátoru stiskněte tlačítko Domů, potáhněte prstem dolů z horní části obrazovky, otevřete Centrum oznámení,vyberte kartu Dnes a klikněte na tlačítko Upravit:
Přidejte rozšíření DaysRemaining do zobrazení Dnes a klikněte na tlačítko Hotovo:
Nový widget se přidá do zobrazení Dnes a zobrazí se výsledky:
Komunikace s hostitelskou aplikací
Příklad Rozšíření Today, které jste vytvořili výše, nekomunikuje s její hostitelskou aplikací (obrazovka Dnes). Pokud ano, použije vlastnost ExtensionContext tříd nebo CodeBasedViewController .
Pro rozšíření, která budou přijímat data z hostitelských aplikací, jsou data ve formě pole objektů NSExtensionItem uložených ve vlastnosti InputItems objektu ExtensionContext rozšíření .
Jiná rozšíření, jako jsou rozšíření pro úpravy fotek, mohou rozlišovat mezi tím, že uživatel dokončí nebo zruší používání. To bude signalizováno zpět do hostitelské aplikace prostřednictvím metod CompleteRequest a CancelRequest vlastnosti ExtensionContext.
Další informace najdete v Průvodci programováním rozšíření aplikací společnostiApple.
Komunikace s nadřazenou aplikací
Skupina aplikací umožňuje různým aplikacím (nebo aplikacím a jejím rozšířením) přístup ke sdílenému umístění úložiště souborů. Skupiny aplikací je možné použít pro data, jako jsou:
Další informace najdete v části Skupiny aplikací v naší dokumentaci Práce s funkcemi.
MobileCoreServices
Při práci s rozšířeními můžete pomocí UTI (Uniform Type Identifier) vytvářet data, která se vyměňují mezi aplikací, jinými aplikacemi nebo službami, a manipulovat s nimi.
Statická MobileCoreServices.UTType třída definuje následující vlastnosti pomocného pomocníka, které se vztahují k definicím společnosti kUTType... Apple:
kUTTypeAlembic-AlembickUTTypeAliasFile-AliasFilekUTTypeAliasRecord-AliasRecordkUTTypeAppleICNS-AppleICNSkUTTypeAppleProtectedMPEG4Audio-AppleProtectedMPEG4AudiokUTTypeAppleProtectedMPEG4Video-AppleProtectedMPEG4VideokUTTypeAppleScript-AppleScriptkUTTypeApplication-ApplicationkUTTypeApplicationBundle-ApplicationBundlekUTTypeApplicationFile-ApplicationFilekUTTypeArchive-ArchivekUTTypeAssemblyLanguageSource-AssemblyLanguageSourcekUTTypeAudio-AudiokUTTypeAudioInterchangeFileFormat-AudioInterchangeFileFormatkUTTypeAudiovisualContent-AudiovisualContentkUTTypeAVIMovie-AVIMoviekUTTypeBinaryPropertyList-BinaryPropertyListkUTTypeBMP-BMPkUTTypeBookmark-BookmarkkUTTypeBundle-BundlekUTTypeBzip2Archive-Bzip2ArchivekUTTypeCalendarEvent-CalendarEventkUTTypeCHeader-CHeaderkUTTypeCommaSeparatedText-CommaSeparatedTextkUTTypeCompositeContent-CompositeContentkUTTypeConformsToKey-ConformsToKeykUTTypeContact-ContactkUTTypeContent-ContentkUTTypeCPlusPlusHeader-CPlusPlusHeaderkUTTypeCPlusPlusSource-CPlusPlusSourcekUTTypeCSource-CSourcekUTTypeData-DatabasekUTTypeDelimitedText-DelimitedTextkUTTypeDescriptionKey-DescriptionKeykUTTypeDirectory-DirectorykUTTypeDiskImage-DiskImagekUTTypeElectronicPublication-ElectronicPublicationkUTTypeEmailMessage-EmailMessagekUTTypeExecutable-ExecutablekUTExportedTypeDeclarationsKey-ExportedTypeDeclarationsKeykUTTypeFileURL-FileURLkUTTypeFlatRTFD-FlatRTFDkUTTypeFolder-FolderkUTTypeFont-FontkUTTypeFramework-FrameworkkUTTypeGIF-GIFkUTTypeGNUZipArchive-GNUZipArchivekUTTypeHTML-HTMLkUTTypeICO-ICOkUTTypeIconFileKey-IconFileKeykUTTypeIdentifierKey-IdentifierKeykUTTypeImage-ImagekUTImportedTypeDeclarationsKey-ImportedTypeDeclarationsKeykUTTypeInkText-InkTextkUTTypeInternetLocation-InternetLocationkUTTypeItem-ItemkUTTypeJavaArchive-JavaArchivekUTTypeJavaClass-JavaClasskUTTypeJavaScript-JavaScriptkUTTypeJavaSource-JavaSourcekUTTypeJPEG-JPEGkUTTypeJPEG2000-JPEG2000kUTTypeJSON-JSONkUTType3dObject-k3dObjectkUTTypeLivePhoto-LivePhotokUTTypeLog-LogkUTTypeM3UPlaylist-M3UPlaylistkUTTypeMessage-MessagekUTTypeMIDIAudio-MIDIAudiokUTTypeMountPoint-MountPointkUTTypeMovie-MoviekUTTypeMP3-MP3kUTTypeMPEG-MPEGkUTTypeMPEG2TransportStream-MPEG2TransportStreamkUTTypeMPEG2Video-MPEG2VideokUTTypeMPEG4-MPEG4kUTTypeMPEG4Audio-MPEG4AudiokUTTypeObjectiveCPlusPlusSource-ObjectiveCPlusPlusSourcekUTTypeObjectiveCSource-ObjectiveCSourcekUTTypeOSAScript-OSAScriptkUTTypeOSAScriptBundle-OSAScriptBundlekUTTypePackage-PackagekUTTypePDF-PDFkUTTypePerlScript-PerlScriptkUTTypePHPScript-PHPScriptkUTTypePICT-PICTkUTTypePKCS12-PKCS12kUTTypePlainText-PlainTextkUTTypePlaylist-PlaylistkUTTypePluginBundle-PluginBundlekUTTypePNG-PNGkUTTypePolygon-PolygonkUTTypePresentation-PresentationkUTTypePropertyList-PropertyListkUTTypePythonScript-PythonScriptkUTTypeQuickLookGenerator-QuickLookGeneratorkUTTypeQuickTimeImage-QuickTimeImagekUTTypeQuickTimeMovie-QuickTimeMoviekUTTypeRawImage-RawImagekUTTypeReferenceURLKey-ReferenceURLKeykUTTypeResolvable-ResolvablekUTTypeRTF-RTFkUTTypeRTFD-RTFDkUTTypeRubyScript-RubyScriptkUTTypeScalableVectorGraphics-ScalableVectorGraphicskUTTypeScript-ScriptkUTTypeShellScript-ShellScriptkUTTypeSourceCode-SourceCodekUTTypeSpotlightImporter-SpotlightImporterkUTTypeSpreadsheet-SpreadsheetkUTTypeStereolithography-StereolithographykUTTypeSwiftSource-SwiftSourcekUTTypeSymLink-SymLinkkUTTypeSystemPreferencesPane-SystemPreferencesPanekUTTypeTabSeparatedText-TabSeparatedTextkUTTagClassFilenameExtension-TagClassFilenameExtensionkUTTagClassMIMEType-TagClassMIMETypekUTTypeTagSpecificationKey-TagSpecificationKeykUTTypeText-TextkUTType3DContent-ThreeDContentkUTTypeTIFF-TIFFkUTTypeToDoItem-ToDoItemkUTTypeTXNTextAndMultimediaData-TXNTextAndMultimediaDatakUTTypeUniversalSceneDescription-UniversalSceneDescriptionkUTTypeUnixExecutable-UnixExecutablekUTTypeURL-URLkUTTypeURLBookmarkData-URLBookmarkDatakUTTypeUTF16ExternalPlainText-UTF16ExternalPlainTextkUTTypeUTF16PlainText-UTF16PlainTextkUTTypeUTF8PlainText-UTF8PlainTextkUTTypeUTF8TabSeparatedText-UTF8TabSeparatedTextkUTTypeVCard-VCardkUTTypeVersionKey-VersionKeykUTTypeVideo-VideokUTTypeVolume-VolumekUTTypeWaveformAudio-WaveformAudiokUTTypeWebArchive-WebArchivekUTTypeWindowsExecutable-WindowsExecutablekUTTypeX509Certificate-X509CertificatekUTTypeXML-XMLkUTTypeXMLPropertyList-XMLPropertyListkUTTypeXPCService-XPCServicekUTTypeZipArchive-ZipArchive
Prohlédněte si následující příklad:
using MobileCoreServices;
...
NSItemProvider itemProvider = new NSItemProvider ();
itemProvider.LoadItem(UTType.PropertyList ,null, (item, err) => {
if (err == null) {
NSDictionary results = (NSDictionary )item;
NSString baseURI =
results.ObjectForKey("NSExtensionJavaScriptPreprocessingResultsKey");
}
});
Další informace najdete v části Skupiny aplikací v naší dokumentaci Práce s funkcemi.
Opatření a důležité informace
Rozšíření mají k dispozici výrazně méně paměti než aplikace. Očekává se, že budou rychle a s minimálním vniknutím do uživatele a aplikace, ve které jsou hostované. Rozšíření by ale také mělo poskytovat užitečnou funkci pro aplikaci, která je náročná, pomocí uživatelského rozhraní s brandovou značkou, které uživateli umožní identifikovat vývojáře rozšíření nebo aplikaci typu kontejner, do které patří.
Vzhledem k těmto požadavkům byste měli nasadit pouze rozšíření, která byla důkladně otestovaná a optimalizovaná pro výkon a spotřebu paměti.
Souhrn
Tento dokument se týkal rozšíření, jejich obsahu, typu ná příponových bodů a známých omezení stanovených pro rozšíření v iOSu. Probrali jsme vytváření, distribuci, instalaci a spouštění rozšíření a životní cyklus rozšíření. Poskytl návod k vytvoření jednoduchého widgetu Today, který ukazuje dva způsoby, jak vytvořit uživatelské rozhraní widgetu pomocí scénářů nebo kódu. Ukázal, jak otestovat rozšíření v simulátoru iOSu. Nakonec stručně probral komunikaci s hostitelskou aplikací a několik opatření a předpokladů, které je třeba vzít v úvahu při vývoji rozšíření.


















