rust_macios/contacts/
cn_contact_store.rs

1use block::{ConcreteBlock, IntoConcreteBlock};
2use objc::{msg_send, sel, sel_impl};
3
4use crate::{
5    foundation::{NSArray, NSData, NSEnumerator, NSError, NSPredicate, NSString},
6    object,
7    objective_c_runtime::{
8        id,
9        macros::interface_impl,
10        nil,
11        traits::{FromId, PNSObject},
12    },
13    utils::to_bool,
14};
15
16use super::{
17    CNChangeHistoryEvent, CNChangeHistoryFetchRequest, CNContact, CNContactFetchRequest,
18    CNContainer, CNFetchResult, CNGroup, CNSaveRequest,
19};
20
21/// The entities the user can grant access to.
22#[derive(Debug, Copy, Clone, PartialEq, Eq)]
23#[repr(i64)]
24pub enum CNEntityType {
25    /// The user's contacts.
26    Contacts,
27}
28
29/// An authorization status the user can grant for an app to access the specified entity type.
30#[derive(Debug, Copy, Clone, PartialEq, Eq)]
31#[repr(i64)]
32pub enum CNAuthorizationStatus {
33    /// The user has not yet made a choice regarding whether the application may access contact data.
34    NotDetermined = 0,
35    /// The application is not authorized to access contact data. The user cannot change this application’s status, possibly due to active restrictions such as parental controls being in place.
36    Restricted,
37    /// The user explicitly denied access to contact data for the application.
38    Denied,
39    /// The application is authorized to access contact data.
40    Authorized,
41}
42
43object! {
44    /// The object that fetches and saves contacts, groups, and containers from the user's contacts database.
45    unsafe pub struct CNContactStore;
46}
47
48#[interface_impl(NSObject)]
49impl CNContactStore {
50    /// Requests access to the user's contacts.
51    #[method]
52    pub fn request_access_for_entity_type_completion_handler<F>(
53        &self,
54        entity_type: CNEntityType,
55        completion_handler: F,
56    ) where
57        F: IntoConcreteBlock<(bool, *mut NSError), Ret = ()> + 'static,
58    {
59        let block = ConcreteBlock::new(completion_handler);
60        let block = block.copy();
61
62        unsafe {
63            msg_send![
64                self.m_self(),
65                requestAccessForEntityType: entity_type
66                completionHandler: block
67            ]
68        }
69    }
70
71    /// Returns the current authorization status to access the contact data.
72    #[method]
73    pub fn authorization_status_for_entity_type(
74        entity_type: CNEntityType,
75    ) -> CNAuthorizationStatus {
76        unsafe {
77            msg_send![
78                Self::m_class(),
79                authorizationStatusForEntityType: entity_type
80            ]
81        }
82    }
83
84    /* Fetching Contacts
85     */
86
87    /// Returns a Boolean value that indicates whether the enumeration of all contacts matching a contact fetch request executed successfully.
88    #[method]
89    pub fn enumerate_contacts_with_fetch_request_using_block<F>(
90        &self,
91        fetch_request: CNContactFetchRequest,
92        block: F,
93    ) -> Result<bool, NSError>
94    where
95        F: IntoConcreteBlock<(CNContact, *mut bool), Ret = ()> + 'static,
96    {
97        let mut error = NSError::m_alloc();
98        let block = ConcreteBlock::new(block);
99        let block = block.copy();
100
101        unsafe {
102            let ptr = msg_send![
103                self.m_self(),
104                enumerateContactsWithFetchRequest: fetch_request
105                error: &mut error
106                usingBlock: block
107            ];
108
109            if error.m_self() == nil {
110                Ok(ptr)
111            } else {
112                Err(error)
113            }
114        }
115    }
116
117    /// Fetches the unified contact that’s the me card.
118    #[method]
119    pub fn unified_me_contact_with_keys_to_fetch(
120        &self,
121        keys: NSArray<id>,
122    ) -> Result<CNContact, NSError> {
123        let mut error = NSError::m_alloc();
124
125        unsafe {
126            let result = CNContact::from_id(msg_send![
127                self.m_self(),
128                unifiedMeContactWithKeysToFetch: keys
129                error: &mut error
130            ]);
131
132            if error.m_self() == nil {
133                Ok(result)
134            } else {
135                Err(error)
136            }
137        }
138    }
139
140    /// Fetches a unified contact for the specified contact identifier.
141    #[method]
142    pub fn unified_contact_with_identifier_keys_to_fetch(
143        &self,
144        identifier: NSString,
145        keys: NSArray<id>,
146    ) -> Result<CNContact, NSError> {
147        let mut error = NSError::m_alloc();
148        unsafe {
149            let result = CNContact::from_id(msg_send![
150                self.m_self(),
151                unifiedContactWithIdentifier: identifier
152                keysToFetch: keys
153                error: &mut error
154            ]);
155
156            if error.m_self() == nil {
157                Ok(result)
158            } else {
159                Err(error)
160            }
161        }
162    }
163
164    /// Fetches all unified contacts matching the specified predicate.
165    #[method]
166    pub fn unified_contacts_matching_predicate_keys_to_fetch(
167        &self,
168        predicate: NSPredicate,
169        keys: NSArray<id>,
170    ) -> Result<NSArray<CNContact>, NSError> {
171        unsafe {
172            let mut error = NSError::m_alloc();
173            let result = NSArray::from_id(msg_send![
174                self.m_self(),
175                unifiedContactsMatchingPredicate: predicate
176                keysToFetch: keys
177                error: &mut error
178            ]);
179
180            if error.m_self() == nil {
181                Ok(result)
182            } else {
183                Err(error)
184            }
185        }
186    }
187
188    /// Enumerates a contact fetch request.
189    #[method]
190    pub fn enumerator_for_contact_fetch_request(
191        &self,
192        fetch_request: CNContactFetchRequest,
193    ) -> Result<CNFetchResult<NSEnumerator<CNContact>>, NSError> {
194        unsafe {
195            let mut error = NSError::m_alloc();
196            let result = CNFetchResult::from_id(msg_send![
197                self.m_self(),
198                enumeratorForContactFetchRequest: fetch_request
199                error: &mut error
200            ]);
201
202            if !result.m_self().is_null() {
203                Ok(result)
204            } else {
205                Err(error)
206            }
207        }
208    }
209
210    /* Fetching Groups and Containers
211     */
212
213    /// Returns the identifier of the default container.
214    #[method]
215    pub fn default_container_identifier(&self) -> NSString {
216        unsafe { NSString::from_id(msg_send![self.m_self(), defaultContainerIdentifier]) }
217    }
218
219    /// Fetches all groups matching the specified predicate.
220    #[method]
221    pub fn groups_matching_predicate(
222        &self,
223        predicate: NSPredicate,
224    ) -> Result<NSArray<CNGroup>, NSError> {
225        unsafe {
226            let mut error = NSError::m_alloc();
227
228            let result = NSArray::from_id(msg_send![
229                self.m_self(),
230                groupsMatchingPredicate: predicate
231                error: &mut error
232            ]);
233
234            if error.m_self() == nil {
235                Ok(result)
236            } else {
237                Err(error)
238            }
239        }
240    }
241
242    /// Fetches all containers matching the specified predicate.
243    #[method]
244    pub fn containers_matching_predicate(
245        &self,
246        predicate: NSPredicate,
247    ) -> Result<NSArray<CNContainer>, NSError> {
248        unsafe {
249            let mut error = NSError::m_alloc();
250            let result = NSArray::from_id(msg_send![
251                self.m_self(),
252                containersMatchingPredicate: predicate
253                error: &mut error
254            ]);
255
256            if error.m_self() == nil {
257                Ok(result)
258            } else {
259                Err(error)
260            }
261        }
262    }
263
264    /* Fetching Change History Info
265     */
266
267    /// Enumerates a change history fetch request.
268    #[method]
269    pub fn enumerator_for_change_history_fetch_request(
270        &self,
271        request: CNChangeHistoryFetchRequest,
272    ) -> Result<CNFetchResult<NSEnumerator<CNChangeHistoryEvent>>, NSError> {
273        unsafe {
274            let mut error = NSError::m_alloc();
275            let result = CNFetchResult::from_id(msg_send![
276                self.m_self(),
277                enumeratorForChangeHistoryFetchRequest: request
278                error: &mut error
279            ]);
280
281            if result.m_self() == nil {
282                Ok(result)
283            } else {
284                Err(error)
285            }
286        }
287    }
288
289    /// The current history token.
290    #[property]
291    pub fn current_history_token(&self) -> NSData {
292        unsafe { NSData::from_id(msg_send![self.m_self(), currentHistoryToken]) }
293    }
294
295    /* Saving Changes
296     */
297
298    /// Executes a save request and returns success or failure.
299    #[method]
300    pub fn execute_save_request(&self, request: CNSaveRequest) -> Result<bool, NSError> {
301        unsafe {
302            let mut error = NSError::m_alloc();
303
304            let ptr =
305                to_bool(msg_send![self.m_self(), executeSaveRequest: request error: &mut error]);
306
307            if error.m_self() != nil {
308                Err(error)
309            } else {
310                Ok(ptr)
311            }
312        }
313    }
314}
315
316extern "C" {
317    /// The shared contact store.
318    pub static CNContactStoreDidChangeNotification: *const NSString;
319}