This commit is contained in:
Mykyta Bondarenko 2019-01-29 18:59:03 +02:00 коммит произвёл Craig Dunn
Родитель 088d8df73d
Коммит d88b9fa196
45 изменённых файлов: 2604 добавлений и 0 удалений

23
Contacts/Contacts.sln Normal file
Просмотреть файл

@ -0,0 +1,23 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Contacts", "Contacts\Contacts.csproj", "{08F05190-711C-43BB-B45D-56791A5D935C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|iPhoneSimulator = Debug|iPhoneSimulator
Release|iPhone = Release|iPhone
Release|iPhoneSimulator = Release|iPhoneSimulator
Debug|iPhone = Debug|iPhone
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{08F05190-711C-43BB-B45D-56791A5D935C}.Debug|iPhoneSimulator.ActiveCfg = Debug|iPhoneSimulator
{08F05190-711C-43BB-B45D-56791A5D935C}.Debug|iPhoneSimulator.Build.0 = Debug|iPhoneSimulator
{08F05190-711C-43BB-B45D-56791A5D935C}.Release|iPhone.ActiveCfg = Release|iPhone
{08F05190-711C-43BB-B45D-56791A5D935C}.Release|iPhone.Build.0 = Release|iPhone
{08F05190-711C-43BB-B45D-56791A5D935C}.Release|iPhoneSimulator.ActiveCfg = Release|iPhoneSimulator
{08F05190-711C-43BB-B45D-56791A5D935C}.Release|iPhoneSimulator.Build.0 = Release|iPhoneSimulator
{08F05190-711C-43BB-B45D-56791A5D935C}.Debug|iPhone.ActiveCfg = Debug|iPhone
{08F05190-711C-43BB-B45D-56791A5D935C}.Debug|iPhone.Build.0 = Debug|iPhone
EndGlobalSection
EndGlobal

Просмотреть файл

@ -0,0 +1,21 @@
using Foundation;
using UIKit;
namespace Contacts
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to application events from iOS.
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
public override UIWindow Window { get; set; }
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// Override point for customization after application launch.
// If not required for your application you can safely delete this method
return true;
}
}
}

Просмотреть файл

@ -0,0 +1,244 @@
{
"images": [
{
"size": "20x20",
"scale": "2x",
"idiom": "iphone"
},
{
"size": "20x20",
"scale": "3x",
"idiom": "iphone"
},
{
"filename": "icon-spotlight-29@2x.png",
"size": "29x29",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "icon-spotlight-29@3x.png",
"size": "29x29",
"scale": "3x",
"idiom": "iphone"
},
{
"filename": "icon-spotlight-40@2x.png",
"size": "40x40",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "icon-spotlight-40@3x.png",
"size": "40x40",
"scale": "3x",
"idiom": "iphone"
},
{
"filename": "icon-app-60@2x.png",
"size": "60x60",
"scale": "2x",
"idiom": "iphone"
},
{
"filename": "Icon-app-60@3x.png",
"size": "60x60",
"scale": "3x",
"idiom": "iphone"
},
{
"size": "20x20",
"scale": "1x",
"idiom": "ipad"
},
{
"size": "20x20",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "icon-spotlight-29.png",
"size": "29x29",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "icon-spotlight-29@2x.png",
"size": "29x29",
"scale": "2x",
"idiom": "ipad"
},
{
"size": "40x40",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "icon-spotlight-40@2x.png",
"size": "40x40",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "Icon-app-83.5@2x.png",
"size": "83.5x83.5",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "icon-app-76.png",
"size": "76x76",
"scale": "1x",
"idiom": "ipad"
},
{
"filename": "icon-app-76@2x.png",
"size": "76x76",
"scale": "2x",
"idiom": "ipad"
},
{
"filename": "app-store-logo.png",
"size": "1024x1024",
"scale": "1x",
"idiom": "ios-marketing"
},
{
"size": "60x60",
"scale": "2x",
"idiom": "car"
},
{
"size": "60x60",
"scale": "3x",
"idiom": "car"
},
{
"role": "notificationCenter",
"size": "24x24",
"subtype": "38mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "notificationCenter",
"size": "27.5x27.5",
"subtype": "42mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "companionSettings",
"size": "29x29",
"scale": "2x",
"idiom": "watch"
},
{
"role": "companionSettings",
"size": "29x29",
"scale": "3x",
"idiom": "watch"
},
{
"role": "appLauncher",
"size": "40x40",
"subtype": "38mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "appLauncher",
"size": "44x44",
"subtype": "40mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "appLauncher",
"size": "50x50",
"subtype": "44mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "quickLook",
"size": "86x86",
"subtype": "38mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "quickLook",
"size": "98x98",
"subtype": "42mm",
"scale": "2x",
"idiom": "watch"
},
{
"role": "quickLook",
"size": "108x108",
"subtype": "44mm",
"scale": "2x",
"idiom": "watch"
},
{
"size": "1024x1024",
"scale": "1x",
"idiom": "watch-marketing"
},
{
"size": "16x16",
"scale": "1x",
"idiom": "mac"
},
{
"size": "16x16",
"scale": "2x",
"idiom": "mac"
},
{
"size": "32x32",
"scale": "1x",
"idiom": "mac"
},
{
"size": "32x32",
"scale": "2x",
"idiom": "mac"
},
{
"size": "128x128",
"scale": "1x",
"idiom": "mac"
},
{
"size": "128x128",
"scale": "2x",
"idiom": "mac"
},
{
"size": "256x256",
"scale": "1x",
"idiom": "mac"
},
{
"size": "256x256",
"scale": "2x",
"idiom": "mac"
},
{
"size": "512x512",
"scale": "1x",
"idiom": "mac"
},
{
"size": "512x512",
"scale": "2x",
"idiom": "mac"
}
],
"info": {
"version": 1,
"author": "xcode"
}
}

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 5.0 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 8.6 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 22 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.3 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.0 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 4.3 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 900 B

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 1.8 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.5 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 2.2 KiB

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 3.3 KiB

Просмотреть файл

@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Просмотреть файл

@ -0,0 +1,138 @@
using Contacts.PickerDelegates;
using Contacts.Helpers;
using ContactsUI;
using Foundation;
using System;
using System.Collections.Generic;
using UIKit;
namespace Contacts
{
public partial class ContactPickerController : UIViewController, IUITableViewDelegate, IUITableViewDataSource
{
private readonly List<Section> sections = new List<Section>();
private ICNContactPickerDelegate contactDelegate;
public ContactPickerController(IntPtr handle) : base(handle) { }
public PickerMode Mode { get; set; }
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.tableView.Hidden = true;
this.headerLabel.Hidden = true;
}
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
switch (this.Mode)
{
case PickerMode.SingleContact:
this.headerLabel.Text = "Selected Contact:";
this.descriptionLabel.Text = "This page allows you to select a single contact from the picker. Tap \"Show Picker\" to launch the view controller.";
break;
case PickerMode.MultupleContacts:
this.headerLabel.Text = "Selected Contacts:";
this.descriptionLabel.Text = "This page allows you to select multiple contacts from the picker. Tap \"Show Picker\" to launch the view controller.";
break;
case PickerMode.SingleProperty:
this.headerLabel.Text = "Selected Property:";
this.descriptionLabel.Text = "This page allows you to select a single property from the picker. Tap \"Show Picker\" to launch the view controller.";
break;
case PickerMode.MultipleProperties:
this.headerLabel.Text = "Selected Properties:";
this.descriptionLabel.Text = "This page allows you to select one or more e-mail properties. Tap \"Show Picker\" to launch the view controller.";
break;
}
}
partial void ShowPicker(NSObject sender)
{
this.UpdateInterface(true);
switch (this.Mode)
{
case PickerMode.SingleContact:
this.contactDelegate = new SingleContactPickerDelegate(this.Update);
var picker = new CNContactPickerViewController { Delegate = this.contactDelegate };
base.PresentViewController(picker, true, null);
break;
case PickerMode.MultupleContacts:
this.contactDelegate = new MultipleContactPickerDelegate(this.Update);
var contactsPicker = new CNContactPickerViewController { Delegate = this.contactDelegate };
base.PresentViewController(contactsPicker, true, null);
break;
case PickerMode.SingleProperty:
this.contactDelegate = new SinglePropertyPickerDelegate(this.Update);
var propertyPicker = new CNContactPickerViewController { Delegate = this.contactDelegate };
propertyPicker.DisplayedPropertyKeys = new NSString[] { CNContactKey.GivenName,
CNContactKey.FamilyName,
CNContactKey.EmailAddresses,
CNContactKey.PhoneNumbers,
CNContactKey.PostalAddresses };
base.PresentViewController(propertyPicker, true, null);
break;
case PickerMode.MultipleProperties:
this.contactDelegate = new MultiplePropertyPickerDelegate(this.Update);
var propertiesPicker = new CNContactPickerViewController { Delegate = this.contactDelegate };
propertiesPicker.PredicateForSelectionOfProperty = NSPredicate.FromFormat("key == 'emailAddresses'");
base.PresentViewController(propertiesPicker, true, null);
break;
}
}
private void UpdateInterface(bool hide)
{
this.tableView.Hidden = hide;
this.headerLabel.Hidden = hide;
if (!hide)
{
this.tableView.ReloadData();
}
}
#region IUITableViewDataSource
[Export("numberOfSectionsInTableView:")]
public nint NumberOfSections(UITableView tableView)
{
return this.sections.Count;
}
public nint RowsInSection(UITableView tableView, nint section)
{
return this.sections[(int)section].Items.Count;
}
public UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
var item = this.sections[indexPath.Section].Items[indexPath.Row];
var cell = tableView.DequeueReusableCell("cellID");
cell.TextLabel.Text = item;
return cell;
}
#endregion
private void Update(List<Section> items)
{
this.sections.Clear();
this.sections.AddRange(items);
// Show and update the table view.
this.UpdateInterface(false);
}
}
}

49
Contacts/Contacts/ContactPickerController.designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,49 @@
// WARNING
//
// This file has been generated automatically by Visual Studio from the outlets and
// actions declared in your storyboard file.
// Manual changes to this file will not be maintained.
//
using Foundation;
using System;
using System.CodeDom.Compiler;
namespace Contacts
{
[Register ("ContactPickerController")]
partial class ContactPickerController
{
[Outlet]
UIKit.UILabel descriptionLabel { get; set; }
[Outlet]
UIKit.UILabel headerLabel { get; set; }
[Outlet]
UIKit.UITableView tableView { get; set; }
[Action ("ShowPicker:")]
partial void ShowPicker (Foundation.NSObject sender);
void ReleaseDesignerOutlets ()
{
if (descriptionLabel != null) {
descriptionLabel.Dispose ();
descriptionLabel = null;
}
if (headerLabel != null) {
headerLabel.Dispose ();
headerLabel = null;
}
if (tableView != null) {
tableView.Dispose ();
tableView = null;
}
}
}
}

Просмотреть файл

@ -0,0 +1,145 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">iPhoneSimulator</Platform>
<ProjectGuid>{08F05190-711C-43BB-B45D-56791A5D935C}</ProjectGuid>
<ProjectTypeGuids>{FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Exe</OutputType>
<RootNamespace>Contacts</RootNamespace>
<AssemblyName>Contacts</AssemblyName>
<IPhoneResourcePrefix>Resources</IPhoneResourcePrefix>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhoneSimulator' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhoneSimulator\Debug</OutputPath>
<DefineConstants>DEBUG;ENABLE_TEST_CLOUD;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchDebug>true</MtouchDebug>
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
<MtouchFastDev>true</MtouchFastDev>
<MtouchProfiling>true</MtouchProfiling>
<IOSDebuggerPort>23248</IOSDebuggerPort>
<MtouchLink>None</MtouchLink>
<MtouchArch>x86_64</MtouchArch>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhone' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhone\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchUseLlvm>true</MtouchUseLlvm>
<MtouchFloat32>true</MtouchFloat32>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<MtouchLink>SdkOnly</MtouchLink>
<MtouchArch>ARM64</MtouchArch>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|iPhoneSimulator' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\iPhoneSimulator\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
<MtouchLink>None</MtouchLink>
<MtouchArch>x86_64</MtouchArch>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|iPhone' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\iPhone\Debug</OutputPath>
<DefineConstants>DEBUG;ENABLE_TEST_CLOUD;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodesignKey>iPhone Developer</CodesignKey>
<DeviceSpecificBuild>true</DeviceSpecificBuild>
<MtouchDebug>true</MtouchDebug>
<MtouchNoSymbolStrip>true</MtouchNoSymbolStrip>
<MtouchFastDev>true</MtouchFastDev>
<MtouchProfiling>true</MtouchProfiling>
<MtouchFloat32>true</MtouchFloat32>
<CodesignEntitlements>Entitlements.plist</CodesignEntitlements>
<IOSDebuggerPort>58655</IOSDebuggerPort>
<MtouchLink>SdkOnly</MtouchLink>
<MtouchArch>ARM64</MtouchArch>
<MtouchHttpClientHandler>NSUrlSessionHandler</MtouchHttpClientHandler>
<PlatformTarget>x86</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Xml" />
<Reference Include="System.Core" />
<Reference Include="Xamarin.iOS" />
</ItemGroup>
<ItemGroup>
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Contents.json" />
<ImageAsset Include="Assets.xcassets\Contents.json" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\app-store-logo.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon-app-83.5%402x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-app-76%402x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-app-76.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-spotlight-29.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-spotlight-29%402x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-app-60%402x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\Icon-app-60%403x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-spotlight-29%403x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-spotlight-40%402x.png" />
<ImageAsset Include="Assets.xcassets\AppIcon.appiconset\icon-spotlight-40%403x.png" />
</ItemGroup>
<ItemGroup>
<Folder Include="Helpers\" />
<Folder Include="PickerDelegates\" />
</ItemGroup>
<ItemGroup>
<InterfaceDefinition Include="LaunchScreen.storyboard" />
<InterfaceDefinition Include="Main.storyboard" />
</ItemGroup>
<ItemGroup>
<None Include="Info.plist" />
<None Include="Entitlements.plist" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AppDelegate.cs" />
<Compile Include="RootViewController.cs" />
<Compile Include="RootViewController.designer.cs">
<DependentUpon>RootViewController.cs</DependentUpon>
</Compile>
<Compile Include="Helpers\ContactExtensions.cs" />
<Compile Include="ContactPickerController.cs" />
<Compile Include="ContactPickerController.designer.cs">
<DependentUpon>ContactPickerController.cs</DependentUpon>
</Compile>
<Compile Include="Helpers\Helper.cs" />
<Compile Include="Helpers\PickerMode.cs" />
<Compile Include="Helpers\Section.cs" />
<Compile Include="PickerDelegates\SingleContactPickerDelegate.cs" />
<Compile Include="PickerDelegates\SinglePropertyPickerDelegate.cs" />
<Compile Include="PickerDelegates\MultipleContactPickerDelegate.cs" />
<Compile Include="PickerDelegates\MultiplePropertyPickerDelegate.cs" />
<Compile Include="PredicateContactViewController.cs" />
<Compile Include="PredicateContactViewController.designer.cs">
<DependentUpon>PredicateContactViewController.cs</DependentUpon>
</Compile>
<Compile Include="Helpers\PredicatePickerMode.cs" />
<Compile Include="PredicatePropertiesViewController.cs" />
<Compile Include="PredicatePropertiesViewController.designer.cs">
<DependentUpon>PredicatePropertiesViewController.cs</DependentUpon>
</Compile>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,103 @@
using System;
using System.Linq;
using Foundation;
namespace Contacts.Helpers
{
public static class ContactExtensions
{
/// <summary>
/// The formatted name of a contact if there is one and "No Name", otherwise.
/// </summary>
public static string GetFormattedName(this CNContact contact)
{
var name = contact != null ? CNContactFormatter.GetStringFrom(contact, CNContactFormatterStyle.FullName)?.Trim() : null;
return !string.IsNullOrEmpty(name) ? name : "No Name";
}
}
public static class ContactPropertyExtensions
{
/// <summary>
/// The name matching the key of the property.
/// </summary>
public static string GetNameMatchingKey(this CNContactProperty property)
{
switch (property.Key)
{
case "emailAddresses":
return "Email address";
case "phoneNumbers":
return "Phone numbers";
case "postalAddresses":
return "Postal address";
default:
return null;
}
}
/// <summary>
/// The name matching the value of the property.
/// </summary>
public static string GetNameMatchingValue(this CNContactProperty property)
{
switch (property.Key)
{
case "emailAddresses":
return property.Value as NSString;
case "phoneNumbers":
if (property.Value is CNPhoneNumber phoneNumber)
{
return phoneNumber.StringValue;
}
break;
case "postalAddresses":
if (property.Value is CNPostalAddress address)
{
return address.GetFormattedPostalAddress();
}
break;
}
return null;
}
/// <summary>
/// The name matching the localized label of the property.
/// </summary>
public static string GetNameMatchingLocalizedLabel(this CNContactProperty property)
{
var label = property?.Label;
if (!string.IsNullOrEmpty(label))
{
var nativeLabel = new NSString(label);
switch (property?.Label)
{
case "emailAddresses":
return CNLabeledValue<NSString>.LocalizeLabel(nativeLabel);
case "phoneNumbers":
return CNLabeledValue<CNPhoneNumber>.LocalizeLabel(nativeLabel);
case "postalAddresses":
return CNLabeledValue<CNPostalAddress>.LocalizeLabel(nativeLabel);
}
}
return null;
}
}
public static class PostalAddressExtensions
{
/// <summary>
/// The formatted postal address.
/// </summary>
public static string GetFormattedPostalAddress(this CNPostalAddress postalAddress)
{
string[] address = { postalAddress.Street, postalAddress.City, postalAddress.State, postalAddress.PostalCode, postalAddress.Country };
var filteredArray = address.Where(item => !string.IsNullOrEmpty(item)).ToArray();
return filteredArray.Any() ? string.Join(", ", filteredArray) : null;
}
}
}

Просмотреть файл

@ -0,0 +1,17 @@
using UIKit;
namespace Contacts.Helpers
{
public static class Helper
{
/// <summary>
/// The formatted name of a contact if there is one and "No Name", otherwise.
/// </summary>
public static void ShowAlert(this UIViewController controller, string message)
{
var alert = UIAlertController.Create("Status", message, UIAlertControllerStyle.ActionSheet);
alert.AddAction(UIAlertAction.Create("Ok", UIAlertActionStyle.Default, null));
controller.PresentViewController(alert, true, null);
}
}
}

Просмотреть файл

@ -0,0 +1,12 @@

namespace Contacts.Helpers
{
public enum PickerMode
{
Default = 0,
SingleContact = 1,
SingleProperty = 2,
MultupleContacts = 3,
MultipleProperties = 4
}
}

Просмотреть файл

@ -0,0 +1,10 @@

namespace Contacts.Helpers
{
public enum PredicatePickerMode
{
Default = 0,
EnableContacts = 1,
SelectContacts = 2,
}
}

Просмотреть файл

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace Contacts.Helpers
{
public class Section
{
public List<string> Items { get; set; }
}
}

Просмотреть файл

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleName</key>
<string>Contacts</string>
<key>CFBundleIdentifier</key>
<string>com.xamarin.contacts</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>9.3</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>XSAppIconAssets</key>
<string>Assets.xcassets/AppIcon.appiconset</string>
<key>NSContactsUsageDescription</key>
<string>Search for a contact.</string>
</dict>
</plist>

Просмотреть файл

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Xamarin" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4S0-UL-5TA">
<rect key="frame" x="116.5" y="319.5" width="142" height="48"/>
<fontDescription key="fontDescription" type="system" pointSize="40"/>
<color key="textColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="4S0-UL-5TA" firstAttribute="centerX" secondItem="dMs-2m-b5R" secondAttribute="centerX" id="2cY-pm-Gtv"/>
<constraint firstItem="4S0-UL-5TA" firstAttribute="centerY" secondItem="dMs-2m-b5R" secondAttribute="centerY" id="lZc-Cl-w2r"/>
</constraints>
<viewLayoutGuide key="safeArea" id="dMs-2m-b5R"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

15
Contacts/Contacts/Main.cs Normal file
Просмотреть файл

@ -0,0 +1,15 @@
using UIKit;
namespace Contacts
{
public class Application
{
// This is the main entry point of the application.
static void Main(string[] args)
{
// if you want to use a different Application Delegate class from "AppDelegate"
// you can specify it here.
UIApplication.Main(args, null, "AppDelegate");
}
}
}

Просмотреть файл

@ -0,0 +1,685 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="xmy-Le-PAz">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Contacts-->
<scene sceneID="2CI-jZ-69t">
<objects>
<tableViewController id="3rF-eF-F3j" customClass="RootViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="NT7-Bx-SQN">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection headerTitle="Contacts" id="s4y-Au-pHX">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="8eX-Ne-lOG" detailTextLabel="fVh-0F-Yvj" style="IBUITableViewCellStyleSubtitle" id="eHd-8a-eGf">
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="eHd-8a-eGf" id="iVn-2w-M2t">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Create New Contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8eX-Ne-lOG">
<rect key="frame" x="16" y="5" width="155" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Enter data for a new contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="fVh-0F-Yvj">
<rect key="frame" x="16" y="25.5" width="160.5" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="622-uG-UuG" detailTextLabel="HKH-LO-X2A" style="IBUITableViewCellStyleSubtitle" id="aXN-y3-iMY">
<rect key="frame" x="0.0" y="99.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aXN-y3-iMY" id="wwR-iy-twy">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Create New Contact With Existing Data" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="622-uG-UuG">
<rect key="frame" x="16" y="5" width="299" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Save the new contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HKH-LO-X2A">
<rect key="frame" x="16" y="25.5" width="122" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="2PV-PN-kDq" detailTextLabel="9O6-6f-NTZ" style="IBUITableViewCellStyleSubtitle" id="YDe-5H-kNs">
<rect key="frame" x="0.0" y="143.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="YDe-5H-kNs" id="o2Z-mg-1uB">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Edit Unknown Contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2PV-PN-kDq">
<rect key="frame" x="16" y="-3" width="171" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Add data to an existing contact or use them to create a new contact" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9O6-6f-NTZ">
<rect key="frame" x="16" y="17.5" width="314.5" height="29"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="iFT-qx-KmL" detailTextLabel="tI1-se-mBj" style="IBUITableViewCellStyleSubtitle" id="wEe-0T-HD1">
<rect key="frame" x="0.0" y="187.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="wEe-0T-HD1" id="I8r-3p-OaG">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Display and Edit Contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iFT-qx-KmL">
<rect key="frame" x="16" y="5" width="188" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Show and edit a contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tI1-se-mBj">
<rect key="frame" x="16" y="25.5" width="137" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Picker" id="Hy4-GH-Z8v">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="yVH-Tk-vhp" style="IBUITableViewCellStyleDefault" id="dL4-pV-Rkf">
<rect key="frame" x="0.0" y="287.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="dL4-pV-Rkf" id="Zx4-iD-FDa">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Single Contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="yVH-Tk-vhp">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="XNl-NY-aga" style="IBUITableViewCellStyleDefault" id="lRs-0K-wym">
<rect key="frame" x="0.0" y="331.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="lRs-0K-wym" id="aic-af-ctN">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Single Property" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="XNl-NY-aga">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="iEA-O4-2Ky" style="IBUITableViewCellStyleDefault" id="wbx-m7-Y64">
<rect key="frame" x="0.0" y="375.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="wbx-m7-Y64" id="Mzi-SB-aNl">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Multiple Contacts" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="iEA-O4-2Ky">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="VMx-do-lbr" style="IBUITableViewCellStyleDefault" id="x7p-vN-nC0">
<rect key="frame" x="0.0" y="419.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="x7p-vN-nC0" id="swq-ch-bQf">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Multiple Properties" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VMx-do-lbr">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection headerTitle="Predicates" id="lSo-qj-Qm8">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="8Dx-f5-QdN" style="IBUITableViewCellStyleDefault" id="ASy-S9-pbN">
<rect key="frame" x="0.0" y="519.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="ASy-S9-pbN" id="glR-Vv-zzo">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Prdicate for Enabling Contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8Dx-f5-QdN">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="hpd-Zn-ehA" style="IBUITableViewCellStyleDefault" id="bmB-G5-HCx">
<rect key="frame" x="0.0" y="563.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="bmB-G5-HCx" id="vr9-xQ-0sD">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Predicate for Selection of Contact" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="hpd-Zn-ehA">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" textLabel="OjX-h6-rME" style="IBUITableViewCellStyleDefault" id="JYF-Y4-aRN">
<rect key="frame" x="0.0" y="607.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="JYF-Y4-aRN" id="Kp1-90-sZL">
<rect key="frame" x="0.0" y="0.0" width="341" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Predicate for Selection of Property" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="OjX-h6-rME">
<rect key="frame" x="16" y="0.0" width="324" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="3qi-sb-9tA" kind="show" id="zpF-Hb-I2D"/>
</connections>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="3rF-eF-F3j" id="2Xr-8r-AFd"/>
<outlet property="delegate" destination="3rF-eF-F3j" id="aOE-dE-18t"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Contacts" id="5z5-1F-WkF"/>
<connections>
<outlet property="createNewContactCell" destination="eHd-8a-eGf" id="ye5-us-U8A"/>
<outlet property="createNewContactExistingData" destination="aXN-y3-iMY" id="Y6n-K3-C2Z"/>
<outlet property="displayEditCell" destination="wEe-0T-HD1" id="tdW-xx-tMW"/>
<outlet property="editContactCell" destination="YDe-5H-kNs" id="c99-2E-JHX"/>
<outlet property="enableContactsPredicateCell" destination="ASy-S9-pbN" id="G2O-we-7vU"/>
<outlet property="pickMultipleContactsCell" destination="wbx-m7-Y64" id="H3k-MP-5Yd"/>
<outlet property="pickMultiplePropertiesCell" destination="x7p-vN-nC0" id="ndh-rW-Erk"/>
<outlet property="pickSingleContactCell" destination="dL4-pV-Rkf" id="0y0-e7-mmq"/>
<outlet property="pickSinglePropertyCell" destination="lRs-0K-wym" id="1As-2R-cDz"/>
<outlet property="selectContactsPredicateCell" destination="bmB-G5-HCx" id="mBY-gT-175"/>
<segue destination="tgi-bi-xDk" kind="show" identifier="PickerSegue" id="T57-bS-Ayv"/>
<segue destination="Fgo-VJ-WUM" kind="show" identifier="PredicatePickerSegue" id="cwV-WH-0E2"/>
</connections>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="89J-7f-3X1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="625" y="193"/>
</scene>
<!--Contact Picker Controller-->
<scene sceneID="xeC-LW-tBn">
<objects>
<viewController id="tgi-bi-xDk" customClass="ContactPickerController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="pII-hd-CvH">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This page allows you to select a single contact from the picker. Tap &quot;Show Picker&quot; to launch the view controller." textAlignment="justified" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="MpU-1M-ojX">
<rect key="frame" x="16" y="80" width="343" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Jab-dz-mr8">
<rect key="frame" x="145.5" y="205" width="84" height="30"/>
<state key="normal" title="Show Picker"/>
<connections>
<action selector="ShowPicker:" destination="tgi-bi-xDk" eventType="touchUpInside" id="veH-8q-QkO"/>
</connections>
</button>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" translatesAutoresizingMaskIntoConstraints="NO" id="Q7F-fw-EFJ">
<rect key="frame" x="0.0" y="395" width="375" height="272"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<constraints>
<constraint firstAttribute="height" constant="272" id="A7s-l4-bSZ"/>
</constraints>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="cellID" textLabel="CJ4-iC-GGM" style="IBUITableViewCellStyleDefault" id="d1c-Ce-6Ls">
<rect key="frame" x="0.0" y="55.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="d1c-Ce-6Ls" id="NqF-Va-vd5">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="CJ4-iC-GGM">
<rect key="frame" x="15" y="0.0" width="345" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<color key="textColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="tgi-bi-xDk" id="tVx-w4-Af0"/>
<outlet property="delegate" destination="tgi-bi-xDk" id="ZNr-uH-TE3"/>
</connections>
</tableView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Contact Selected:" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tvg-Iv-roU">
<rect key="frame" x="20" y="366" width="335" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="Q7F-fw-EFJ" secondAttribute="trailing" id="0az-4Y-Rqs"/>
<constraint firstItem="MpU-1M-ojX" firstAttribute="leading" secondItem="3uv-qv-gMC" secondAttribute="leading" constant="16" id="B9z-OA-VDF"/>
<constraint firstItem="3uv-qv-gMC" firstAttribute="trailing" secondItem="MpU-1M-ojX" secondAttribute="trailing" constant="16" id="BDW-ay-2OQ"/>
<constraint firstItem="Q7F-fw-EFJ" firstAttribute="top" secondItem="tvg-Iv-roU" secondAttribute="bottom" constant="8" symbolic="YES" id="HBe-5p-w8n"/>
<constraint firstAttribute="bottom" secondItem="Q7F-fw-EFJ" secondAttribute="bottom" id="LRc-i9-KiE"/>
<constraint firstItem="Jab-dz-mr8" firstAttribute="top" secondItem="MpU-1M-ojX" secondAttribute="bottom" constant="64" id="PFL-BI-j9p"/>
<constraint firstItem="MpU-1M-ojX" firstAttribute="top" secondItem="3uv-qv-gMC" secondAttribute="top" constant="16" id="QdC-vL-1fY"/>
<constraint firstItem="Jab-dz-mr8" firstAttribute="centerX" secondItem="3uv-qv-gMC" secondAttribute="centerX" id="ZZU-da-Hyz"/>
<constraint firstItem="Q7F-fw-EFJ" firstAttribute="leading" secondItem="pII-hd-CvH" secondAttribute="leading" id="g15-3v-eqG"/>
<constraint firstItem="3uv-qv-gMC" firstAttribute="trailing" secondItem="tvg-Iv-roU" secondAttribute="trailing" constant="20" id="ssz-6m-HFy"/>
<constraint firstItem="tvg-Iv-roU" firstAttribute="leading" secondItem="3uv-qv-gMC" secondAttribute="leading" constant="20" id="vMg-fw-aCZ"/>
</constraints>
<viewLayoutGuide key="safeArea" id="3uv-qv-gMC"/>
</view>
<connections>
<outlet property="descriptionLabel" destination="MpU-1M-ojX" id="SKy-A8-cSy"/>
<outlet property="headerLabel" destination="tvg-Iv-roU" id="n2b-We-taH"/>
<outlet property="tableView" destination="Q7F-fw-EFJ" id="0Fp-eM-f24"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Bhw-st-tcJ" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1368.8" y="192.95352323838082"/>
</scene>
<!--Navigation Controller-->
<scene sceneID="YlM-pa-ZTx">
<objects>
<navigationController id="xmy-Le-PAz" sceneMemberID="viewController">
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="n5j-uE-ruW">
<rect key="frame" x="0.0" y="20" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<connections>
<segue destination="3rF-eF-F3j" kind="relationship" relationship="rootViewController" id="8gJ-rv-ZBJ"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="vFP-ud-CoI" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-122" y="193"/>
</scene>
<!--Predicate Contact View Controller-->
<scene sceneID="Nki-GU-CHR">
<objects>
<tableViewController id="Fgo-VJ-WUM" customClass="PredicateContactViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="cTo-ee-ZCc">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection id="6vQ-03-oTO">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="u70-yG-f5Q" detailTextLabel="GZ3-hE-sfm" style="IBUITableViewCellStyleSubtitle" id="lpP-S7-82i">
<rect key="frame" x="0.0" y="35" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="lpP-S7-82i" id="zMe-nb-ovQ">
<rect key="frame" x="0.0" y="0.0" width="335" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="All Contacts" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="u70-yG-f5Q">
<rect key="frame" x="16" y="5" width="92.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="All contacts are enabled." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="GZ3-hE-sfm">
<rect key="frame" x="16" y="25.5" width="140" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="VyS-Qm-xJc" detailTextLabel="3Ru-fE-dq2" style="IBUITableViewCellStyleSubtitle" id="CJh-mT-n8c">
<rect key="frame" x="0.0" y="79" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="CJh-mT-n8c" id="dil-BV-vIQ">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Email Addresses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="VyS-Qm-xJc">
<rect key="frame" x="16" y="-3" width="236" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with an email address are enabled. All others are disabled." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="3Ru-fE-dq2">
<rect key="frame" x="16" y="17.5" width="311" height="29"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Fos-bK-lbu" detailTextLabel="9Kq-mw-ZcW" style="IBUITableViewCellStyleSubtitle" id="0vy-pd-KQD">
<rect key="frame" x="0.0" y="123" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0vy-pd-KQD" id="zF8-59-cmp">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Postal Addresses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Fos-bK-lbu">
<rect key="frame" x="16" y="-3" width="242" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with a postal address are enabled. All others are disabled." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9Kq-mw-ZcW">
<rect key="frame" x="16" y="17.5" width="308.5" height="29"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="5zV-aT-rBc" detailTextLabel="ija-e1-RXE" style="IBUITableViewCellStyleSubtitle" id="9Zl-SK-7BP">
<rect key="frame" x="0.0" y="167" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="9Zl-SK-7BP" id="7mk-Lr-0hQ">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Two or More Phone Numbers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="5zV-aT-rBc">
<rect key="frame" x="16" y="-3" width="333" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with 2 or more phone numbers are enabled. All others are disabled." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ija-e1-RXE">
<rect key="frame" x="16" y="17.5" width="322" height="29"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="B7e-ex-oKi" detailTextLabel="95w-EO-Upf" style="IBUITableViewCellStyleSubtitle" id="5g9-wc-Rwh">
<rect key="frame" x="0.0" y="211" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="5g9-wc-Rwh" id="7cj-en-GUx">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Profile Picture" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="B7e-ex-oKi">
<rect key="frame" x="16" y="-3" width="217.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with a profile picture are enabled. All others are disabled." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="95w-EO-Upf">
<rect key="frame" x="16" y="17.5" width="304.5" height="29"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection id="4JF-4I-l99">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="diR-2N-kst" style="IBUITableViewCellStyleDefault" id="U4Y-rs-sAf">
<rect key="frame" x="0.0" y="291" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="U4Y-rs-sAf" id="Lk8-fX-caQ">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Show Picker" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="diR-2N-kst">
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="Fgo-VJ-WUM" id="dV4-Vj-oCm"/>
<outlet property="delegate" destination="Fgo-VJ-WUM" id="Rte-ZD-co3"/>
</connections>
</tableView>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="0hh-Cj-4DO" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-122" y="963"/>
</scene>
<!--Predicate Properties View Controller-->
<scene sceneID="ToU-m9-xl6">
<objects>
<tableViewController id="3qi-sb-9tA" customClass="PredicatePropertiesViewController" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="grouped" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="r5o-HM-0nw">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<sections>
<tableViewSection id="ekw-hl-a30">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" accessoryType="checkmark" indentationWidth="10" textLabel="im7-tP-1m6" detailTextLabel="egV-wA-AKz" style="IBUITableViewCellStyleSubtitle" id="jKc-ev-bE7">
<rect key="frame" x="0.0" y="35" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="jKc-ev-bE7" id="raP-jb-w5T">
<rect key="frame" x="0.0" y="0.0" width="335" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="All Contacts" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="im7-tP-1m6">
<rect key="frame" x="16" y="5" width="92.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Select any contact's property to return it." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="egV-wA-AKz">
<rect key="frame" x="16" y="25.5" width="233.5" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="lsf-wD-wOl" detailTextLabel="EEc-Td-hhd" style="IBUITableViewCellStyleSubtitle" id="gez-sH-FRX">
<rect key="frame" x="0.0" y="79" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="gez-sH-FRX" id="enx-q2-ghu">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Email Addresses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lsf-wD-wOl">
<rect key="frame" x="16" y="5" width="236" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Select a contact's email address to return it." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="EEc-Td-hhd">
<rect key="frame" x="16" y="25.5" width="250" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="89c-N2-jvm" detailTextLabel="QcW-cw-Ibz" style="IBUITableViewCellStyleSubtitle" id="pHO-tC-cFe">
<rect key="frame" x="0.0" y="123" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="pHO-tC-cFe" id="AmP-i2-cTr">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Postal Addresses" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="89c-N2-jvm">
<rect key="frame" x="16" y="5" width="242" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Select a contact's postal address to return it." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="QcW-cw-Ibz">
<rect key="frame" x="16" y="25.5" width="254.5" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="esU-2f-R0E" detailTextLabel="BTi-G3-Uvj" style="IBUITableViewCellStyleSubtitle" id="VxB-tx-KGs">
<rect key="frame" x="0.0" y="167" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="VxB-tx-KGs" id="fcl-CT-HSM">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Contacts with Phone Numbers" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="esU-2f-R0E">
<rect key="frame" x="16" y="5" width="233.5" height="20.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Select a contact's phone number to return it." textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="BTi-G3-Uvj">
<rect key="frame" x="16" y="25.5" width="253.5" height="14.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
<tableViewSection id="Vg6-48-3rs">
<cells>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="ycB-tf-ctF" style="IBUITableViewCellStyleDefault" id="Bo9-eT-wDG">
<rect key="frame" x="0.0" y="247" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Bo9-eT-wDG" id="WUc-2s-wQc">
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Show Picker" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="ycB-tf-ctF">
<rect key="frame" x="16" y="0.0" width="343" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
</cells>
</tableViewSection>
</sections>
<connections>
<outlet property="dataSource" destination="3qi-sb-9tA" id="cNf-Lu-hHR"/>
<outlet property="delegate" destination="3qi-sb-9tA" id="UEW-mp-Yef"/>
</connections>
</tableView>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="1sV-2M-nAL" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="625" y="963"/>
</scene>
</scenes>
</document>

Просмотреть файл

@ -0,0 +1,32 @@
using Contacts.Helpers;
using ContactsUI;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Contacts.PickerDelegates
{
public class MultipleContactPickerDelegate : CNContactPickerDelegate
{
private readonly Action<List<Section>> callback;
public MultipleContactPickerDelegate(Action<List<Section>> callback)
{
this.callback = callback;
}
public override void DidSelectContacts(CNContactPickerViewController picker, CNContact[] contacts)
{
if(contacts != null && contacts.Any())
{
var section = new Section { Items = new List<string>() };
foreach (var contact in contacts)
{
section.Items.Add(contact.GetFormattedName());
}
this.callback(new List<Section> { section });
}
}
}
}

Просмотреть файл

@ -0,0 +1,55 @@
using Contacts.Helpers;
using ContactsUI;
using System;
using System.Collections.Generic;
using System.Linq;
namespace Contacts.PickerDelegates
{
public class MultiplePropertyPickerDelegate : CNContactPickerDelegate
{
private readonly Action<List<Section>> callback;
public MultiplePropertyPickerDelegate(Action<List<Section>> callback)
{
this.callback = callback;
}
public override void DidSelectContactProperties(CNContactPickerViewController picker, CNContactProperty[] contactProperties)
{
if (contactProperties != null && contactProperties.Any())
{
var sections = new List<Section>();
foreach (var contactProperty in contactProperties)
{
var section = new Section { Items = new List<string>() };
var nameKey = contactProperty.GetNameMatchingKey();
if (!string.IsNullOrEmpty(nameKey))
{
section.Items.Add($"Contact: {contactProperty.Contact.GetFormattedName()}");
section.Items.Add($"Key: {nameKey}");
}
// Attempt to fetch the localized label of the property.
var localizedLabel = contactProperty.GetNameMatchingLocalizedLabel();
if (!string.IsNullOrEmpty(localizedLabel))
{
section.Items.Add($"Label : {localizedLabel}");
}
// Attempt to fetch the value of the property.
var value = contactProperty.GetNameMatchingValue();
if (!string.IsNullOrEmpty(value))
{
section.Items.Add($"Value: {value}");
}
sections.Add(section);
}
this.callback(sections);
}
}
}
}

Просмотреть файл

@ -0,0 +1,30 @@
using Contacts.Helpers;
using ContactsUI;
using System;
using System.Collections.Generic;
namespace Contacts.PickerDelegates
{
public class SingleContactPickerDelegate : CNContactPickerDelegate
{
private readonly Action<List<Section>> callback;
public SingleContactPickerDelegate(Action<List<Section>> callback)
{
this.callback = callback;
}
public override void DidSelectContact(CNContactPickerViewController picker, CNContact contact)
{
if (contact != null)
{
var sections = new List<Section>
{
new Section { Items = new List<string> { contact.GetFormattedName() } }
};
this.callback(sections);
}
}
}
}

Просмотреть файл

@ -0,0 +1,50 @@
using Contacts.Helpers;
using ContactsUI;
using System;
using System.Collections.Generic;
namespace Contacts.PickerDelegates
{
public class SinglePropertyPickerDelegate : CNContactPickerDelegate
{
private readonly Action<List<Section>> callback;
public SinglePropertyPickerDelegate(Action<List<Section>> callback)
{
this.callback = callback;
}
public override void DidSelectContactProperty(CNContactPickerViewController picker, CNContactProperty contactProperty)
{
if (contactProperty != null)
{
var sections = new List<Section>();
var section = new Section { Items = new List<string>() };
var nameKey = contactProperty.GetNameMatchingKey();
if (!string.IsNullOrEmpty(nameKey))
{
section.Items.Add($"Contact: {contactProperty.Contact.GetFormattedName()}");
section.Items.Add($"Key: {nameKey}");
}
// Attempt to fetch the localized label of the property.
var localizedLabel = contactProperty.GetNameMatchingLocalizedLabel();
if (!string.IsNullOrEmpty(localizedLabel))
{
section.Items.Add($"Label : {localizedLabel}");
}
// Attempt to fetch the value of the property.
var value = contactProperty.GetNameMatchingValue();
if (!string.IsNullOrEmpty(value))
{
section.Items.Add($"Value: {value}");
}
sections.Add(section);
this.callback(sections);
}
}
}
}

Просмотреть файл

@ -0,0 +1,170 @@
using Contacts.Helpers;
using ContactsUI;
using Foundation;
using System;
using UIKit;
namespace Contacts
{
public partial class PredicateContactViewController : UITableViewController, ICNContactPickerDelegate
{
private UITableViewCell previousSelectedCell;
private string message;
public PredicatePickerMode Mode { get; internal set; }
public PredicateContactViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
var index = NSIndexPath.FromRowSection(0, 0);
base.TableView.SelectRow(index, false, UITableViewScrollPosition.Top);
this.previousSelectedCell = base.TableView.CellAt(index);
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (!string.IsNullOrEmpty(this.message))
{
base.NavigationController.ShowAlert(this.message);
this.message = null;
}
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Section == 0)
{
var selectedCell = tableView.CellAt(indexPath);
if (selectedCell != this.previousSelectedCell)
{
selectedCell.Accessory = UITableViewCellAccessory.Checkmark;
if (this.previousSelectedCell != null)
{
this.previousSelectedCell.Accessory = UITableViewCellAccessory.None;
}
this.previousSelectedCell = selectedCell;
}
}
else
{
// show picker
this.ShowPicker();
}
tableView.DeselectRow(indexPath, true);
}
private void ShowPicker()
{
var index = base.TableView.IndexPathForCell(this.previousSelectedCell);
switch (index.Row)
{
case 0:
// Enable all contacts in the contacts picker view.
this.HandleAllContacts();
break;
case 1:
// Only enable contacts with email addresses in the contacts picker view.
this.HandleContactsWithEmailAddresses();
break;
case 2:
// Only enable contacts with postal addresses in the contacts picker view.
this.HandleContactsWithPostalAddresses();
break;
case 3:
// Only enable contacts with 2 or more phone numbers in the contacts picker view.
this.HandleContactsWithPhoneNumbers();
break;
case 4:
// Only enable contacts with a profile picture in the contacts picker view.
this.HandleContactsWithProfilePicture();
break;
}
}
private void HandleContactsWithProfilePicture()
{
var picker = this.CreatePicker();
// Only show contacts with email addresses.
picker.PredicateForEnablingContact = NSPredicate.FromFormat("imageDataAvailable == true");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleContactsWithPhoneNumbers()
{
var picker = this.CreatePicker();
// Only show contacts with email addresses.
picker.PredicateForEnablingContact = NSPredicate.FromFormat("phoneNumbers.@count > 1");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleContactsWithPostalAddresses()
{
var picker = this.CreatePicker();
// Only show contacts with email addresses.
picker.PredicateForEnablingContact = NSPredicate.FromFormat("postalAddresses.@count > 0");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleContactsWithEmailAddresses()
{
var picker = this.CreatePicker();
// Only show contacts with email addresses.
picker.PredicateForEnablingContact = NSPredicate.FromFormat("emailAddresses.@count > 0");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleAllContacts()
{
var picker = this.CreatePicker();
base.NavigationController.PresentViewController(picker, true, null);
}
private CNContactPickerViewController CreatePicker()
{
var controller = new CNContactPickerViewController();
if (this.Mode == PredicatePickerMode.SelectContacts)
{
controller.Delegate = this;
}
return controller;
}
#region ICNContactPickerDelegate
[Export("contactPicker:didSelectContact:")]
public void DidSelectContact(CNContactPickerViewController picker, CNContact contact)
{
var name = contact?.GetFormattedName();
if (!string.IsNullOrEmpty(name))
{
this.message = $"{name} was selected.";
}
}
#endregion
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (this.previousSelectedCell != null)
{
this.previousSelectedCell.Dispose();
this.previousSelectedCell = null;
}
}
}
}

20
Contacts/Contacts/PredicateContactViewController.designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,20 @@
// WARNING
//
// This file has been generated automatically by Visual Studio to store outlets and
// actions made in the UI designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using Foundation;
using System.CodeDom.Compiler;
namespace Contacts
{
[Register ("PredicateContactViewController")]
partial class PredicateContactViewController
{
void ReleaseDesignerOutlets ()
{
}
}
}

Просмотреть файл

@ -0,0 +1,163 @@
using Contacts.Helpers;
using ContactsUI;
using Foundation;
using System;
using UIKit;
namespace Contacts
{
public partial class PredicatePropertiesViewController : UITableViewController, ICNContactPickerDelegate
{
private UITableViewCell previousSelectedCell;
private string message;
public PredicatePropertiesViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
var index = NSIndexPath.FromRowSection(0, 0);
base.TableView.SelectRow(index, false, UITableViewScrollPosition.Top);
this.previousSelectedCell = base.TableView.CellAt(index);
}
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (!string.IsNullOrEmpty(this.message))
{
base.NavigationController.ShowAlert(this.message);
this.message = null;
}
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
if (indexPath.Section == 0)
{
var selectedCell = tableView.CellAt(indexPath);
if (selectedCell != this.previousSelectedCell)
{
selectedCell.Accessory = UITableViewCellAccessory.Checkmark;
if (this.previousSelectedCell != null)
{
this.previousSelectedCell.Accessory = UITableViewCellAccessory.None;
}
this.previousSelectedCell = selectedCell;
}
}
else
{
// show picker
this.ShowPicker();
}
tableView.DeselectRow(indexPath, true);
}
private void ShowPicker()
{
var index = base.TableView.IndexPathForCell(this.previousSelectedCell);
switch (index.Row)
{
case 0:
// Only show the given and family names, email addresses, phone numbers, and postal addresses of a contact.
this.HandleAllContacts();
break;
case 1:
// When users select a contact's email address, it dismisses the view controller and returns the email address using
// CNContactPickerDelegate's contactPicker(_:didSelect:). When users select other properties, it implements their default action.
this.HandleContactsWithEmailAddresses();
break;
case 2:
// When users select a contact's postal address, it dismisses the view controller and returns the birthday using
// CNContactPickerDelegate's contactPicker(_:didSelect:). When users select other properties, it implements their default action.
this.HandleContactsWithPostalAddresses();
break;
case 3:
// When users select a contact's phone number, it dismisses the view controller and returns the phone number using
// CNContactPickerDelegate's contactPicker(_:didSelect:). When users select other properties, it implements their default action.
this.HandleContactsWithPhoneNumbers();
break;
}
}
private void HandleContactsWithPhoneNumbers()
{
var picker = new CNContactPickerViewController { Delegate = this };
// Only show contacts with email addresses.
picker.PredicateForSelectionOfProperty = NSPredicate.FromFormat("key == 'phoneNumbers'");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleContactsWithPostalAddresses()
{
var picker = new CNContactPickerViewController { Delegate = this };
// Only show contacts with email addresses.
picker.PredicateForSelectionOfProperty = NSPredicate.FromFormat("key == 'postalAddresses'");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleContactsWithEmailAddresses()
{
var picker = new CNContactPickerViewController { Delegate = this };
// Only show contacts with email addresses.
picker.PredicateForSelectionOfProperty = NSPredicate.FromFormat("(key == 'emailAddresses')");
base.NavigationController.PresentViewController(picker, true, null);
}
private void HandleAllContacts()
{
var picker = new CNContactPickerViewController { Delegate = this };
/*
Only show the given and family names, email addresses, phone numbers,
and postal addresses of a contact.
*/
picker.DisplayedPropertyKeys = new NSString[]
{
CNContactKey.GivenName,
CNContactKey.FamilyName,
CNContactKey.EmailAddresses,
CNContactKey.PhoneNumbers,
CNContactKey.PostalAddresses
};
base.NavigationController.PresentViewController(picker, true, null);
}
#region ICNContactPickerDelegate
[Export("contactPicker:didSelectContactProperty:")]
public void DidSelectContactProperty(CNContactPickerViewController picker, CNContactProperty contactProperty)
{
if (contactProperty != null)
{
var value = contactProperty.GetNameMatchingValue();
var key = contactProperty.GetNameMatchingKey();
if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(key))
{
this.message = $"{contactProperty.Contact.GetFormattedName()}'s {key} ({value}) was selected.";
}
}
}
#endregion
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (this.previousSelectedCell != null)
{
this.previousSelectedCell.Dispose();
this.previousSelectedCell = null;
}
}
}
}

20
Contacts/Contacts/PredicatePropertiesViewController.designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,20 @@
// WARNING
//
// This file has been generated automatically by Visual Studio to store outlets and
// actions made in the UI designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using Foundation;
using System.CodeDom.Compiler;
namespace Contacts
{
[Register ("PredicatePropertiesViewController")]
partial class PredicatePropertiesViewController
{
void ReleaseDesignerOutlets ()
{
}
}
}

Просмотреть файл

@ -0,0 +1,322 @@
using Contacts.Helpers;
using ContactsUI;
using CoreFoundation;
using Foundation;
using System;
using System.Linq;
using UIKit;
namespace Contacts
{
public partial class RootViewController : UITableViewController, ICNContactViewControllerDelegate
{
private readonly CNContactStore store = new CNContactStore();
public RootViewController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
this.CheckContactsAccess();
}
private void CheckContactsAccess()
{
var status = CNContactStore.GetAuthorizationStatus(CNEntityType.Contacts);
switch (status)
{
// Access was granted. Update the UI with the default navigation menu.
case CNAuthorizationStatus.Authorized:
Console.WriteLine("App is authorized");
break;
case CNAuthorizationStatus.NotDetermined:
this.store.RequestAccess(CNEntityType.Contacts, (granted, _) =>
{
if (granted)
{
Console.WriteLine("App is authorized");
}
});
break;
// Access was denied or restricted.
case CNAuthorizationStatus.Restricted:
case CNAuthorizationStatus.Denied:
Console.WriteLine("Access denied or restricted.");
break;
}
}
public override void PrepareForSegue(UIStoryboardSegue segue, NSObject sender)
{
if (segue.Identifier == "PickerSegue")
{
if (segue.DestinationViewController is ContactPickerController contactPickerController)
{
contactPickerController.Mode = (PickerMode)(sender as NSNumber).Int32Value;
}
}
else if (segue.Identifier == "PredicatePickerSegue")
{
if (segue.DestinationViewController is PredicateContactViewController predicateContactViewController)
{
predicateContactViewController.Mode = (PredicatePickerMode)(sender as NSNumber).Int32Value;
}
}
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
var selectedCell = tableView.CellAt(indexPath);
// regular contacts logic
if (indexPath.Section == 0)
{
this.PerformContactAction(selectedCell);
}
// picker logic
else if (indexPath.Section == 1)
{
this.PerformContactPickerAction(selectedCell);
}
// predicate picker logic
else if (indexPath.Section == 2)
{
this.PerformContactPredicatePickerAction(selectedCell);
}
tableView.DeselectRow(indexPath, false);
}
#region Contact predicate picker logic (3d section)
private void PerformContactPredicatePickerAction(UITableViewCell selectedCell)
{
if (selectedCell == this.enableContactsPredicateCell)
{
base.PerformSegue("PredicatePickerSegue", new NSNumber((int)PredicatePickerMode.EnableContacts));
}
else if (selectedCell == this.selectContactsPredicateCell)
{
base.PerformSegue("PredicatePickerSegue", new NSNumber((int)PredicatePickerMode.SelectContacts));
}
}
#endregion
#region Contact picker logic (2st section)
private void PerformContactPickerAction(UITableViewCell selectedCell)
{
var mode = default(PickerMode);
if (selectedCell == this.pickSingleContactCell)
{
mode = PickerMode.SingleContact;
}
else if (selectedCell == this.pickSinglePropertyCell)
{
mode = PickerMode.SingleProperty;
}
else if (selectedCell == this.pickMultipleContactsCell)
{
mode = PickerMode.MultupleContacts;
}
else if (selectedCell == this.pickMultiplePropertiesCell)
{
mode = PickerMode.MultipleProperties;
}
base.PerformSegue("PickerSegue", new NSNumber((int)mode));
}
#endregion
#region Regular contact logic (1st section)
private void PerformContactAction(UITableViewCell selectedCell)
{
if (selectedCell == this.createNewContactCell)
{
// Create an empty contact view controller.
var contactViewController = CNContactViewController.FromNewContact(null);
// Set its delegate.
contactViewController.Delegate = this;
// Push it using the navigation controller.
base.NavigationController.PushViewController(contactViewController, true);
}
// Called when users tap "Create New Contact With Existing Data" in the UI.
// Create and launch a contacts view controller with pre - filled fields.
else if (selectedCell == this.createNewContactExistingData)
{
var contact = new CNMutableContact
{
// Given and family names.
FamilyName = Name.Family,
GivenName = Name.Given,
};
// Phone numbers.
contact.PhoneNumbers = new CNLabeledValue<CNPhoneNumber>[]
{
new CNLabeledValue<CNPhoneNumber>(PhoneNumber.IPhone,
new CNPhoneNumber(PhoneNumber.IPhone)),
new CNLabeledValue<CNPhoneNumber>(PhoneNumber.Mobile,
new CNPhoneNumber(PhoneNumber.Mobile))
};
// Postal address.
var homeAddress = new CNMutablePostalAddress
{
Street = Address.Street,
City = Address.City,
State = Address.State,
PostalCode = Address.PostalCode,
};
contact.PostalAddresses = new CNLabeledValue<CNPostalAddress>[] { new CNLabeledValue<CNPostalAddress>(CNLabelKey.Home, homeAddress) };
// Create a contact view controller with the above contact.
var contactViewController = CNContactViewController.FromNewContact(contact);
// Set its delegate.
contactViewController.Delegate = this;
// Push it using the navigation controller.
base.NavigationController.PushViewController(contactViewController, true);
}
// Called when users tap "Edit Unknown Contact" in the UI.
// The view controller displays some contact information that you can either add to an existing contact or use them to create a new contact.
else if (selectedCell == this.editContactCell)
{
var contact = new CNMutableContact();
// Phone number.
contact.PhoneNumbers = new CNLabeledValue<CNPhoneNumber>[] { new CNLabeledValue<CNPhoneNumber>(CNLabelPhoneNumberKey.iPhone, new CNPhoneNumber(PhoneNumber.Mobile)) };
// Postal address.
var homeAddress = new CNMutablePostalAddress()
{
Street = Address.Street,
City = Address.City,
State = Address.State,
PostalCode = Address.PostalCode,
};
contact.PostalAddresses = new CNLabeledValue<CNPostalAddress>[] { new CNLabeledValue<CNPostalAddress>(CNLabelKey.Home, homeAddress) };
// Create a view controller that allows editing.
var contactViewController = CNContactViewController.FromUnknownContact(contact);
contactViewController.AllowsEditing = true;
contactViewController.ContactStore = new CNContactStore();
contactViewController.Delegate = this;
// Push the unknown contact in the view controler.
base.NavigationController.PushViewController(contactViewController, true);
}
// Called when users tap "Display and Edit Contact" in the UI.
// Searches for the contact specified whose last name and first name are respectively specified by contact.family and contact.given
else if (selectedCell == this.displayEditCell)
{
var name = $"{Name.Given} {Name.Family}";
this.FetchContact(name, (contacts) =>
{
if (contacts.Any())
{
var contactViewController = CNContactViewController.FromContact(contacts[0]);
contactViewController.AllowsEditing = true;
contactViewController.AllowsActions = true;
contactViewController.Delegate = this;
/*
Set the view controller's highlightProperty if
highlightedPropertyIdentifier exists. Thus, ensuring
that the contact's phone number specified by
highlightedPropertyIdentifier will be highlighted in the
UI.
*/
var highlightedPropertyIdentifiers = contacts[0].PhoneNumbers.FirstOrDefault()?.Identifier;
if (!string.IsNullOrEmpty(highlightedPropertyIdentifiers))
{
contactViewController.HighlightProperty(new NSString("phoneNumbers"), highlightedPropertyIdentifiers);
}
// Show the view controller.
base.NavigationController.PushViewController(contactViewController, true);
}
else
{
this.ShowAlert($"Could not find {name} in Contacts.");
}
});
}
}
/// <summary>
/// Exising contacts matching the specified name.
/// </summary>
private void FetchContact(string name, Action<CNContact[]> completion)
{
var result = store.GetUnifiedContacts(CNContact.GetPredicateForContacts(name),
new ICNKeyDescriptor[] { CNContactViewController.DescriptorForRequiredKeys },
out NSError error);
if (error != null)
{
Console.WriteLine($"Error: {error.LocalizedDescription}");
}
else
{
DispatchQueue.MainQueue.DispatchAsync(() => completion(result));
}
}
#endregion
#region ICNContactViewControllerDelegate
/// <summary>
/// Setting it to false prevents users to perform default actions such as dialing a phone number, when they select a contact property.
/// </summary>
[Export("contactViewController:shouldPerformDefaultActionForContactProperty:")]
public bool ShouldPerformDefaultAction(CNContactViewController viewController, CNContactProperty property)
{
return false;
}
/// <summary>
/// Used to dismiss the view controller when using init(forNewContact:) to create a new contact.
/// </summary>
[Export("contactViewController:didCompleteWithContact:")]
public void DidComplete(CNContactViewController viewController, CNContact contact)
{
base.NavigationController.PopViewController(true);
if (contact != null)
{
base.NavigationController.ShowAlert($"{contact.GetFormattedName()} was successfully added.");
}
}
#endregion
/* helpers */
static class PhoneNumber
{
public static string IPhone { get; } = "(408) 555-0126";
public static string Mobile { get; } = "(415) 123-4567";
}
static class Name
{
public static string Family { get; } = "Appleseed";
public static string Given { get; } = "Jane";
}
static class Address
{
public static string Street { get; } = "1 Infinite Loop";
public static string City { get; } = "Cupertino";
public static string State { get; } = "CA";
public static string PostalCode { get; } = "95014";
}
}
}

