How to create contacts list like whats app did - ios

I'm working on an app that creates an user profile. I need to be able to see who from my contacts has the app installed so that i am able to grant them access to my profile and see their profiles.
How do i get the full contact list, determine my phone number to create my account with it, and check how many people from the contacts have the app installed? (similar to how WhatsApp does it)
I know it's possible to get the contact list by using Apple API's, but do i have to send all the information to the server to check if they have the app installed?
Thank you.

I think you are managing one local database to store users locally.
First, You must have one contact mapping table on server that determines which number is allocate to which user (Each user must have unique number per account).
You have to pass array of phone numbers to your server request and fire query to get only those users whose phone numbers are in array.
You get one users objects array and that array you have to save in local database. (You can store all contacts in local database and update record (for appId, contactId, server name etc) is user is application user).
Finally these users who has appId are your application users.
Hope this concept might help you.

If you are using webservices your backend will can give the contacts which are using your application.
For getting the app contacts you have to use user phone number using phone number you can get the app user through webservices

to get all contact from Phonebook you can use below method in swift
first import Contacts
func FetchContact()
{
if #available(iOS 9.0, *) {
let contactStore = CNContactStore()
do {
let request:CNContactFetchRequest
request = CNContactFetchRequest(keysToFetch: [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactMiddleNameKey, CNContactEmailAddressesKey,CNContactPhoneNumbersKey])
request.sortOrder = CNContactSortOrder.GivenName
try contactStore.enumerateContactsWithFetchRequest(request) {
(contact, cursor) -> Void in
self.dataArray?.addObject(contact)
}
}
catch{
print("Handle the error please")
}
//self.collectionView?.reloadData()
}
}

Related

When i terminate app MUC group chat members are getting removed

When i terminate app MUC group chat members are getting removed, i have to join them again while coming back to app from bookmarks? We do not want to rejoin again and again. Can someone please suggest way how to avoid rejoining.
In Android smack there is provision for auto-rejoin.
Even from Openfire back end we have managed code to do not remove.
So Android is working fine, iOS is removing users.
Please do suggest.
Instead of rejoining the room every time, do set the presence of the group when the user relaunches the app.
Set presence with below code function iterate through all your groups name and set presence:
for group in chatListModel ?? []{
if(group.opponent_type == "2"){
print("Group Name: \(group.opponent_uuid ?? "")")
XMPPGlobal.sharedIntanceXMPP.xmppController.updatePresence(roomJID: XMPPJID(string: "\(group.opponent_uuid ?? "")#\(groupServerName)"))
}
}
Define below function in your XMPPController class:
func updatePresence(roomJID : XMPPJID?) {
let presence = XMPPPresence(type: "presence")
presence.addAttribute(withName: "from", stringValue: self.xmppStream.myJID?.user ?? "")
presence.addAttribute(withName: "to", stringValue: "\(roomJID?.full ?? "")/\(self.xmppStream.myJID?.user ?? "")")
let element = DDXMLElement.init(name: "x", xmlns: XMPPMUCNamespace)
presence.addChild(element)
self.xmppStream.send(presence)
}
Hope it will works for you.
In spite of the fact that there is the answer.
I would like to elaborate a little bit :)
In case of MUC rooms: there is an affiliation, i.e. long-lasting role (admin, owner, etc) and "subscription" role (visitor, member etc).
What you are asking is per se described in XMPP MUC. 7.1 Order of Events
You send your presence to join the room, and receive presence from other other participants, you can also get some cached messages if your XMPP backend was configured properly.
For instance for ejabberd (process-one): mod_muc: history_size settings defines in-memory cache.
You might don't want to get set of room events, as described in 7.1 above.
There might be some server's extensions. In case of ejabberd there is MUCPubSub you send your subscription (not presence) and get the following messages, plus you can get list of members or track its changes, and etc:
<subscribe xmlns='urn:xmpp:mucsub:0'
nick='mynick'
password='roompassword'>
<event node='urn:xmpp:mucsub:nodes:messages' />

Given a users UID can I access his profile info?

I know that I can save user info to his profile with firebase. But I am wondering if I am able to get this same info when all I have is a UID?
As I understand it I can only do this to get the info:
Auth.auth().currentUser.displayName...
It seems like If I want to be able to fetch other users info I would have to keep a copy of their data in a users node.
Am I correct? Or can I access their profile info withought having to keep a copy?
If you use firebase authentication, then you can retrieve the current user info. So, if currently user X is logged in and he is authenticated, you can retrieve the following info about him:
let user = Auth.auth().currentUser
if let user = user {
// The user's ID, unique to the Firebase project.
// Do NOT use this value to authenticate with your backend server,
// if you have one. Use getTokenWithCompletion:completion: instead.
let uid = user.uid
let email = user.email
let photoURL = user.photoURL
// ...
}
If you want to retrieve information about other users, then in that case you need to use firebase database:
users
userId (firebase authentication)
name : user X
userId
name : user Y
Depending on the reason you need this data, you can actually get access to an auth user by using the firebase-admin package.
inside of your firebase function - or node.js backend - (this is only for backend node.js functions, not for front-end), you can get the user by doing the following:
const admin = require("firebase-admin");
const authUser = await admin.auth().getUser(uid);
authUser = authUser.toJSON(); // Optional
You can read more about retrieving user data here
If you want to load in multiple users at once, you can easily use the getUsers function and it's also possible to load in the user based on other information like email:
getUser(uid)
getUserByEmail(email)
getUserByPhoneNumber(phoneNumber)

AWS AppSync multiple subscriptions in same view controller not working - iOS Swift

Just FYI I posted this question originally in the AWS AppSync forum (in case in the future AWS answers it).
I have been trying to make a simple Posts app like the one in the docs but I have found no documentation or guides that handle multiple subscriptions in one view controller.
Three mutations: onCreatePost, onUpdatePost, onDeletePost
(and of course three subscriptions to those mutations)
In Xcode, I have three functions called during viewDidLoad(): subscribeToNewPosts(), subscribeToUpdatedPosts(), subscribeToDeletedPosts()
Each subscription function works and creates a subscription with the correct functionality and updates the table view accordingly if used alone. But, if called one after the other, only the last subscription will actually receive data and update the table view. I put a breakpoint to check out topicSubscribersDictionary in AppSyncMQTTClient.swift after subscribing to all three mutations
func startNewSubscription(subscriptionInfo: AWSSubscriptionInfo) {
var topicQueue = [String]()
let mqttClient = MQTTClient<AnyObject, AnyObject>()
mqttClient.clientDelegate = self
for topic in subscriptionInfo.topics {
if topicSubscribersDictionary[topic] != nil {
// if the client wants subscriptions and is allowed we add it to list of subscribe
topicQueue.append(topic)
}
}
mqttClients.append(mqttClient)
mqttClientsWithTopics[mqttClient] = topicQueue
mqttClient.connect(withClientId: subscriptionInfo.clientId, toHost: subscriptionInfo.url, statusCallback: nil)
}
and all three subscriptions are in fact in the dictionary...
Do I need multiple instances of appSyncClient, one for each subscription? Is it a problem with the schema design?
schema.graphql
schema.json
mutations.graphql
queries.graphql
subscriptions.graphql
Example use case: simple chat app. New conversation started = OnCreatePostSubscription; new incoming message in that conversation = OnUpdatePostSubscription
Are you using API Key for authorization in AppSync? If you are using API Key only one subscription is supported by the SDK at this point. Could you switch to IAM (Cognito Identity) or Cognito UserPools based auth and see if multiple subscriptions work for you?
I managed to have several subscriptions working with API Key by replacing the call startSubscriptions to startNewSubscription inside AWSAppSyncSubscriptionWatcher
if let subscriptionInfo = subscriptionResult.subscrptionInfo {
self.subscriptionTopic = subscriptionResult.newTopics
self.client?.addWatcher(watcher: self, topics: subscriptionResult.newTopics!, identifier: self.uniqueIdentifier)
//self.client?.startSubscriptions(subscriptionInfo: subscriptionInfo)
subscriptionInfo.forEach { self.client?.startNewSubscription(subscriptionInfo: $0) }
}
Couldn't find any side effect with this approach yet, apart from requiring to fork the iOS SKD

Save email address to accounts app iOS

I have two apps (eg: App1 and App2) which requires login with an account. What I need to achieve is when an user log-in successfully into the App1, the email address should get saved to the default Accounts app of the device. Then when the user opens up the App2, the email address saved from App1 should show up as a recommendation for the user if he need to use the same account to sign in to App2 as well. Just like some apps do if you click on sign in with Google or Facebook.
Since I am new to iOS, I need to ask if this is possible to achieve in iOS and if yes what procedure should I follow.
EDIT
I tried implementing KeyChain for this. Something like below :-
void StoreKeysInKeychain (string key, string value) {
var s = new SecRecord (SecKind.GenericPassword) {
ValueData = NSData.FromString (value),
Generic = NSData.FromString (key)
};
var err = SecKeyChain.Add (s);
}
void GetRecordsFromKeychain (string key)
{
SecStatusCode res;
var rec = new SecRecord (SecKind.GenericPassword) {
Generic = NSData.FromString (key)
};
var match = SecKeyChain.QueryAsRecord (rec, out res);
if (match != null) {
// nsdata object : match.ValueData;
}
}
This way when I login to the App1 with an email address it gets saved and when I open the App2 I get that email address. This works fine. But now the issue is that if I logout from App1 and login with another email address. That account is not visible in App2. How can I get a list of all the email address?
Any help is appreciated.
you need to use app Group to share information among app, Enable app Group from build settings in both app and certificate , assign same group to them , and put information for each other on a suite of NSuserdefault .
Xamarin documentation for app group is here : https://developer.xamarin.com/guides/ios/watch/working-with/app-groups/
I believe you can set up a ParseServer that user account management for both apps

Struggling to Understand CKSubscriptions in CloudKit

I've been reading about and trying to use the CKSubscription feature for weeks, but I can't find info about some general questions. I've read Apple docs, online tutorials, books I bought, and questions here on SO, but I still don't understand the fundamentals I think. Any help is very much appreciated.
Here are questions I cannot find answers to:
1). What is the purpose of the subscriptionID? The convenience init does not include it, so why is it needed in the designated init? If you use it, is it the same for all users of the app?
2). I saw someone mention here that you can unregister a subscriptionID. Why or how would you do this?
3). Can subscriptions be setup in both public or the user's private database?
4). If I have a query based subscription that is the same for all users, will there only ever be 1 subscription listed in the database?
For instance, I'm having trouble getting notifications to work with my
specific use case. It's not a problem in my setup, as I can get a True predicate to work and the notification comes. So I must not understand the fundamentals of how subscriptions work still.
I'm trying to setup a subscription that fires whenever a new record is created when a different user makes a comment on a post. This new record will then contain a reference to the user who created the post. The only subscription I see in the database for both users is - Notifications.user (equals reference). So, I'm assuming I'll only ever see this one subscription.(?) But how does the server keep track of every user's recordID or know when to send it to a specific device?
The problem is I can't get the notification to work. I manually add a record in the dashboard, and I put the other user's recordID as the CKReference. While I'm adding the record, I have the app running in the background on a device under the user's account whom I added as the CKReference in the field. I'd expect the query to trigger and send a push notification since someone commented on this user's post.
Here's my code to setup the subscription:
func subscribe(userID: CKRecordID) {
let options = CKSubscriptionOptions.FiresOnRecordCreation
let userRef = CKReference(recordID: userID, action: .DeleteSelf)
let predicate = NSPredicate(format: "userRef == %#", userRef)
let predicateTwo = NSPredicate(format: "read = %#", "")
let compoundPred = NSCompoundPredicate(type: .AndPredicateType, subpredicates: [predicate, predicateTwo])
let subscription = CKSubscription(recordType: "Notifications", predicate: compoundPred, subscriptionID: subscriptionID,
options: options)
subscription.notificationInfo = CKNotificationInfo()
subscription.notificationInfo.desiredKeys = ["userPost"]
subscription.notificationInfo.alertBody = "Someone replied to your Pod post"
publicDB.saveSubscription(subscription, completionHandler: {
subscription, error in
if (error != nil) {
println("error subscribing: \(error)")
} else {
println("subscribed!")
}
})
}
Let me try and answer:
SubscriptionId allows you to identify later a subscription for example to delete it using the CKDatabase method deleteSubscriptionWithID
For how see answer 1. As to why, well maybe you do not want to get notifications on this subscription any more. This depends on what you are trying to achieve with your app.
Yes
Yes, if you register only one subscription it should work for all users of your app
Regarding your issues, please note that a user recordIDs are special, so you may have issues specifically related to that due to the privacy issues around them. I would suggest to try a simple case that does not involve users and see if subscriptions are working for you. Then think again about how you use user record IDs

Resources