Crie aplicativos iOS Swift com o Microsoft Graph
Este tutorial ensina como criar um aplicativo iOS com o Swift que usa a API do Microsoft Graph para recuperar informações de calendário para um usuário.
Dica
Se você preferir apenas baixar o tutorial concluído, poderá baixar ou clonar o GitHub repositório.
Pré-requisitos
Antes de iniciar este tutorial, você deve ter o seguinte instalado em sua máquina de desenvolvimento.
Você também deve ter uma conta pessoal da Microsoft com uma caixa de correio em Outlook.com, ou uma conta de trabalho ou de estudante da Microsoft. Se você não tiver uma conta da Microsoft, há algumas opções para obter uma conta gratuita:
- Você pode se inscrever em uma nova conta pessoal da Microsoft.
- Você pode se inscrever no programa Microsoft 365 desenvolvedor para obter uma assinatura Microsoft 365 gratuita.
Observação
Este tutorial foi escrito usando xcode versão 12.3 e CocoaPods versão 1.10.1 As etapas neste guia podem funcionar com outras versões, mas que não foram testadas.
Comentários
Forneça qualquer comentário sobre este tutorial no repositório GitHub.
Crie um aplicativo iOS Swift
Comece criando um novo projeto Swift.
Abra Xcode. No menu Arquivo, selecione Novo, e Project.
Escolha o modelo de aplicativo e selecione Próximo.
De definir o Nome do Produto como e o
GraphTutorial
idioma como Swift.Preencha os campos restantes e selecione Next.
Escolha um local para o projeto e selecione Criar.
Instalar dependências
Antes de continuar, instale algumas dependências adicionais que você usará mais tarde.
- Biblioteca de Autenticação da Microsoft (MSAL) para iOS para autenticação com o Azure AD.
- Microsoft Graph SDK para Objetivo C para fazer chamadas para o Microsoft Graph.
- Microsoft Graph SDK de Modelos para Objetivo C para objetos fortemente digitados que representam a Microsoft Graph recursos como usuários ou eventos.
Encerrar Xcode.
Abra Terminal e altere o diretório para o local do seu projeto GraphTutorial.
Execute o seguinte comando para criar um Podfile.
pod init
Abra o Podfile e adicione as seguintes linhas logo após a
use_frameworks!
linha.pod 'MSAL', '~> 1.1.13' pod 'MSGraphClientSDK', ' ~> 1.0.0' pod 'MSGraphClientModels', '~> 1.3.0'
Salve o Podfile e execute o seguinte comando para instalar as dependências.
pod install
Depois que o comando é concluído, abra o graphTutorial.xcworkspace recém-criado em Xcode.
Design do aplicativo
Nesta seção, você criará as exibições do aplicativo: uma página de login, um navegador de barra de guias, uma página de boas-vindas e uma página de calendário. Você também criará uma sobreposição de indicador de atividade.
Criar página de login
Expanda a pasta GraphTutorial em Xcode e selecione ViewController.swift.
No Inspetor de Arquivos, altere o Nome do arquivo para
SignInViewController.swift
.Abra SignInViewController.swift e substitua seu conteúdo pelo código a seguir.
import UIKit class SignInViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } @IBAction func signIn() { self.performSegue(withIdentifier: "userSignedIn", sender: nil) } }
Abra Main.storyboard. Expanda a Cena do Controlador de Exibição e selecione Exibir Controlador.
Selecione o Inspetor de Identidade e altere o menu suspenso Classe para SignInViewController.
Selecione a Biblioteca e, em seguida, arraste um botão para o Controlador de Exibição de Login.
Com o botão selecionado, selecione o Inspetor de Atributos e altere o Título do botão para
Sign In
.Com o botão selecionado, selecione o botão Alinhar na parte inferior do storyboard. Selecione horizontalmente no contêiner e verticalmente em restrições de contêiner, deixe seus valores como 0 e selecione Adicionar 2 restrições.
Selecione o Controlador de Exibição de Login e selecione o Inspetor de Conexões.
Em Ações Recebidas, arraste o círculo não preenchido ao lado de entrar no botão. Selecione Tocar para Dentro no menu pop-up.
Criar barra de guias
Selecione a Biblioteca e arraste um Controlador de Barra de Guias para o storyboard.
Selecione o Controlador de Exibição de Login e selecione o Inspetor de Conexões.
Em Segues Disparados, arraste o círculo não preenchido ao lado do manual para o Controlador da Barra de Guias no storyboard. Selecione Apresentar Modally no menu pop-up.
Selecione o segue que você acabou de adicionar e selecione o Inspetor de Atributos. De definir o campo Identificador como
userSignedIn
, e definir Apresentação como Tela Inteira.Selecione a Cena do Item 1 e selecione o Inspetor de Conexões.
Em Segues Disparados, arraste o círculo não preenchido ao lado do manual para o Controlador de Exibição de Login no storyboard. Selecione Apresentar Modally no menu pop-up.
Selecione o segue que você acabou de adicionar e selecione o Inspetor de Atributos. De definir o campo Identificador como
userSignedOut
, e definir Apresentação como Tela Inteira.
Criar página de boas-vindas
Selecione o arquivo Assets.xcassets.
No menu Editor, selecione Adicionar Novo Ativo e, em seguida, Conjunto de Imagens.
Selecione o novo ativo Image e use o Inspetor de Atributos para definir seu Nome como
DefaultUserPhoto
.Adicione qualquer imagem que você gosta de servir como uma foto de perfil de usuário padrão.
Crie um novo arquivo da Classe Cocoa Touch na pasta GraphTutorial chamada
WelcomeViewController
. Escolha UIViewController na Subclasse do campo.Abra WelcomeViewController.swift e substitua seu conteúdo pelo código a seguir.
import UIKit class WelcomeViewController: UIViewController { @IBOutlet var userProfilePhoto: UIImageView! @IBOutlet var userDisplayName: UILabel! @IBOutlet var userEmail: UILabel! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // TEMPORARY self.userProfilePhoto.image = UIImage(imageLiteralResourceName: "DefaultUserPhoto") self.userDisplayName.text = "Default User" self.userEmail.text = "default@contoso.com" } @IBAction func signOut() { self.performSegue(withIdentifier: "userSignedOut", sender: nil) } }
Abra Main.storyboard. Selecione a Cena do Item 1 e selecione o Inspetor de Identidade. Altere o valor class para WelcomeViewController.
Usando a Biblioteca, adicione os itens a seguir à Cena do Item 1.
- One Image View
- Dois rótulos
- Um botão
Usando o Inspetor de Conexões, faça as seguintes conexões.
- Vincule a saída userDisplayName ao primeiro rótulo.
- Vincule a saída userEmail ao segundo rótulo.
- Vincule a saída userProfilePhoto ao exibição de imagem.
- Vincule a ação signOut recebida ao botão Touch Up Inside.
Selecione o exibição de imagem e selecione o Inspetor de Tamanhos.
De definir Width e Height como 196.
Use o botão Alinhar para adicionar a restrição Horizontalmente no contêiner com um valor 0.
Use o botão Adicionar Novas Restrições (ao lado do botão Alinhar) para adicionar as seguintes restrições:
- Alinhar Superior a: Cofre Área, valor: 0
- Espaço inferior para: Nome de Exibição do Usuário, valor: Standard
- Altura, valor: 196
- Largura, valor: 196
Selecione o primeiro rótulo e, em seguida, use o botão Alinhar para adicionar a restrição Horizontalmente no contêiner com um valor 0.
Use o botão Adicionar Novas Restrições para adicionar as seguintes restrições:
- Espaço Superior para: Foto do Perfil de Usuário, valor: Padrão
- Espaço inferior para: Email do Usuário, valor: Standard
Selecione o segundo rótulo e selecione o Inspetor de Atributos.
Altere a cor para Cor cinza escuro e altere a Fonte para o Sistema 12.0.
Use o botão Alinhar para adicionar a restrição Horizontalmente no contêiner com um valor 0.
Use o botão Adicionar Novas Restrições para adicionar as seguintes restrições:
- Espaço Superior para: Nome de Exibição do Usuário, valor: Padrão
- Espaço inferior para: Sair, valor: 14
Selecione o botão e selecione o Inspetor de Atributos.
Altere o título para
Sign Out
.Use o botão Alinhar para adicionar a restrição Horizontalmente no contêiner com um valor 0.
Use o botão Adicionar Novas Restrições para adicionar as seguintes restrições:
- Espaço Superior para: Email do Usuário, valor: 14
Selecione o item da barra de guias na parte inferior da cena e selecione o Inspetor de Atributos. Altere o título para
Me
.
A cena de boas-vindas deve ser semelhante a essa depois de terminar.
Criar página de calendário
Crie um novo arquivo da Classe Cocoa Touch na pasta GraphTutorial chamada
CalendarViewController
. Escolha UIViewController na Subclasse do campo.Abra CalendarViewController.swift e substitua seu conteúdo pelo código a seguir.
import UIKit class CalendarViewController: UIViewController { @IBOutlet var calendarJSON: UITextView! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // TEMPORARY calendarJSON.text = "Calendar" calendarJSON.sizeToFit() } }
Abra Main.storyboard. Selecione a Cena do Item 2 e selecione o Inspetor de Identidade. Altere o valor class para CalendarViewController.
Usando a Biblioteca, adicione um Texto Exibição à Cena do Item 2.
Selecione o exibição de texto que você acabou de adicionar. No menu Editor, escolha Incorporar em, em seguida, Exibir Rolagem.
Resize a exibição de rolagem e a exibição de texto para assumir toda a tela.
Usando o Inspetor de Conexões, conecte a saída calendarJSON ao exibição de texto.
Selecione o item da barra de guias na parte inferior da cena e selecione o Inspetor de Atributos. Altere o título para
Calendar
.No menu Editor, selecione Resolver Problemas de Layout Automático e, em seguida, selecione Adicionar Restrições Ausentes abaixo de Todos os Exibições no Controlador de Modo de Exibição de Calendário.
A cena do calendário deve ser semelhante a essa depois de terminar.
Criar indicador de atividade
Crie um novo arquivo da Classe Cocoa Touch na pasta GraphTutorial chamada
SpinnerViewController
. Escolha UIViewController na Subclasse do campo.Abra SpinnerViewController.swift e substitua seu conteúdo pelo código a seguir.
import UIKit class SpinnerViewController: UIViewController { var spinner = UIActivityIndicatorView(style: .large) override func loadView() { view = UIView() view.backgroundColor = UIColor(white: 0, alpha: 0.7) spinner.translatesAutoresizingMaskIntoConstraints = false spinner.startAnimating() view.addSubview(spinner) spinner.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true spinner.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true } public func start(container: UIViewController) { container.addChild(self) self.view.frame = container.view.frame container.view.addSubview(self.view) self.didMove(toParent: container) } public func stop() { self.willMove(toParent: nil) self.view.removeFromSuperview() self.removeFromParent() } }
O aplicativo de teste
Salve suas alterações e iniciar o aplicativo. Você deve ser capaz de mover entre as telas usando os botões Entrar e Sair e a barra de guias.
Registrar o aplicativo no portal
Neste exercício, você criará um novo aplicativo nativo do Azure AD usando o Azure Active Directory de administração.
Abra um navegador, navegue até o centro de administração do Azure Active Directory e faça logon usando uma conta pessoal (também conhecida como conta da Microsoft) ou Conta Corporativa ou de Estudante.
Selecione Azure Active Directory na navegação esquerda e selecione Registros de aplicativos em Gerenciar.
Selecione Novo registro. Na página Registrar um aplicativo, defina os valores da seguinte forma.
- Defina Nome para
iOS Swift Graph Tutorial
. - Defina Tipos de conta com suporte para Contas em qualquer diretório organizacional e contas pessoais da Microsoft.
- Deixe o URI de Redirecionamento vazio.
- Defina Nome para
Selecione Registrar. Na página tutorial do iOS Swift Graph, copie o valor da ID do Aplicativo (cliente) e salve-a, você precisará dele na próxima etapa.
Selecione Autenticação em Gerenciar. Selecione Adicionar uma plataforma, em seguida, iOS /macOS.
Insira a ID do Pacote do seu aplicativo e selecione Configurar, em seguida, selecione Feito.
Adicionar autenticação do Azure AD
Neste exercício, você estenderá o aplicativo do exercício anterior para dar suporte à autenticação com o Azure AD. Isso é necessário para obter o token de acesso OAuth necessário para chamar o microsoft Graph. Para fazer isso, você integrará a Biblioteca de Autenticação da Microsoft (MSAL) para iOS ao aplicativo.
Crie um novo arquivo de Lista de Propriedades no projeto GraphTutorial chamado AuthSettings.plist.
Adicione os itens a seguir ao arquivo no dicionário raiz.
Chave Tipo Valor AppId
Cadeia de caracteres A ID do aplicativo do portal do Azure GraphScopes
Matriz Três valores de cadeia de User.Read
caracteres:MailboxSettings.Read
, eCalendars.ReadWrite
Importante
Se você estiver usando o controle de origem como git, agora seria um bom momento para excluir o arquivo AuthSettings.plist do controle de origem para evitar o vazamento inadvertida da ID do aplicativo.
Implementar login
Nesta seção, você configurará o projeto para MSAL, criará uma classe gerenciador de autenticação e atualizará o aplicativo para entrar e sair.
Configurar projeto para MSAL
Adicione um novo grupo de chaveiros aos recursos do seu projeto.
- Selecione o projeto GraphTutorial e, em seguida, Assinando & Recursos.
- Selecione + Funcionalidade e clique duas vezes em Compartilhamento de Chave.
- Adicione um grupo de chaveiros com o valor
com.microsoft.adalcache
.
Controle clique em Info.plist e selecione Abrir como, em seguida, Código-fonte.
Adicione o seguinte dentro do
<dict>
elemento.<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>msauth.$(PRODUCT_BUNDLE_IDENTIFIER)</string> </array> </dict> </array> <key>LSApplicationQueriesSchemes</key> <array> <string>msauthv2</string> <string>msauthv3</string> </array>
Abra AppDelegate.swift e adicione a seguinte instrução de importação na parte superior do arquivo.
import MSAL
Adicione a função a seguir à classe
AppDelegate
.func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { guard let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String else { return false } return MSALPublicClientApplication.handleMSALResponse(url, sourceApplication: sourceApplication) }
Criar gerenciador de autenticação
Crie um novo Arquivo Swift no projeto GraphTutorial chamado AuthenticationManager.swift. Adicione o código a seguir a esse arquivo.
import Foundation import MSAL import MSGraphClientSDK // Implement the MSAuthenticationProvider interface so // this class can be used as an auth provider for the Graph SDK class AuthenticationManager: NSObject, MSAuthenticationProvider { // Implement singleton pattern static let instance = AuthenticationManager() private let publicClient: MSALPublicClientApplication? private let appId: String private let graphScopes: Array<String> private override init() { // Get app ID and scopes from AuthSettings.plist let bundle = Bundle.main let authConfigPath = bundle.path(forResource: "AuthSettings", ofType: "plist")! let authConfig = NSDictionary(contentsOfFile: authConfigPath)! self.appId = authConfig["AppId"] as! String self.graphScopes = authConfig["GraphScopes"] as! Array<String> do { // Create the MSAL client try self.publicClient = MSALPublicClientApplication(clientId: self.appId) } catch { print("Error creating MSAL public client: \(error)") self.publicClient = nil } } // Required function for the MSAuthenticationProvider interface func getAccessToken(for authProviderOptions: MSAuthenticationProviderOptions!, andCompletion completion: ((String?, Error?) -> Void)!) { getTokenSilently(completion: completion) } public func getTokenInteractively(parentView: UIViewController, completion: @escaping(_ accessToken: String?, Error?) -> Void) { let webParameters = MSALWebviewParameters(authPresentationViewController: parentView) let interactiveParameters = MSALInteractiveTokenParameters(scopes: self.graphScopes, webviewParameters: webParameters) interactiveParameters.promptType = MSALPromptType.selectAccount // Call acquireToken to open a browser so the user can sign in publicClient?.acquireToken(with: interactiveParameters, completionBlock: { (result: MSALResult?, error: Error?) in guard let tokenResult = result, error == nil else { print("Error getting token interactively: \(String(describing: error))") completion(nil, error) return } print("Got token interactively: \(tokenResult.accessToken)") completion(tokenResult.accessToken, nil) }) } public func getTokenSilently(completion: @escaping(_ accessToken: String?, Error?) -> Void) { // Check if there is an account in the cache var userAccount: MSALAccount? do { userAccount = try publicClient?.allAccounts().first } catch { print("Error getting account: \(error)") } if (userAccount != nil) { // Attempt to get token silently let silentParameters = MSALSilentTokenParameters(scopes: self.graphScopes, account: userAccount!) publicClient?.acquireTokenSilent(with: silentParameters, completionBlock: { (result: MSALResult?, error: Error?) in guard let tokenResult = result, error == nil else { print("Error getting token silently: \(String(describing: error))") completion(nil, error) return } print("Got token silently: \(tokenResult.accessToken)") completion(tokenResult.accessToken, nil) }) } else { print("No account in cache") completion(nil, NSError(domain: "AuthenticationManager", code: MSALError.interactionRequired.rawValue, userInfo: nil)) } } public func signOut() -> Void { do { // Remove all accounts from the cache let accounts = try publicClient?.allAccounts() try accounts!.forEach({ (account: MSALAccount) in try publicClient?.remove(account) }) } catch { print("Sign out error: \(String(describing: error))") } } }
Adicionar entrar e sair
Abra SignInViewController.swift e substitua seu conteúdo pelo código a seguir.
import UIKit class SignInViewController: UIViewController { private let spinner = SpinnerViewController() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. // See if a user is already signed in spinner.start(container: self) AuthenticationManager.instance.getTokenSilently { (token: String?, error: Error?) in DispatchQueue.main.async { self.spinner.stop() guard let _ = token, error == nil else { // If there is no token or if there's an error, // no user is signed in, so stay here return } // Since we got a token, a user is signed in // Go to welcome page self.performSegue(withIdentifier: "userSignedIn", sender: nil) } } } @IBAction func signIn() { spinner.start(container: self) // Do an interactive sign in AuthenticationManager.instance.getTokenInteractively(parentView: self) { (token: String?, error: Error?) in DispatchQueue.main.async { self.spinner.stop() guard let _ = token, error == nil else { // Show the error and stay on the sign-in page let alert = UIAlertController(title: "Error signing in", message: error.debugDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alert, animated: true) return } // Signed in successfully // Go to welcome page self.performSegue(withIdentifier: "userSignedIn", sender: nil) } } } }
Abra WelcomeViewController.swift e substitua a função
signOut
existente pelo seguinte.@IBAction func signOut() { AuthenticationManager.instance.signOut() self.performSegue(withIdentifier: "userSignedOut", sender: nil) }
Salve suas alterações e reinicie o aplicativo no Simulador.
Se você entrar no aplicativo, verá um token de acesso exibido na janela de saída em Xcode.
Obter detalhes do usuário
Nesta seção, você criará uma classe auxiliar para manter todas as chamadas para o Microsoft Graph e atualizar a para usar essa nova classe para obter o usuário WelcomeViewController
conectado.
Crie um novo Arquivo Swift no projeto GraphTutorial chamado GraphManager.swift. Adicione o código a seguir a esse arquivo.
import Foundation import MSGraphClientSDK import MSGraphClientModels class GraphManager { // Implement singleton pattern static let instance = GraphManager() private let client: MSHTTPClient? public var userTimeZone: String private init() { client = MSClientFactory.createHTTPClient(with: AuthenticationManager.instance) userTimeZone = "UTC" } public func getMe(completion: @escaping(MSGraphUser?, Error?) -> Void) { // GET /me let select = "$select=displayName,mail,mailboxSettings,userPrincipalName" let meRequest = NSMutableURLRequest(url: URL(string: "\(MSGraphBaseURL)/me?\(select)")!) let meDataTask = MSURLSessionDataTask(request: meRequest, client: self.client, completion: { (data: Data?, response: URLResponse?, graphError: Error?) in guard let meData = data, graphError == nil else { completion(nil, graphError) return } do { // Deserialize response as a user let user = try MSGraphUser(data: meData) completion(user, nil) } catch { completion(nil, error) } }) // Execute the request meDataTask?.execute() } }
Abra WelcomeViewController.swift e adicione a seguinte
import
instrução na parte superior do arquivo.import MSGraphClientModels
Adicione a propriedade a seguir à classe
WelcomeViewController
.private let spinner = SpinnerViewController()
Substitua o existente
viewDidLoad
pelo código a seguir.override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.spinner.start(container: self) // Get the signed-in user self.userProfilePhoto.image = UIImage(imageLiteralResourceName: "DefaultUserPhoto") GraphManager.instance.getMe { (user: MSGraphUser?, error: Error?) in DispatchQueue.main.async { self.spinner.stop() guard let currentUser = user, error == nil else { print("Error getting user: \(String(describing: error))") return } // Set display name self.userDisplayName.text = currentUser.displayName ?? "Mysterious Stranger" self.userDisplayName.sizeToFit() // AAD users have email in the mail attribute // Personal accounts have email in the userPrincipalName attribute self.userEmail.text = currentUser.mail ?? currentUser.userPrincipalName ?? "" self.userEmail.sizeToFit() // Save the user's time zone GraphManager.instance.userTimeZone = currentUser.mailboxSettings?.timeZone ?? "UTC" } } }
Se você salvar suas alterações e reiniciar o aplicativo agora, depois de entrar na interface do usuário é atualizado com o nome de exibição do usuário e o endereço de email.
Obter uma exibição de calendário
Neste exercício, você incorporará o microsoft Graph no aplicativo. Para este aplicativo, você usará o Microsoft Graph SDK para Objetivo C para fazer chamadas para o Microsoft Graph.
Obtenha eventos de calendário do Outlook
Nesta seção, você estenderá a classe para adicionar uma função para obter os eventos do usuário para a semana atual e atualizar para GraphManager
CalendarViewController
usar essas novas funções.
Abra GraphManager.swift e adicione o método a seguir à
GraphManager
classe.public func getCalendarView(viewStart: String, viewEnd: String, completion: @escaping(Data?, Error?) -> Void) { // GET /me/calendarview // Set start and end of the view let start = "startDateTime=\(viewStart)" let end = "endDateTime=\(viewEnd)" // Only return these fields in results let select = "$select=subject,organizer,start,end" // Sort results by when they were created, newest first let orderBy = "$orderby=start/dateTime" // Request at most 25 results let top = "$top=25" let eventsRequest = NSMutableURLRequest(url: URL(string: "\(MSGraphBaseURL)/me/calendarview?\(start)&\(end)&\(select)&\(orderBy)&\(top)")!) // Add the Prefer: outlook.timezone header to get start and end times // in user's time zone eventsRequest.addValue("outlook.timezone=\"\(self.userTimeZone)\"", forHTTPHeaderField: "Prefer") let eventsDataTask = MSURLSessionDataTask(request: eventsRequest, client: self.client, completion: { (data: Data?, response: URLResponse?, graphError: Error?) in guard let eventsData = data, graphError == nil else { completion(nil, graphError) return } // TEMPORARY completion(eventsData, nil) }) // Execute the request eventsDataTask?.execute() }
Observação
Considere o que o código
getCalendarView
está fazendo.- O URL que será chamado é
/v1.0/me/calendarview
.- Os
startDateTime
endDateTime
parâmetros e consulta definem o início e o fim do exibição de calendário. - O parâmetro de consulta limita os campos retornados para cada evento para apenas aqueles que o
select
exibição realmente usará. - O
orderby
parâmetro de consulta classifica os resultados por hora de início. - O
top
parâmetro de consulta solicita 25 resultados por página. - o header faz com que o microsoft Graph retornar os horários de início e término de cada evento no
Prefer: outlook.timezone
fuso horário do usuário.
- Os
- O URL que será chamado é
Crie um novo Arquivo Swift no projeto GraphTutorial chamado GraphToIana.swift. Adicione o código a seguir a esse arquivo.
import Foundation // Basic lookup for mapping Windows time zone identifiers to // IANA identifiers // Mappings taken from // https://github.com/unicode-org/cldr/blob/master/common/supplemental/windowsZones.xml class GraphToIana { private static let timeZoneMap = [ "Dateline Standard Time" : "Etc/GMT+12", "UTC-11" : "Etc/GMT+11", "Aleutian Standard Time" : "America/Adak", "Hawaiian Standard Time" : "Pacific/Honolulu", "Marquesas Standard Time" : "Pacific/Marquesas", "Alaskan Standard Time" : "America/Anchorage", "UTC-09" : "Etc/GMT+9", "Pacific Standard Time (Mexico)" : "America/Tijuana", "UTC-08" : "Etc/GMT+8", "Pacific Standard Time" : "America/Los_Angeles", "US Mountain Standard Time" : "America/Phoenix", "Mountain Standard Time (Mexico)" : "America/Chihuahua", "Mountain Standard Time" : "America/Denver", "Central America Standard Time" : "America/Guatemala", "Central Standard Time" : "America/Chicago", "Easter Island Standard Time" : "Pacific/Easter", "Central Standard Time (Mexico)" : "America/Mexico_City", "Canada Central Standard Time" : "America/Regina", "SA Pacific Standard Time" : "America/Bogota", "Eastern Standard Time (Mexico)" : "America/Cancun", "Eastern Standard Time" : "America/New_York", "Haiti Standard Time" : "America/Port-au-Prince", "Cuba Standard Time" : "America/Havana", "US Eastern Standard Time" : "America/Indianapolis", "Turks And Caicos Standard Time" : "America/Grand_Turk", "Paraguay Standard Time" : "America/Asuncion", "Atlantic Standard Time" : "America/Halifax", "Venezuela Standard Time" : "America/Caracas", "Central Brazilian Standard Time" : "America/Cuiaba", "SA Western Standard Time" : "America/La_Paz", "Pacific SA Standard Time" : "America/Santiago", "Newfoundland Standard Time" : "America/St_Johns", "Tocantins Standard Time" : "America/Araguaina", "E. South America Standard Time" : "America/Sao_Paulo", "SA Eastern Standard Time" : "America/Cayenne", "Argentina Standard Time" : "America/Buenos_Aires", "Greenland Standard Time" : "America/Godthab", "Montevideo Standard Time" : "America/Montevideo", "Magallanes Standard Time" : "America/Punta_Arenas", "Saint Pierre Standard Time" : "America/Miquelon", "Bahia Standard Time" : "America/Bahia", "UTC-02" : "Etc/GMT+2", "Azores Standard Time" : "Atlantic/Azores", "Cape Verde Standard Time" : "Atlantic/Cape_Verde", "UTC" : "Etc/GMT", "GMT Standard Time" : "Europe/London", "Greenwich Standard Time" : "Atlantic/Reykjavik", "Sao Tome Standard Time" : "Africa/Sao_Tome", "Morocco Standard Time" : "Africa/Casablanca", "W. Europe Standard Time" : "Europe/Berlin", "Central Europe Standard Time" : "Europe/Budapest", "Romance Standard Time" : "Europe/Paris", "Central European Standard Time" : "Europe/Warsaw", "W. Central Africa Standard Time" : "Africa/Lagos", "Jordan Standard Time" : "Asia/Amman", "GTB Standard Time" : "Europe/Bucharest", "Middle East Standard Time" : "Asia/Beirut", "Egypt Standard Time" : "Africa/Cairo", "E. Europe Standard Time" : "Europe/Chisinau", "Syria Standard Time" : "Asia/Damascus", "West Bank Standard Time" : "Asia/Hebron", "South Africa Standard Time" : "Africa/Johannesburg", "FLE Standard Time" : "Europe/Kiev", "Israel Standard Time" : "Asia/Jerusalem", "Kaliningrad Standard Time" : "Europe/Kaliningrad", "Sudan Standard Time" : "Africa/Khartoum", "Libya Standard Time" : "Africa/Tripoli", "Namibia Standard Time" : "Africa/Windhoek", "Arabic Standard Time" : "Asia/Baghdad", "Turkey Standard Time" : "Europe/Istanbul", "Arab Standard Time" : "Asia/Riyadh", "Belarus Standard Time" : "Europe/Minsk", "Russian Standard Time" : "Europe/Moscow", "E. Africa Standard Time" : "Africa/Nairobi", "Iran Standard Time" : "Asia/Tehran", "Arabian Standard Time" : "Asia/Dubai", "Astrakhan Standard Time" : "Europe/Astrakhan", "Azerbaijan Standard Time" : "Asia/Baku", "Russia Time Zone 3" : "Europe/Samara", "Mauritius Standard Time" : "Indian/Mauritius", "Saratov Standard Time" : "Europe/Saratov", "Georgian Standard Time" : "Asia/Tbilisi", "Volgograd Standard Time" : "Europe/Volgograd", "Caucasus Standard Time" : "Asia/Yerevan", "Afghanistan Standard Time" : "Asia/Kabul", "West Asia Standard Time" : "Asia/Tashkent", "Ekaterinburg Standard Time" : "Asia/Yekaterinburg", "Pakistan Standard Time" : "Asia/Karachi", "Qyzylorda Standard Time" : "Asia/Qyzylorda", "India Standard Time" : "Asia/Calcutta", "Sri Lanka Standard Time" : "Asia/Colombo", "Nepal Standard Time" : "Asia/Katmandu", "Central Asia Standard Time" : "Asia/Almaty", "Bangladesh Standard Time" : "Asia/Dhaka", "Omsk Standard Time" : "Asia/Omsk", "Myanmar Standard Time" : "Asia/Rangoon", "SE Asia Standard Time" : "Asia/Bangkok", "Altai Standard Time" : "Asia/Barnaul", "W. Mongolia Standard Time" : "Asia/Hovd", "North Asia Standard Time" : "Asia/Krasnoyarsk", "N. Central Asia Standard Time" : "Asia/Novosibirsk", "Tomsk Standard Time" : "Asia/Tomsk", "China Standard Time" : "Asia/Shanghai", "North Asia East Standard Time" : "Asia/Irkutsk", "Singapore Standard Time" : "Asia/Singapore", "W. Australia Standard Time" : "Australia/Perth", "Taipei Standard Time" : "Asia/Taipei", "Ulaanbaatar Standard Time" : "Asia/Ulaanbaatar", "Aus Central W. Standard Time" : "Australia/Eucla", "Transbaikal Standard Time" : "Asia/Chita", "Tokyo Standard Time" : "Asia/Tokyo", "North Korea Standard Time" : "Asia/Pyongyang", "Korea Standard Time" : "Asia/Seoul", "Yakutsk Standard Time" : "Asia/Yakutsk", "Cen. Australia Standard Time" : "Australia/Adelaide", "AUS Central Standard Time" : "Australia/Darwin", "E. Australia Standard Time" : "Australia/Brisbane", "AUS Eastern Standard Time" : "Australia/Sydney", "West Pacific Standard Time" : "Pacific/Port_Moresby", "Tasmania Standard Time" : "Australia/Hobart", "Vladivostok Standard Time" : "Asia/Vladivostok", "Lord Howe Standard Time" : "Australia/Lord_Howe", "Bougainville Standard Time" : "Pacific/Bougainville", "Russia Time Zone 10" : "Asia/Srednekolymsk", "Magadan Standard Time" : "Asia/Magadan", "Norfolk Standard Time" : "Pacific/Norfolk", "Sakhalin Standard Time" : "Asia/Sakhalin", "Central Pacific Standard Time" : "Pacific/Guadalcanal", "Russia Time Zone 11" : "Asia/Kamchatka", "New Zealand Standard Time" : "Pacific/Auckland", "UTC+12" : "Etc/GMT-12", "Fiji Standard Time" : "Pacific/Fiji", "Chatham Islands Standard Time" : "Pacific/Chatham", "UTC+13" : "Etc/GMT-13", "Tonga Standard Time" : "Pacific/Tongatapu", "Samoa Standard Time" : "Pacific/Apia", "Line Islands Standard Time" : "Pacific/Kiritimati" ] public static func getIanaIdentifier(graphIdentifer: String) -> String { // If a mapping was not found, assume the value passed // was already an IANA identifier return timeZoneMap[graphIdentifer] ?? graphIdentifer } }
Isso faz uma análise simples para encontrar um identificador de fuso horário IANA com base no nome do fuso horário retornado pela Microsoft Graph.
Abra CalendarViewController.swift e substitua todo o conteúdo pelo código a seguir.
import UIKit import MSGraphClientModels class CalendarViewController: UIViewController { @IBOutlet var calendarJSON: UITextView! private let spinner = SpinnerViewController() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.spinner.start(container: self) // Calculate the start and end of the current week let timeZone = GraphToIana.getIanaIdentifier(graphIdentifer: GraphManager.instance.userTimeZone) let now = Date() var calendar = Calendar(identifier: .gregorian) calendar.timeZone = TimeZone(identifier: timeZone)! let startOfWeek = calendar.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: now).date! let endOfWeek = calendar.date(byAdding: .day, value: 7, to: startOfWeek)! // Convert start and end to ISO 8601 strings let isoFormatter = ISO8601DateFormatter() let viewStart = isoFormatter.string(from: startOfWeek) let viewEnd = isoFormatter.string(from: endOfWeek) GraphManager.instance.getCalendarView(viewStart: viewStart, viewEnd: viewEnd) { (data: Data?, error: Error?) in DispatchQueue.main.async { self.spinner.stop() // TEMPORARY guard let eventsData = data, error == nil else { self.calendarJSON.text = error.debugDescription return } let jsonString = String(data: eventsData, encoding: .utf8) self.calendarJSON.text = jsonString self.calendarJSON.sizeToFit() } } } }
Agora você pode executar o aplicativo, entrar e tocar no item de navegação Calendário no menu. Você deve ver um despejo JSON dos eventos no aplicativo.
Exibir os resultados
Agora você pode substituir o despejo JSON por algo para exibir os resultados de maneira amigável. Nesta seção, você modificará a função para retornar objetos fortemente digitados e modificará para usar um exibição de tabela getCalendarView
CalendarViewController
para renderizar os eventos.
Abra GraphManager.swift. Substitua a função
getCalendarView
existente pela seguinte.public func getCalendarView(viewStart: String, viewEnd: String, completion: @escaping([MSGraphEvent]?, Error?) -> Void) { // GET /me/calendarview // Set start and end of the view let start = "startDateTime=\(viewStart)" let end = "endDateTime=\(viewEnd)" // Only return these fields in results let select = "$select=subject,organizer,start,end" // Sort results by when they were created, newest first let orderBy = "$orderby=start/dateTime" // Request at most 25 results let top = "$top=25" let eventsRequest = NSMutableURLRequest(url: URL(string: "\(MSGraphBaseURL)/me/calendarview?\(start)&\(end)&\(select)&\(orderBy)&\(top)")!) // Add the Prefer: outlook.timezone header to get start and end times // in user's time zone eventsRequest.addValue("outlook.timezone=\"\(self.userTimeZone)\"", forHTTPHeaderField: "Prefer") let eventsDataTask = MSURLSessionDataTask(request: eventsRequest, client: self.client, completion: { (data: Data?, response: URLResponse?, graphError: Error?) in guard let eventsData = data, graphError == nil else { completion(nil, graphError) return } do { // Deserialize response as events collection let eventsCollection = try MSCollection(data: eventsData) var eventArray: [MSGraphEvent] = [] eventsCollection.value.forEach({ (rawEvent: Any) in // Convert JSON to a dictionary guard let eventDict = rawEvent as? [String: Any] else { return } // Deserialize event from the dictionary let event = MSGraphEvent(dictionary: eventDict)! eventArray.append(event) }) // Return the array completion(eventArray, nil) } catch { completion(nil, error) } }) // Execute the request eventsDataTask?.execute() }
Crie um novo arquivo da Classe Cocoa Touch no projeto GraphTutorial chamado
CalendarTableViewController.swift
. Escolha UITableViewController na Subclasse do campo.Abra CalendarTableViewController.swift e substitua seu conteúdo pelo seguinte.
import UIKit import MSGraphClientModels class CalendarTableViewController: UITableViewController { private let tableCellIdentifier = "EventCell" private var events: [MSGraphEvent]? override func viewDidLoad() { super.viewDidLoad() tableView.rowHeight = UITableView.automaticDimension tableView.estimatedRowHeight = 100 } // Number of sections, always 1 override func numberOfSections(in tableView: UITableView) -> Int { return 1 } // Return the number of events in the table override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return events?.count ?? 0 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: tableCellIdentifier, for: indexPath) as! CalendarTableViewCell // Get the event that corresponds to the row let event = events?[indexPath.row] // Configure the cell cell.subject = event?.subject cell.organizer = event?.organizer?.emailAddress?.name // Build a duration string let duration = "\(self.formatGraphDateTime(dateTime: event?.start)) to \(self.formatGraphDateTime(dateTime: event?.end))" cell.duration = duration return cell } private func formatGraphDateTime(dateTime: MSGraphDateTimeTimeZone?) -> String { guard let graphDateTime = dateTime else { return "" } // Create a formatter to parse Graph's date format let isoFormatter = DateFormatter() isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS" let date = isoFormatter.date(from: graphDateTime.dateTime) // Output like 5/5/2019, 2:00 PM let dateFormatter = DateFormatter() dateFormatter.dateStyle = .short dateFormatter.timeStyle = .short return dateFormatter.string(from: date!) } public func setEvents(events: [MSGraphEvent]?) -> Void { self.events = events self.tableView.reloadData() } }
Crie um novo arquivo da Classe Cocoa Touch no projeto GraphTutorial chamado
CalendarTableViewCell.swift
. Escolha UITableViewCell na Subclasse do campo.Abra CalendarTableViewCell.swift e adicione as seguintes propriedades à
CalendarTableViewCell
classe.@IBOutlet var subjectLabel: UILabel! @IBOutlet var organizerLabel: UILabel! @IBOutlet var durationLabel: UILabel! var subject: String? { didSet { subjectLabel.text = subject } } var organizer: String? { didSet { organizerLabel.text = organizer } } var duration: String? { didSet { durationLabel.text = duration } }
Abra Main.storyboard e localize a Cena do Calendário. Exclua o exibição de rolagem do exibição raiz.
Usando a Biblioteca, adicione uma Barra de Navegação à parte superior do modo de exibição.
Clique duas vezes no Título na barra de navegação e atualize-o para
Calendar
.Usando a Biblioteca, adicione um Item de Botão de Barra ao lado direito da barra de navegação.
Selecione o novo botão de barra e selecione o Inspetor de Atributos. Alterar Imagem para mais.
Adicione um Modo de Exibição de Contêiner da Biblioteca ao modo de exibição na barra de navegação. Resize o exibição de contêiner para tirar todo o espaço restante no exibição.
Definir restrições na barra de navegação e no modo de exibição de contêiner da seguinte forma.
- Barra de Navegação
- Adicionar restrição: Altura, valor: 44
- Adicionar restrição: Levando espaço Cofre Área, valor: 0
- Adicionar restrição: espaço à Cofre Área, valor: 0
- Adicionar restrição: Espaço superior Cofre Área, valor: 0
- Exibição de contêiner
- Adicionar restrição: Levando espaço Cofre Área, valor: 0
- Adicionar restrição: espaço à Cofre Área, valor: 0
- Adicionar restrição: Espaço superior à Barra de Navegação Inferior, valor: 0
- Adicionar restrição: Espaço inferior para Cofre Área, valor: 0
- Barra de Navegação
Localize o segundo controlador de exibição adicionado ao storyboard quando você adicionou o exibição de contêiner. Ele é conectado à Cena do Calendário por um segue de incorporar. Selecione este controlador e use o Inspetor de Identidade para alterar Class para CalendarTableViewController.
Exclua o View do Controlador de Exibição de Tabela de Calendário.
Adicione um Exibição de Tabela da Biblioteca ao Controlador de Exibição de Tabela de Calendário.
Selecione o exibição de tabela e selecione o Inspetor de Atributos. Definir células de protótipo como 1.
Arraste a borda inferior da célula protótipo para lhe dar uma área maior para trabalhar.
Use a Biblioteca para adicionar três Rótulos à célula protótipo.
Selecione a célula protótipo e selecione o Inspetor de Identidade. Alterar classe para CalendarTableViewCell.
Selecione o Inspetor de Atributos e de definir Identificador como
EventCell
.Com o EventCell selecionado, selecione o Inspetor de Conexões e conecte - e aos rótulos adicionados à célula
durationLabel
noorganizerLabel
subjectLabel
storyboard.De definir as propriedades e restrições nos três rótulos da seguinte forma.
- Rótulo de assunto
- Adicionar restrição: Espaço à esquerda para a margem de exibição de conteúdo, valor: 0
- Adicionar restrição: espaço à direita à margem de exibição de conteúdo à direita, valor: 0
- Adicionar restrição: Espaço superior à Margem Superior de Exibição de Conteúdo, valor: 0
- Rótulo organizador
- Fonte: Sistema 12.0
- Adicionar restrição: Altura, valor: 15
- Adicionar restrição: Espaço à esquerda para a margem de exibição de conteúdo, valor: 0
- Adicionar restrição: espaço à direita à margem de exibição de conteúdo à direita, valor: 0
- Adicionar restrição: Espaço superior para Subject Label Bottom, valor: Standard
- Rótulo de Duração
- Fonte: Sistema 12.0
- Cor: Cor cinza escuro
- Adicionar restrição: Altura, valor: 15
- Adicionar restrição: Espaço à esquerda para a margem de exibição de conteúdo, valor: 0
- Adicionar restrição: espaço à direita à margem de exibição de conteúdo à direita, valor: 0
- Adicionar restrição: Espaço superior ao Rótulo do Organizador Inferior, valor: Padrão
- Adicionar restrição: Espaço inferior à margem inferior do exibição de conteúdo, valor: 0
- Rótulo de assunto
Selecione EventCell e selecione o Inspetor de Tamanhos. Habilitar Automático para Altura da Linha.
Abra CalendarViewController.swift e substitua seu conteúdo pelo código a seguir.
import UIKit import MSGraphClientModels class CalendarViewController: UIViewController { private let spinner = SpinnerViewController() private var tableViewController: CalendarTableViewController? override func viewDidLoad() { super.viewDidLoad() self.spinner.start(container: self) // Calculate the start and end of the current week let timeZone = GraphToIana.getIanaIdentifier(graphIdentifer: GraphManager.instance.userTimeZone) let now = Date() var calendar = Calendar(identifier: .gregorian) calendar.timeZone = TimeZone(identifier: timeZone)! let startOfWeek = calendar.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: now).date! let endOfWeek = calendar.date(byAdding: .day, value: 7, to: startOfWeek)! // Convert start and end to ISO 8601 strings let isoFormatter = ISO8601DateFormatter() let viewStart = isoFormatter.string(from: startOfWeek) let viewEnd = isoFormatter.string(from: endOfWeek) GraphManager.instance.getCalendarView(viewStart: viewStart, viewEnd: viewEnd) { (eventArray: [MSGraphEvent]?, error: Error?) in DispatchQueue.main.async { self.spinner.stop() guard let events = eventArray, error == nil else { // Show the error let alert = UIAlertController(title: "Error getting events", message: error.debugDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alert, animated: true) return } self.tableViewController?.setEvents(events: events) } } } internal override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // Save reference to the contained table view if segue.destination is CalendarTableViewController { self.tableViewController = segue.destination as? CalendarTableViewController } } @IBAction func showNewEventForm() { self.performSegue(withIdentifier: "showEventForm", sender: self) } }
Execute o aplicativo, entre e toque na guia Calendário. Você deve ver a lista de eventos.
Criar um novo evento
Nesta seção, você adicionará a capacidade de criar eventos no calendário do usuário.
Abra GraphManager.swift e adicione a seguinte função para criar um novo evento no calendário do usuário.
public func createEvent(subject: String, start: Date, end: Date, attendees: [Substring]?, body: String?, completion: @escaping(MSGraphEvent?, Error?) -> Void) { let isoFormatter = DateFormatter() isoFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss" // Create a dictionary to represent the event // Current version of the Graph SDK models don't serialize properly // see https://github.com/microsoftgraph/msgraph-sdk-objc-models/issues/27 var newEventDict: [String: Any] = [ "subject": subject, "start": [ "dateTime": isoFormatter.string(from: start), "timeZone": self.userTimeZone ], "end": [ "dateTime": isoFormatter.string(from: end), "timeZone": self.userTimeZone ] ] if attendees?.count ?? 0 > 0 { var attendeeArray: [Any] = [] for attendee in attendees! { let attendeeDict: [String: Any] = [ "type": "required", "emailAddress": [ "address": String(attendee) ] ] attendeeArray.append(attendeeDict) } newEventDict["attendees"] = attendeeArray } if !(body?.isEmpty ?? false) { newEventDict["body"] = [ "content": body, "contentType": "text" ] } let eventData = try? JSONSerialization.data(withJSONObject: newEventDict) let createEventRequest = NSMutableURLRequest(url: URL(string: "\(MSGraphBaseURL)/me/events")!) createEventRequest.httpMethod = "POST" createEventRequest.httpBody = eventData createEventRequest.addValue("application/json", forHTTPHeaderField: "Content-Type") let createEventTask = MSURLSessionDataTask(request: createEventRequest, client: self.client, completion: { (data: Data?, response: URLResponse?, graphError: Error?) in guard let eventData = data, graphError == nil else { completion(nil, graphError) return } do { // Deserialize response as event let returnedEvent = try MSGraphEvent(data: eventData) // Return the event completion(returnedEvent, nil) } catch { completion(nil, error) } }) // Execute the task createEventTask?.execute() }
Crie um novo arquivo da Classe Cocoa Touch na pasta GraphTutorial chamada
NewEventViewController
. Escolha UIViewController na Subclasse do campo.Abra NewEventViewController.swift e substitua seu conteúdo pelo seguinte.
import UIKit import MSGraphClientModels class NewEventViewController: UIViewController { @IBOutlet var subject: UITextField! @IBOutlet var attendees: UITextField! @IBOutlet var start: UIDatePicker! @IBOutlet var end: UIDatePicker! @IBOutlet var body: UITextView! private let spinner = SpinnerViewController() override func viewDidLoad() { super.viewDidLoad() // Add border around text view let borderColor : UIColor = UIColor(red: 0.85, green: 0.85, blue: 0.85, alpha: 1.0) body.layer.borderWidth = 0.5 body.layer.borderColor = borderColor.cgColor body.layer.cornerRadius = 5.0 // Set start picker to the next closest half-hour let now = Date() let calendar = Calendar.current let components = calendar.dateComponents([.minute], from:now) let offset = 30 - (components.minute! % 30) let start = calendar.date(byAdding: .minute, value: offset, to: now) self.start.date = start! // Set end picker to start + 30 min let end = calendar.date(byAdding: .minute, value: 30, to: start!) self.end.date = end! } @IBAction func createEvent() { self.spinner.start(container: self) // Do create let subject = self.subject.text ?? "" let attendees = self.attendees.text?.split(separator: ";") let start = self.start.date let end = self.end.date let body = self.body.text ?? "" GraphManager.instance.createEvent(subject: subject, start: start, end: end, attendees: attendees, body: body) { (event: MSGraphEvent?, error: Error?) in DispatchQueue.main.async { self.spinner.stop() guard let _ = event, error == nil else { // Show the error let alert = UIAlertController(title: "Error creating event", message: error.debugDescription, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: nil)) self.present(alert, animated: true) return } let alert = UIAlertController(title: "Success", message: "Event created", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { (action: UIAlertAction?) in self.dismiss(animated: true, completion: nil) })) self.present(alert, animated: true) } } } @IBAction func cancel() { self.dismiss(animated: true, completion: nil) } }
Abra Main.storyboard. Use a Biblioteca para arrastar um Controlador de Exibição para o storyboard.
Usando a Biblioteca, adicione uma Barra de Navegação ao controlador de exibição.
Clique duas vezes no Título na barra de navegação e atualize-o para
New Event
.Usando a Biblioteca, adicione um Item de Botão de Barra ao lado esquerdo da barra de navegação.
Selecione o novo botão de barra e selecione o Inspetor de Atributos. Alterar Título para
Cancel
.Usando a Biblioteca, adicione um Item de Botão de Barra ao lado direito da barra de navegação.
Selecione o novo botão de barra e selecione o Inspetor de Atributos. Alterar Título para
Create
.Selecione o controlador de exibição e selecione o Inspetor de Identidade. Alterar classe para NewEventViewController.
Adicione os controles a seguir da Biblioteca à exibição.
- Adicione um Rótulo na barra de navegação. De definir seu texto como
Subject
. - Adicione um Campo de Texto sob o rótulo. Definir seu atributo Placeholder como
Subject
. - Adicione um Rótulo no campo de texto. De definir seu texto como
Attendees
. - Adicione um Campo de Texto sob o rótulo. Definir seu atributo Placeholder como
Separate multiple entries with ;
. - Adicione um Rótulo no campo de texto. De definir seu texto como
Start
. - Adicione um Selador de Data sob o rótulo. Definir seu Estilo Preferencial como Compacto, seu Intervalo como 15 minutos e sua altura como 35.
- Adicione um Rótulo no selador de datas. De definir seu texto como
End
. - Adicione um Selador de Data sob o rótulo. Definir seu Estilo Preferencial como Compacto, seu Intervalo como 15 minutos e sua altura como 35.
- Adicione um Text View no selador de datas.
- Adicione um Rótulo na barra de navegação. De definir seu texto como
Selecione o Novo Controlador de Exibição de Evento e use o Inspetor de Conexão para fazer as seguintes conexões.
- Conexão ação cancelar recebida no botão Cancelar barra.
- Conexão a ação createEvent recebida no botão Criar barra.
- Conexão saída de assunto para o primeiro campo de texto.
- Conexão a saída dos participantes para o segundo campo de texto.
- Conexão saída inicial para o selador de primeira data.
- Conexão saída final para o segundo se picker de data.
- Conexão saída do corpo para o exibição de texto.
Adicione as seguintes restrições.
- Barra de Navegação
- Espaço à Cofre Área, valor: 0
- Espaço à Cofre Área, valor: 0
- Espaço superior para Cofre Área, valor: 0
- Altura, valor: 44
- Rótulo de assunto
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para a Barra de Navegação, valor: 20
- Campo Texto do Assunto
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para Rótulo de Assunto, valor: Standard
- Rótulo de participantes
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para Campo de Texto de Assunto, valor: Standard
- Campo texto dos participantes
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para Rótulo de Participantes, valor: Standard
- Iniciar Rótulo
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para Campo de Texto de Assunto, valor: Standard
- Se picker de data de início
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para Rótulo de Participantes, valor: Standard
- Altura, valor: 35
- Rótulo final
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para o Se picker de data de início, valor: Standard
- Se picker de data de término
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para Rótulo Final, valor: Standard
- Altura: 35
- Body Text View
- Espaço à esquerda para Exibir margem, valor: 0
- Espaço à direita para Exibir margem, valor: 0
- Espaço superior para o Se picker de data de término, valor: Standard
- Espaço inferior para Exibir margem, valor: 0
- Barra de Navegação
Selecione a Cena do Calendário e selecione o Inspetor de Conexões.
Em Segues Disparados, arraste o círculo não preenchido ao lado do manual para o Novo Controlador de Modo de Exibição de Eventos no storyboard. Selecione Apresentar Modally no menu pop-up.
Selecione o segue que você acabou de adicionar e selecione o Inspetor de Atributos. Definir o campo Identificador como
showEventForm
.Conexão a ação showNewEventForm recebida no botão da barra de + navegação.
Salve suas alterações e reinicie o aplicativo. Vá para a página de calendário e toque no + botão. Preencha o formulário e toque em Criar para criar um novo evento.
Parabéns!
Você concluiu o tutorial do microsoft Graph iOS Swift. Agora que você tem um aplicativo de trabalho que chama a Microsoft Graph, você pode experimentar e adicionar novos recursos. Visite a visão geral do microsoft Graph para ver todos os dados que você pode acessar com o Microsoft Graph.
Comentários
Forneça qualquer comentário sobre este tutorial no repositório GitHub .
Tem algum problema com essa seção? Se tiver, envie seus comentários para que possamos melhorar esta seção.