98
Contacts/Contacts/RootViewController.designer.cs сгенерированный Normal file
Просмотреть файл

@ -0,0 +1,98 @@
// WARNING
//
// This file has been generated automatically by Visual Studio to store outlets and
// actions made in the UI designer. If it is removed, they will be lost.
// Manual changes to this file may not be handled correctly.
//
using Foundation;
using System.CodeDom.Compiler;
namespace Contacts
{
[Register ("RootViewController")]
partial class RootViewController
{
[Outlet]
UIKit.UITableViewCell createNewContactCell { get; set; }
[Outlet]
UIKit.UITableViewCell createNewContactExistingData { get; set; }
[Outlet]
UIKit.UITableViewCell displayEditCell { get; set; }
[Outlet]
UIKit.UITableViewCell editContactCell { get; set; }
[Outlet]
UIKit.UITableViewCell enableContactsPredicateCell { get; set; }
[Outlet]
UIKit.UITableViewCell pickMultipleContactsCell { get; set; }
[Outlet]
UIKit.UITableViewCell pickMultiplePropertiesCell { get; set; }
[Outlet]
UIKit.UITableViewCell pickSingleContactCell { get; set; }
[Outlet]
UIKit.UITableViewCell pickSinglePropertyCell { get; set; }
[Outlet]
UIKit.UITableViewCell selectContactsPredicateCell { get; set; }
void ReleaseDesignerOutlets ()
{
if (createNewContactCell != null) {
createNewContactCell.Dispose ();
createNewContactCell = null;
}
if (createNewContactExistingData != null) {
createNewContactExistingData.Dispose ();
createNewContactExistingData = null;
}
if (displayEditCell != null) {
displayEditCell.Dispose ();
displayEditCell = null;
}
if (editContactCell != null) {
editContactCell.Dispose ();
editContactCell = null;
}
if (pickMultipleContactsCell != null) {
pickMultipleContactsCell.Dispose ();
pickMultipleContactsCell = null;
}
if (pickMultiplePropertiesCell != null) {
pickMultiplePropertiesCell.Dispose ();
pickMultiplePropertiesCell = null;
}
if (pickSingleContactCell != null) {
pickSingleContactCell.Dispose ();
pickSingleContactCell = null;
}
if (pickSinglePropertyCell != null) {
pickSinglePropertyCell.Dispose ();
pickSinglePropertyCell = null;
}
if (enableContactsPredicateCell != null) {
enableContactsPredicateCell.Dispose ();
enableContactsPredicateCell = null;
}
if (selectContactsPredicateCell != null) {
selectContactsPredicateCell.Dispose ();
selectContactsPredicateCell = null;
}
}
}
}

