I have only one phone and Apple ID. I want to test CKShare between two users. Do I need two phones? Do I need two different Apple IDs? I read that two Apple IDs cannot share same phone. Can someone tell me what is the best way to test CKShare between two users on my development environment
Post
Replies
Boosts
Views
Activity
I create a share and the shared URL is successfully created
let share = CKShare(rootRecord: infraRecord)
// save
let op: CKFetchShareParticipantsOperation = CKFetchShareParticipantsOperation(userIdentityLookupInfos: lookupInfos)
op.fetchShareParticipantsCompletionBlock = { error in
if let error = error {
print("error: ", error)
completion(false, error)
}
}
op.shareParticipantFetchedBlock = { participant in
participant.permission = .readOnly
share.addParticipant(participant)
let modOp: CKModifyRecordsOperation = CKModifyRecordsOperation(recordsToSave: [infraRecord, share], recordIDsToDelete: nil)
modOp.savePolicy = .ifServerRecordUnchanged
modOp.perRecordCompletionBlock = {record, error in
print("record completion \(record) and \(String(describing: error))")
}
modOp.modifyRecordsCompletionBlock = {records, recordIDs, error in
if let error = error {
print("error in modifying the records: ", error)
}
else if let anURL = share.url {
// update the location CKRecord with share URL
self.updateLocationPublicRecord(withShareUrl: anURL.absoluteString, locationRecord: locationRecord, completion: { (status, error) in
if let error = error {
print("error: ", error)
}
})
print("share url \(String(describing: share.url))")
}
completion(true, nil)
}
self.privateDB?.add(modOp)
//completion(true, nil)
}
self.defaultContainer?.add(op)
To access the share I first try to get the recordzones from shared database
func getRecordZones(completion: @escaping (CKRecordZoneID?, Error?) -> Void) {
self.sharedDB?.fetchAllRecordZones(completionHandler: { (ckrecordZones, error) in
guard error == nil else {
if let ckError = error as? CKError {
self.aErrorHandler.handleCkError(ckerror: ckError)
}
completion (nil, error)
return
}
if let recordZones = ckrecordZones {
for i in 0 ..< recordZones.count{
// find the zone you want to query
if recordZones[i].zoneID.zoneName == Cloud.SharedZone.UserProfile.ZoneName {
completion (recordZones[i].zoneID, nil)
}
}
}
})
}
```
I dont get any recordzones from shared database. When I go to cloudkit dashboard, I don't see any shared zones in the shared database. Why is it that shared record zone does not exist? how to make this work?
Upgraded ios 13.6 and changed bundle identifier and container name. Created CKDatabaseSubscription for both public and shared database and can see in cloudkit dashboard. Both didFinishLaunchingWithOptions and didRegisterForRemoteNotificationsWithDeviceToken get called in AppDelegate.
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound], completionHandler: { granted, error in
guard granted else { return }
DispatchQueue.main.async {
application.registerForRemoteNotifications()
print("Registered for Remote notifications")
}
})
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data){
let tokenParts = deviceToken.map { data in String(format: "%02.2hhx", data) }
let token = tokenParts.joined()
print("Device Token: \(token)")
})
self.iCloudSubscribeToPrivateDB()
self.iCloudSubscribeToSharedDB()
}
In the project both background fetch and remote notifications are enabled. I make databases changes in cloudkit dashboard, but push notifications are not being sent. They were working now just stopped after I made the above changes. What could be wrong?
while presenting the UICloudSharingController on top of a view, it presents the screen and when I select the messages option to send a message to a person whom I want to share with, it gives a spinning wheel with "uploading" message and vanishes.
However when I go to cloudkit dashboard the root record has been shared. But I cannot share it with specific person. Is it because it has shared global? How can I fix it?
self.shareInfraRecord(zoneID: appDelegate.privateContactZoneID, completion: { (status) in
		 if ( status == false) {
						 return
			}
		})
func shareInfraRecord(zoneID: CKRecordZone.ID, completion: @escaping(Bool) -> Void) {
		if let rootRecord = self.rootRecord {
				if self.rootRecord?.share == nil {
						let sharingController = UICloudSharingController { (controller, preparationHandler: @escaping (CKShare?, CKContainer?, Error?) -> Void) in
								
								let shareID = CKRecord.ID(recordName: UUID().uuidString, zoneID: zoneID)
								var share = CKShare(rootRecord: rootRecord, shareID: shareID)
							
								share[CKShare.SystemFieldKey.title] = Cloud.ShareInfrastructure.ContactShareTitleKey as CKRecordValue?
								share[CKShare.SystemFieldKey.shareType] = Cloud.ShareInfrastructure.ContactShareTypeKey as CKRecordValue?
							
								let modifyRecZoneOp = CKModifyRecordsOperation(recordsToSave:[rootRecord, share], recordIDsToDelete: nil)
								modifyRecZoneOp.modifyRecordsCompletionBlock = { (records, recordID, error) in
										if error != nil {
												if let ckerror = error as? CKError {
														if let serverVersion = ckerror.serverRecord as? CKShare {
																share = serverVersion
														}
														completion(false)
												}
										}
										preparationHandler(share, self.defaultContainer, error)
								}
								self.privateDB?.add(modifyRecZoneOp)
						}
I drag a scroll view and then set constraint 0 on all four directions. I cannot activate update frame. Gives error ScrollView has ambiguous scalable content width and height
in Cloudkit Dashboard, I select Record Type, Edit Indexes, then I select Add Basic Index. I see createTime, createdBy, eTag, modTime, modifiedBy, recordID. I do not see recordName. Without creating index on recordName, I cannot query the record in cloudKit Dashboard. How to create index on recordName??
I have timer based code running perfectly when the app is running. Both the timer based functions get called and I am able to access and update iCloud. But if accidentally app goes off-line or user kills it, the timer code cannot be invoked. Is there a off-line mechanism, or some technique anyone can suggest that will allow to recollect and invoke pre-defined timer calls and execute the associated code?
let currentDateTime = Date()
let calendar = Calendar.current
var tempDateTime1 = calendar.date(byAdding: .minute, value: 1, to: currentDateTime)
var tempDateTime2 = calendar.date(byAdding: .minute, value: 2, to: currentDateTime)
DispatchQueue.main.async {
let userInfo:Dictionary<String, String> = ["tag": orderCkRecordName]
let startTimer = Timer(fireAt: tempDateTime1!, interval: 0.0, target: self, selector: #selector(self.beginOrderUpdate(sender:)), userInfo: userInfo as Dictionary, repeats: false)
let endTimer = Timer(fireAt: tempDateTime2!, interval: 0.0, target: self, selector: #selector(self.endOrderUpdate(sender:)), userInfo: userInfo as Dictionary, repeats: false)
RunLoop.current.add(startTimer, forMode: RunLoopMode.commonModes)
RunLoop.current.add(endTimer, forMode: RunLoopMode.commonModes)
}
I have a working app with core data and cloudkit. I changed the NSPersistentContainer to NSPersistentCloudKitContainer. Two NSManagedObjects 'Contact' and 'Location' already exist in core data with relationships along with some other related NSManagedObjects. Populated core data in 'Contact' and saved. Logged in to CloudKit to see it had created CD_Contact and CD_Location CKRecords along with some other CKRecords. Queried CD_Contact it gave error - index name not available on recordName. So created an Index of type Queryable on recordName and searched again. There is no data in CD_Contact.
It is supposed to sync data from core data to cloud Kit, but only CKRecord is created but data saved in core data is not synced and populated in CloudKit. How to fix this? On debug I get this:
"<CKRecord: 0x104f0afc0; recordType=CD_Contact, recordID=558FD3FB-A293-444C-8894-A1A7B786D73A:(com.apple.coredata.cloudkit.zone:__defaultOwner__), recordChangeTag=15, values={\n \"CD_assignedEEP\" = 0;\n \"CD_createdDate\" = \"2022-11-03 04:14:17 +0000\";\n \"CD_email\" = \"crsp@gmail\";\n \"CD_entityName\" = Contact;\n \"CD_firstName\" = chaya;\n \"CD_imageName\" = \"{ length=87143, sha256=ed66d0026ea41aed08e213928643398504dea984c010b80a8852a0fb72c80350 }\";\n \"CD_lastName\" = rao;\n \"CD_me\" = 0;\n \"CD_orgName\" = \"\";\n \"CD_phone\" = 8327292039;\n \"CD_screenName\" = cvr;\n \"CD_uniqueId\" = \"A2469E8D-782F-49F5-8186-3C38B8F9B715-55813-00001051FEDEEF2F\";\n \"CD_userRating\" = \"Not rated\";\n \"CD_userType\" = \"Consumer & Producer(Household)\";\n}>",
"CD_contactEmail" = "crsp@gmail";
"CD_contactEmail_ckAsset",
"CD_contact",
"CD_contactEmail",
"<CKRecord: 0x111659350; recordType=CD_Location, recordID=D6FA5778-587E-4778-925E-197AD5ABC66B:(com.apple.coredata.cloudkit.zone:__defaultOwner__), recordChangeTag=19, values={\n \"CD_apt\" = \"\";\n \"CD_assignedEEP\" = 0;\n \"CD_batterykWh\" = 0;\n \"CD_city\" = Houston;\n \"CD_contactEmail\" = \"crsp@gmail\";\n \"CD_country\" = US;\n \"CD_entityName\" = Location;\n \"CD_evkWh\" = 0;\n \"CD_latitude\" = \"29.92885756496788\";\n \"CD_loadWatts\" = 0;\n \"CD_loadkWh\" = 0;\n \"CD_locationName\" = myloc;\n \"CD_locationType\" = Household;\n \"CD_longitude\" = \"-95.60777006842892\";\n \"CD_netMeterEsid\" = 1008901023808105650100;\n \"CD_provider\" = \"AMIGO ENERGY\";\n \"CD_providerType\" = \"Energy Provider\";\n \"CD_solarkWh\" = 0;\n \"CD_state\" = TX;\n \"CD_street\" = \"11202 Hillside Glen Trail \";\n \"CD_uniqueId\" = \"27D61490-B38A-4F0A-A5EC-76BDBDEBA46F-55813-00001052B902170C\";\n \"CD_windkWh\" = 0;\n \"CD_zip\" = 77065;\n}>"
My AppDelegate Code:
let container = NSPersistentCloudKitContainer(name: "MyModel")
let defaultStoreURL = try! FileManager.default.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent("MyModel.xcdatamodeld")
let description = NSPersistentStoreDescription(url: defaultStoreURL)
let cloudkitOptions = NSPersistentCloudKitContainerOptions(containerIdentifier: "iCloud.com.ggp.nr")
description.cloudKitContainerOptions = cloudkitOptions
let remoteChangeKey = "NSPersistentStoreRemoteChangeNotificationOptionKey"
description.setOption(true as NSNumber,
forKey: remoteChangeKey)
description.setOption(true as NSNumber,
forKey: NSPersistentHistoryTrackingKey)
container.persistentStoreDescriptions = [description]
container.viewContext.automaticallyMergesChangesFromParent = true
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
fatalError("Unresolved error \(error), \(error.userInfo)")
}
// if FileManager.default.fileExists(atPath: self.storeURL.path) {
// self.duplicateRecordsAndDeleteOldStore(newContext: container.newBackgroundContext(), mom: container.managedObjectModel)
// }
})
return container
}()
Also in my cloudKit database "iCloud.com.ggp.nr", under security roles for iCloud and World I have set Read and Write permissions for all the CD_ Records.
Don't know what else to do. Any help is appreciated.
Inside the core data database, I created new private configuration. Then Created a new entity which got added to default configuration. Dragged the new entity to the newly created private configuration. It crashes.
Am I doing this right? If so is it Xcode 13.3.1 bug ? and should I upgrade?
Once I get past this issue, will the below given load persistent stores code
export/synchronize the new entity from core data private configuration to cloudkit private database?
container.loadPersistentStores(completionHandler: { (loadedStoreDescription, error) in
if let loadError = error as NSError? {
fatalError("###\(#function): Failed to load persistent stores:\(loadError)")
} else if let cloudKitContainerOptions = loadedStoreDescription.cloudKitContainerOptions {
if #available(iOS 14.0, *) {
if .public == loadedStoreDescription.cloudKitContainerOptions?.databaseScope {
self._publicPersistentStore = container.persistentStoreCoordinator.persistentStore(for: loadedStoreDescription.url!)
} else if .private == loadedStoreDescription.cloudKitContainerOptions?.databaseScope {
self._privatePersistentStore = container.persistentStoreCoordinator.persistentStore(for: loadedStoreDescription.url!)
}
} else {
// Fallback on earlier versions
}
}
The NSPersistentCloudKitContainer synchronization between core data and
iCloud was working fine with phone 15.1. Connected a new iPhone iOS 15.5, it gives error:
CoreData: debug: CoreData+CloudKit: -[NSCloudKitMirroringDelegate managedObjectContextSaved:](2504): <NSCloudKitMirroringDelegate: 0x28198c000>: Observed context save: <NSPersistentStoreCoordinator: 0x2809c9420> - <NSManagedObjectContext: 0x2819ad520>
2022-12-05 13:32:28.377000-0600 r2nr[340:6373] [error] error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1245): <PFCloudKitImporter: 0x2837dd740>: Import failed with error:
Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)}
CoreData: error: CoreData+CloudKit: -[NSCloudKitMirroringDelegate _importFinishedWithResult:importer:](1245): <PFCloudKitImporter: 0x2837dd740>: Import failed with error:
Error Domain=NSCocoaErrorDomain Code=4864 "*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)" UserInfo={NSDebugDescription=*** -[NSKeyedUnarchiver _initForReadingFromData:error:throwLegacyExceptions:]: incomprehensible archive (0x53, 0x6f, 0x6d, 0x65, 0x20, 0x65, 0x78, 0x61)}
I go back and try with my old iPhone iOS 15.1, gives same error.
If several users are sharing records with .readwrite permission with me, how can I find out who shared which CKRecord? I know user information is confidential information. But I need to be able to find out who shared so I can react to the shared record by either modifying or ignoring. I cannot find anything in Cloud Sharing website by Apple. Can someone give ideas/ponters?
In Xcode 14.2 Data Model is displayed as source code. I cannot change the view to relationships and cannot generate NSManagedObject classes. It is veriy difficult tom work with source code as I have more than 30 entities with inter-relationships. Can someone help.
display simple view with two text fields inside a vStack/HStack combination. It leaves huge gap at the top as shown on the attached image. I tried vStack, it has .leading and .trailing which justifies left or right. How can set specific spacing at the top? code:
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.dismiss) var dismiss
@Environment(\.presentationMode) var presentationMode
@Binding var chosenPlan: ProviderApiCaller.ProviderData
@State var state: String?
@State var zip: String?
func onAdd(plan: ProviderApiCaller.ProviderData ) {
}
var body: some View {
NavigationView {
VStack {
HStack {
Text(chosenPlan.name!)
}
HStack {
Text(chosenPlan.plans.first!.planUrl)
}
}
}
.navigationTitle("Plan Details")
.toolbar {
// Back button
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { presentationMode.wrappedValue.dismiss() }, label: {
HStack(spacing: 2) {
Image(systemName: "chevron.backward")
.foregroundColor(.black)
Button("Back", action: {
self.presentationMode.wrappedValue.dismiss()
} )
.foregroundColor(.black)
}
})
}
ToolbarItem(placement: .confirmationAction) {
// Button("Save", action: { Task { try? await rI?(nameInput, phoneInput) } })
Button("Save", action: { onAdd(plan: chosenPlan)
} )
.foregroundColor(.blue)
}
}
.navigationViewStyle(StackNavigationViewStyle())
.navigationBarBackButtonHidden(true)
}
![]("https://developer.apple.com/forums/content/attachment/7510538e-c8b1-42d2-a68a-94d5aeaac186" "title=Screenshot 2023-05-26 at 4.11.30 PM.png;width=429;height=881")
I have an existing ScrollView view with a Picker. Upon selection of a picker value, and user pressing the details button, I want to append a view to the bottom of the existing view. I call detailsView. But it does not seem to work.
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.dismiss) var dismiss
@Environment(\.presentationMode) var presentationMode
@Binding var chosenProvider: Provider?
@State var selectedLocation: Location?
@State private var vendorNames: [String] = []
@State private var selectedVendor:String? = nil
@State private var showingSheet = false
@State var state: String?
@State var zip: String?
var body: some View {
ScrollView {
VStack {
HStack {
Text("Select Vendor")
Picker("Provider", selection: $selectedVendor , content: {
ForEach(vendorNames,id: \.self, content: { name in
Text(name)
})
})
.pickerStyle(MenuPickerStyle())
.onTapGesture {
self.getVendorNames() { providers, status in
if (status) {
vendorNames = providers
}
}
}
}
.onChange(of: selectedVendor, perform: { newValue in
selectedVendor = newValue
})
.tint(.orange)
Button {
DetailsView()
} label: {
Label("Details", systemImage: "list.bullet.rectangle")
.foregroundColor(.blue)
}
Spacer()
}
}
.onAppear{
self.getVendorNames() { providers, status in
if (status) {
vendorNames = providers
}
}
}
.navigationTitle("Add Vendor")
.toolbar {
// Back button
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { presentationMode.wrappedValue.dismiss() }, label: {
HStack(spacing: 2) {
Image(systemName: "chevron.backward")
.foregroundColor(.black)
Button("Back", action: {
self.presentationMode.wrappedValue.dismiss()
} )
.foregroundColor(.black)
}
})
}
}
.navigationViewStyle(StackNavigationViewStyle())
.navigationBarBackButtonHidden(true)
}
struct DetailsView: View {
var body: some View {
VStack {
Text("Some Details")
}
}
}
func getVendorNames (completionHandler: @escaping ([String], Bool) -> Void ) {
var names = ["Acme", "Abc"]
completionHandler(names, true)
}
}
I created project with Xcode 14.3. Then I upgraded to 14.3.1, Xcode would not start. I downgraded to 14.3 same issue Xcode would not start. Then downgraded to 14.2 Xcode started. But now I cannot edit the Textfield in any of the views in side the old project. I try to highlight the textfield, it shows a paste icon and allows me to paste whatever is in buffer from previous copy command. But it will not allow me to edit and enter data. In fact none of the Textfields in any of the views are editable.
How to fix this please?
My code below:
struct AddContactView: View {
@Environment(\.managedObjectContext) private var viewContext
@Environment(\.dismiss) var dismiss
@State private var fNameInput: String = ""
@State private var lNameInput: String = ""
@State private var phoneInput: String = ""
@State private var emailInput: String = ""
@State private var screenNameInput: String = ""
@State private var consumerTypeInput: String = ""
@State private var defaultUserRating: String = "*****"
@State private var isShowPhotoLibrary = false
@State private var image = UIImage()
@State private var selectedPhoto: PhotosPickerItem?
@State private var selectedPhotoData: Data?
@Environment(\.presentationMode) var presentationMode
var body: some View {
VStack (alignment: .leading){
Form {
TextField("Full Name", text: $fNameInput)
.textContentType(.name)
.keyboardType(.alphabet)
TextField("Last Name", text: $lNameInput)
.textContentType(.name)
.keyboardType(.alphabet)
TextField("Phone Number", text: $phoneInput)
.textContentType(.telephoneNumber)
.keyboardType(.numberPad)
TextField("Email", text: $emailInput)
.textContentType(.emailAddress)
.keyboardType(.alphabet)
TextField("Consumer Type", text: $consumerTypeInput)
.textContentType(.name)
.textContentType(.name)
.keyboardType(.alphabet)
}
Spacer()
}
.padding()
.navigationTitle("Add Contact")
.toolbar {
ToolbarItem(placement: .navigationBarLeading) {
Button(action: { presentationMode.wrappedValue.dismiss() }, label: {
HStack(spacing: 2) {
Image(systemName: "chevron.backward")
.foregroundColor(.black)
Button("Back", action: {
self.presentationMode.wrappedValue.dismiss()
} )
.foregroundColor(.black)
}
})
}
}
.navigationBarBackButtonHidden(true)
}
}
View: