Hi,I reciently rewrote on of my apps in Swift and the way I did it is I started from scratch creating a brand new project and what I'm trying to do is to upload this new project as a new version of an existing app in the Appstore.Is this possible to do? If yes, what is the process?Thanks
Post
Replies
Boosts
Views
Activity
Now with Dark Mode I have been creating color assets to manage dark mode colors, but sometimes I think of a more semantic name for a certain color after I have used it in multiple places and I was wondering if there is a way to find where a color has been used even if I have to go and manually changed them, I'm not really looking for an automatic solution.Is there a way to rename or find all of the instances where a custom color asset has been used in Xcode?Thanks!
Hi,Can someone please summaries and explain the logic/process for creating a reminders app?I'm no looking for code I just need the list of frameworks and steps needed for creating a reminders app1. You fist create a calendar event (what framework/methods?).2. Than you load the calendar event (what framework/methods?).3. Than you notify the user (what framework/methods?).I know this is a very broad question but I have to start some where.Thanks
With the following code, I can successfully create a reminder event and add an alarm to it that triggers 10 seconds after the event has been created. What I don't like about the way the reminder is created is that it shows in the Apple's Reminders app and when you get the notification message in your device, it shows the Reminders' app icon.Is it possible to make the reminder private so it doesn't show in Apple's Reminders app? If not, what are my options to achieve such of task?import EventKit
class ViewController: UIViewController{
var eventStore = EKEventStore()
override func viewDidLoad(){
super.viewDidLoad()
// get user permission
eventStore.requestAccess(to: EKEntityType.reminder, completion: {(granted, error) in
if !granted{
print("Access denied!")
}
})
}
@IBAction func createReminder(_ sender: Any) {
let reminder = EKReminder(eventStore: self.eventStore)
reminder.title = "Get Milk from the Store"
reminder.calendar = eventStore.defaultCalendarForNewReminders()
let date = Date()
let alarm = EK Alarm(absoluteDate: date.addingTimeInterval(10) as Date)
reminder.addAlarm(alarm)
do {
try eventStore.save(reminder, commit: true)
} catch let error {
print("Error: \(error.localizedDescription)")
}
}
}FYI - To make the above code work you would need to add the NSRemindersUsageDescription key in the info.plist file.RemindersUsageDescription key in the info.plist file.Also, please note the space in class `EK Alarm`, for some reason it would let me add it as one word I had to add a space.
Hi all,I know this is may not be the right forum to post questions about Realm but my issue has to do with the nature of how SwiftUI works.Has anyone been able to successfully integrate Realm with SwiftUI, especially deleting records/rows from a SwiftUI List? I have tried a few different things but no matter what I do I get the same error. After reading some related threads I found out that other people have the same issue but I refuse to think that there is no current solution to integrate Realm with SwiftUI.The following code successfully presents all of the items from Realm in a SwiftUI List, I can create new ones and they show up in the List as expected, my issues is when I try to delete records from the List by either manually pressing a button or by left-swiping to delete the selected row, I get an Index is out of bounds error.Here is my code.Realm Model:class Dog: Object {
@objc dynamic var name = ""
@objc dynamic var age = 0
@objc dynamic var createdAt = NSDate()
@objc dynamic var userID = UUID().uuidString
override static func primaryKey() -> String? {
return "userID"
}
}SwiftUI Code:class BindableResults: ObservableObject where Element: RealmSwift.RealmCollectionValue {
var results: Results
private var token: NotificationToken!
init(results: Results) {
self.results = results
lateInit()
}
func lateInit() {
token = results.observe { [weak self] _ in
self?.objectWillChange.send()
}
}
deinit {
token.invalidate()
}
}
struct DogRow: View {
var dog = Dog()
var body: some View {
HStack {
Text(dog.name)
Text("\(dog.age)")
}
}
}
struct ContentView : View {
@ObservedObject var dogs = BindableResults(results: try! Realm().objects(Dog.self))
var body: some View {
VStack{
List{
ForEach(dogs.results, id: \.name) { dog in
DogRow(dog: dog)
}.onDelete(perform: deleteRow )
}
Button(action: {
try! realm.write {
realm.delete(self.dogs.results[0])
}
}){
Text("Delete User")
}
}
}
private func deleteRow(with indexSet: IndexSet){
indexSet.forEach ({ index in
try! realm.write {
realm.delete(self.dogs.results[index])
}
})
}
}ERRORTerminating app due to uncaught exception ‘RLMException’, reason: ‘Index 23 is out of bounds (must be less than 23).’Of course, the 23 changes depending on how many items are in the Realm database, in this case, I had 24 records when I swiped and tapped the delete button.
I'm trying to share a record with other users in CloudKit but I keep getting an error. When I tap one of the items/records on the table I'm presented with the UICloudSharingController and I can see the iMessage app icon, but when I tap on it I get an error and the UICloudSharingController disappears, the funny thing is that even after the error I can still continue using the app.Here is what I have.Code var items = [CKRecord]()
var itemName: String?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = items[indexPath.row]
let share = CKShare(rootRecord: item)
if let itemName = item.object(forKey: "name") as? String {
self.itemName = item.object(forKey: "name") as? String
share[CKShareTitleKey] = "Sharing \(itemName)" as CKRecordValue?
} else {
share[CKShareTitleKey] = "" as CKRecordValue?
self.itemName = "item"
}
share[CKShareTypeKey] = "bundle.Identifier.Here" as CKRecordValue
prepareToShare(share: share, record: item)
}
private func prepareToShare(share: CKShare, record: CKRecord){
let sharingViewController = UICloudSharingController(preparationHandler: {(UICloudSharingController, handler: @escaping (CKShare?, CKContainer?, Error?) -> Void) in
let modRecordsList = CKModifyRecordsOperation(recordsToSave: [record, share], recordIDsToDelete: nil)
modRecordsList.modifyRecordsCompletionBlock = {
(record, recordID, error) in
handler(share, CKContainer.default(), error)
}
CKContainer.default().privateCloudDatabase.add(modRecordsList)
})
sharingViewController.delegate = self
sharingViewController.availablePermissions = [.allowPrivate]
self.navigationController?.present(sharingViewController, animated:true, completion:nil)
}
// Delegate Methods:
func cloudSharingControllerDidSaveShare(_ csc: UICloudSharingController) {
print("saved successfully")
}
func cloudSharingController(_ csc: UICloudSharingController, failedToSaveShareWithError error: Error) {
print("failed to save: \(error.localizedDescription)")
}
func itemThumbnailData(for csc: UICloudSharingController) -> Data? {
return nil //You can set a hero image in your share sheet. Nil uses the default.
}
func itemTitle(for csc: UICloudSharingController) -> String? {
return self.itemName
}ERRORFailed to modify some records Here is what I see...https://i.stack.imgur.com/0SLlK.pngAny idea what could be wrong?
I have an app where I can create and share records with other users. When I share a record and the user accepts it, I can display the shared object right after the `userDidAcceptCloudKitShareWith` gets called and using the `CKFetchRecordsOperation` class to fetch the object, no issues here. My problem is trying to read the shared records directly from the `Shared Database` after the user has accepted the record, closed the app, and reopened the app again.The following code successfully reads all of the records from the `Private Database` located in a zone called `ListsZone`. @IBAction func sharedRecords(_ sender: Any) {
let privateDatabase = CKContainer.init(identifier: "iCloud.com.mySite.lists").database(with: .private)
let predicate = NSPredicate(value: true)
let query = CKQuery(recordType: "Items", predicate: predicate)
let ckRecordZoneID = CKRecordZone(zoneName: "ListsZone")
let ckRecordID = CKRecord.ID(zoneID: ckRecordZoneID.zoneID)
privateDatabase.perform(query, inZoneWith:ckRecordID.zoneID){( results , error) in
guard error == nil else{
print("Error \(String(describing: error?.localizedDescription))")
return
}
if let itemsFromResults = results{
print("Items: \(itemsFromResults)")
}
}
}What I'm expecting is to be able to read the shared records from the `Shared Database` with the same code above except modifying the line below, but it's not working.let privateDatabase = CKContainer.init(identifier: "iCloud.com.mySite.lists").database(with: .shared)I get the following error."Only shared zones can be accessed in the shared DB"What am I missing?What is the proper way to read records from the `Shared Database`?I was under the impression that users who already accepted a shared record from a user and the records are saved in the `Shared Database` the user could access the records by requiring the `Shared Database` directly as shown in my code above.FYI - I know there are shared records in the shared database because I can see them in the CloudKit dashboard.
I have an app where I can share records with other users, everything works when I share a single record, my issue is when I share a record (parent record) which has children records referencing it, I can see the parent record in the Shared Database in the CloudKit Dashboard after the user accepts the share but I don't see any of the related child records.Based on the WWDC videos and some other threads I read, the child records are automatically shared when you share the parent record, but it's not what I'm seeing, again, I can see the parent record in the Shared Database but no child records.Here is an overview of how the app is set up in the CloudKit Dashboard.In the CloudKit Dashboard, I have a `Lists` and an `Items` record type, where the `Lists` record is the parent of one or many `Items`. In the `Items` schema, I have a `Reference` field type which keeps a reference to its parent list.### Here is the code I'm using to save the parent record. func shareList(){
let share = CKShare(rootRecord: self.list)
if let listName = self.list.object(forKey: "name") as? String {
self.listName = self.list.object(forKey: "name") as? String
share[CKShare.SystemFieldKey.title] = "Sharing \(listName)" as CKRecordValue?
} else {
share[CKShare.SystemFieldKey.title] = "" as CKRecordValue?
}
share[CKShare.SystemFieldKey.shareType] = "com.mySite.lists" as CKRecordValue
let sharingViewController = UICloudSharingController(preparationHandler: {(UICloudSharingController, handler: @escaping (CKShare?, CKContainer?, Error?) -> Void) in
let modRecordsList = CKModifyRecordsOperation(recordsToSave: [self.list, share], recordIDsToDelete: nil)
modRecordsList.modifyRecordsCompletionBlock = {
(record, recordID, error) in
handler(share, CKContainer.default(), error)
}
CKContainer.default().privateCloudDatabase.add(modRecordsList)
})
sharingViewController.delegate = self
sharingViewController.availablePermissions = [.allowPrivate]
self.navigationController?.present(sharingViewController, animated:true, completion:nil)
}What I'm I missing? Is there any additional set up I need to do when sharing the parent record?I'm right saying that the child records should automatically be shared alone with the parent record?Here is a picture that demonstrates the relationship between the items and the list is working in the `Private Database`.https://i.stack.imgur.com/u7J3h.png
I have been playing around with CloudKit and I was under the impression that the user needed to be logged-in into iCloud in order to use CloudKit, but I don't think it's true.
I'm testing an app that successfully communicates with the private database in CloudKit, I can read and write records to it. To my surprise I logged-off from my iCloud account and from the Sandbox Account and I can still read and write records from CloudKit which was unexpected, I was thinking that after logging off I wouldn't be able to communicate with CloudKit, in fact, I deleted the app from my phone, recompiled in Xcode and the app can still communicate with CloudKit.
Is this normal behavior, does CloudKit works without the user being logged into iCloud?
Thanks
Can someone please clarify the expectations for an app that offers sync technologies. My understanding is that you can use an app in your main phone, enter some data and that data should to show in any device that the user owns, simple enough.
What I don't quite understand is if it is possible to login to a second device which was setup with a different account and expect the data you entered in you first device to show up.
In other words let's say I have an app installed in device1 and I have been entering data and than for some reason I barrow device2 from someone else, then login to iCloud with my own account, then I download the app I was using in device1, should I expect the data from device1 to show in device2?
I recently tried to submit an update to an app that I have been constantly updating; the last update was done two months ago using Xcode 11 and I had no issues back then. This time when I Distributed the App using Xcode 12, everything went smoothly without any errors but after a few minutes, I got the following email from Apple.
Dear Developer, We identified one or more issues with a recent delivery for your app, “My App” 6.2 (6.2). Please correct the following issues, then upload again. ITMS-90561: Invalid Swift Support - The watchOS application has Swift libraries at both /Payload/My App.app/My App Watch App.app/My App Watch App Extension.appex/Frameworks/ and /Payload/My App.app/My App Watch App.app/Frameworks/. Remove all of the Swift libraries from one of the locations and resubmit your app. Best regards,
The App Store Team
Any idea what should I be removing?
Can someone please explain why the first time I tap on an item from the list, the selectedItem?.name becomes nil? The second time it shows the right item name correctly but not the first time, why?. I was expecting that to have a value even the first time since I'm setting it in the onTapGesture method selectedItem = item.
// model
struct Item: Identifiable{
var id = UUID()
var name:String
}
// SwiftUI
struct UpdateStateProperty: View {
var items:[Item] = [Item(name: "Oranges"),
Item(name: "Apples"),
Item(name: "Cookies") ]
@State private var presentView = false
@State private var selectedItem: Item?
var body: some View {
List{
ForEach(items){ item in
HStack{
Text(item.name)
}.onTapGesture {
selectedItem = item
presentView.toggle()
}
}
}
.sheet(isPresented: $presentView){
Text("\(selectedItem?.name)" as String)
}
}
}
I have a SwiftUI app where I would like to enable NSPersistentCloudKitContainer to start using CloudKit and be able to sync the content of the app between multiple devices, but I'm not sure how to handle the user experience. Should this be a feature that the user turns On and Off in the app settings screen or does the user expects the syncing mechanism to work by default without having to do anything, can someone please share your experience on how you implemented CloudKit/Sync in your app.
Do I need to offer a login mechanism so the user logs in?
Should I include an On/Off option so the user decides if they want the sync option or not?
In general, can someone be so kind and explain what the user experience should be when an app provides ClouldKit/sync?
FYI - I'm not asking how to implement CloudKit sync I already know what it is and how it works. I just need to know what the expedition is from an app the provides that feature.
Thanks!
I'm trying to give the user the ability to decide whether they want to sync to CloudKit or not by turning On or Off a Switch located somewhere in the app settings screen but I'm not sure how to do it in SwiftUI.
The following code successfully stops the sync to CloudKit by setting the cloud kit container options to nil description.cloudKitContainerOptions = nil.
class CoreDataManager{
static let instance = CoreDataManager()
let container: NSPersistentCloudKitContainer
let context: NSManagedObjectContext
init(){
container = NSPersistentCloudKitContainer(name: "CoreDataContainer")
guard let description = container.persistentStoreDescriptions.first else{
fatalError("###\(#function): Failed to retrieve a persistent store description.")
}
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
description.cloudKitContainerOptions = nil
container.loadPersistentStores { (description, error) in
if let error = error{
print("Error loading Core Data. \(error)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
context = container.viewContext
}
func save(){
do{
try context.save()
print("Saved successfully!")
}catch let error{
print("Error saving Core Data. \(error.localizedDescription)")
}
}
}
What I ultimately want is to be able to control the syncing process with an @AppStore property or some sort of property, something like this...
class CoreDataManager{
@AppStorage("iCloudSync") private var iCloudSync = false
//missing code...
init(){
if !iCloudSync{
description.cloudKitContainerOptions = nil
}
}
//missing code...
}
But I'm facing a couple of issues, one, I'm getting an error when using the iCloudSync wrapper variable and the second one and the most difficult for me to solve is
the fact that I need to make the persistent storage reload when the switch changes from On to Off of vise-versa.
Any idea how can I structure my code so I can control the syncing process and be able to reload the persistent storage when the switch changes?
By the way and just for reference, here is how I'm using the CoreDataManager class in my view model.
class CarViewModel: ObservableObject{
let manager = CoreDataManager.instance
@Published var cars: [Car] = []
init(){
getCars()
}
func addCar(){}
func getCars(){}
func deleteCar(){}
func save(){
self.manager.save()
}
}
How can I reload the NSPersistentCloudKitContainer from a SwiftUI View?
I have a SwiftUI + MVVM + CloudKit app that successfully syncs to CloudKit but what I would like to be able to do is reload the NSPersistentCloudKitContainer from some View in the app to be able to evaluate if the app should sync to CloudKit or not by setting the cloudKitContainerOptions to nil (description.cloudKitContainerOptions = nil) if the user doesn't want to sync.
In other words, I need to reload the code inside the init() method in the CoreDataManager file when a method in the View Model is called. See the code and comments below.
Here is the code...
Core Data Manager
class CoreDataManager{
static let instance = CoreDataManager()
let container: NSPersistentCloudKitContainer
let context: NSManagedObjectContext
init(){
container = NSPersistentCloudKitContainer(name: "CoreDataContainer")
guard let description = container.persistentStoreDescriptions.first else{
fatalError("###\(#function): Failed to retrieve a persistent store description.")
}
description.setOption(true as NSNumber, forKey: NSPersistentHistoryTrackingKey)
description.setOption(true as NSNumber, forKey: NSPersistentStoreRemoteChangeNotificationPostOptionKey)
/// This is the code that I would like to control from other view in the app
/// if iCloudSync is off, do nothing otherwise set it to nil
if !iCloudSync{
description.cloudKitContainerOptions = nil
}
container.loadPersistentStores { (description, error) in
if let error = error{
print("Error loading Core Data. \(error)")
}
}
container.viewContext.automaticallyMergesChangesFromParent = true
context = container.viewContext
}
func save(){
do{
try context.save()
print("Saved successfully!")
}catch let error{
print("Error saving Core Data. \(error.localizedDescription)")
}
}
}
View Model
Somehow I would like to be able to have a way to control the reload process in the View Model.
class CarViewModel: ObservableObject{
let manager = CoreDataManager.instance
@Published var cars: [Car] = []
init(){
getCars()
}
func addCar(){}
func getCars(){}
func deleteCar(){}
func save(){
self.manager.save()
}
}
SwiftUI View
Then from a view, I would like to control the reload process through the View Model by calling a method.
struct ContentView: View {
@State private var isSync = false
@StateObject var viewModel = CarViewModel()
var body: some View {
VStack {
Toggle("iCloud Sync", isOn: $isSync)
.toggleStyle(SwitchToggleStyle(tint: .red))
if isSync {
// RELOAD the container, something like this
viewModel.reloadContainer(withSync: true)
}
}
}
}
Any help would be appreciated.
Thanks