42
Contacts/LICENSE.txt Normal file
Просмотреть файл

@ -0,0 +1,42 @@
Sample code project: ManagingContactsUI: Using ContactsUI View Controllers and Properties
Version: 1.0
IMPORTANT: This Apple software is supplied to you by Apple
Inc. ("Apple") in consideration of your agreement to the following
terms, and your use, installation, modification or redistribution of
this Apple software constitutes acceptance of these terms. If you do
not agree with these terms, please do not use, install, modify or
redistribute this Apple software.
In consideration of your agreement to abide by the following terms, and
subject to these terms, Apple grants you a personal, non-exclusive
license, under Apple's copyrights in this original Apple software (the
"Apple Software"), to use, reproduce, modify and redistribute the Apple
Software, with or without modifications, in source and/or binary forms;
provided that if you redistribute the Apple Software in its entirety and
without modifications, you must retain this notice and the following
text and disclaimers in all such redistributions of the Apple Software.
Neither the name, trademarks, service marks or logos of Apple Inc. may
be used to endorse or promote products derived from the Apple Software
without specific prior written permission from Apple. Except as
expressly stated in this notice, no other rights or licenses, express or
implied, are granted by Apple herein, including but not limited to any
patent rights that may be infringed by your derivative works or by other
works in which the Apple Software may be incorporated.
The Apple Software is provided by Apple on an "AS IS" basis. APPLE
MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
Copyright (C) 2017 Apple Inc. All Rights Reserved.

10
Contacts/Metadata.xml Normal file
Просмотреть файл

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<SampleMetadata>
<ID>3d6ede64-4510-4bfc-a386-66bd622ddb1e</ID>
<IsFullApplication>true</IsFullApplication>
<Brief>This sample is a set of sample code that demonstrates how to use ContactsUI view controllers and properties.</Brief>
<SupportedPlatforms>iOS</SupportedPlatforms>
<Level>Intermediate</Level>
<Tags>Contacts</Tags>
<Gallery>true</Gallery>
</SampleMetadata>

27
Contacts/README.md Normal file
Просмотреть файл

@ -0,0 +1,27 @@
Contacts: Using ContactsUI View Controllers and Properties
============
This sample is a set of sample code that demonstrates how to use ContactsUI view controllers and properties.
![Home Screen](Screenshots/screenshot-1.png)
Build Requirements
-------
Xcode 9.0 or later; iOS 10.3 SDK or later
Related Links
-------
- [Original sample](https://developer.apple.com/library/archive/samplecode/ManagingContactsUI/Introduction/Intro.html)
- [Documentation](https://developer.apple.com/documentation/contactsui)
License
-------
Xamarin port changes are released under the MIT license.
Author
------
Ported to Xamarin.iOS by Mykyta Bondarenko

Двоичные данные
Contacts/Screenshots/screenshot-1.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 77 KiB

Двоичные данные
Contacts/Screenshots/screenshot-2.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 40 KiB

Двоичные данные
Contacts/Screenshots/screenshot-3.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 56 KiB

Двоичные данные
Contacts/Screenshots/screenshot-4.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 62 KiB