I’m doing an basic App for create notes and subnotes in iPhone and show them in Watch. I did the both CRUD but I can’t view the data in Watch. I’m using userDefaults because It’s so simple app.
I tried add NSObject and WCSessionDelegate to my NoteViewModel but doesn’t work. When I start the app, I get ‘WCSessionActivationState(rawValue: 2)’.
Here is my NoteViewModel.swift:
<code>import Combine
import Foundation
import WatchConnectivity
class NoteViewModel: NSObject, WCSessionDelegate, ObservableObject {
@Published var notes: [Note] = []
func addNote(title: String) {
let newNote = Note(title: title, subNotes: [])
notes.append(newNote)
saveNotes()
}
func addSubNote(to note: Note, title: String, content: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
let newSubNote = SubNote(title: title, content: content)
notes[index].subNotes.append(newSubNote)
saveNotes()
}
}
func removeNote(note: Note) {
notes.removeAll { $0.id == note.id }
saveNotes()
}
func removeSubNote(from note: Note, subNote: SubNote) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].subNotes.removeAll { $0.id == subNote.id }
saveNotes()
}
}
func updateNote(note: Note, newTitle: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].title = newTitle
saveNotes()
}
}
override init() {
super.init()
if WCSession.isSupported() {
WCSession.default.delegate = self
WCSession.default.activate()
self.notes = loadNotes()
}
}
func session(
_ session: WCSession,
activationDidCompleteWith activationState: WCSessionActivationState,
error: Error?
) {
if let error = error {
print("Error al activar la sesión: (error.localizedDescription)")
} else {
print("Sesión activada con estado: (activationState)")
}
}
#if os(iOS)
func sessionDidBecomeInactive(_ session: WCSession) { }
func sessionDidDeactivate(_ session: WCSession) {
session.activate()
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
if let notesArray = message["notes"] as? [[String: Any]] {
let decoder = JSONDecoder()
if let data = try? JSONSerialization.data(withJSONObject: notesArray, options: []),
let notes = try? decoder.decode([Note].self, from: data) {
self.notes = notes
saveNotes()
}
}
}
#endif
private func saveNotes() {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(notes) {
if let defaults = UserDefaults(suiteName: "group.lucasleone.WatchNotesApp") {
defaults.set(encoded, forKey: "notes")
}
sendNotesToWatch(notes: notes)
}
}
private func loadNotes() -> [Note] {
if let defaults = UserDefaults(suiteName: "group.lucasleone.WatchNotesApp"),
let savedNotes = defaults.data(forKey: "notes") {
let decoder = JSONDecoder()
if let loadedNotes = try? decoder.decode([Note].self, from: savedNotes) {
return loadedNotes
}
}
return []
}
private func sendNotesToWatch(notes: [Note]) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(notes) {
let notesDict = try? JSONSerialization.jsonObject(with: encoded, options: []) as? [[String: Any]]
if WCSession.default.isReachable {
WCSession.default.sendMessage(["notes": notesDict ?? []], replyHandler: nil, errorHandler: { error in
print("Error enviando mensaje: (error.localizedDescription)")
})
}
}
}
}
</code>
<code>import Combine
import Foundation
import WatchConnectivity
class NoteViewModel: NSObject, WCSessionDelegate, ObservableObject {
@Published var notes: [Note] = []
func addNote(title: String) {
let newNote = Note(title: title, subNotes: [])
notes.append(newNote)
saveNotes()
}
func addSubNote(to note: Note, title: String, content: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
let newSubNote = SubNote(title: title, content: content)
notes[index].subNotes.append(newSubNote)
saveNotes()
}
}
func removeNote(note: Note) {
notes.removeAll { $0.id == note.id }
saveNotes()
}
func removeSubNote(from note: Note, subNote: SubNote) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].subNotes.removeAll { $0.id == subNote.id }
saveNotes()
}
}
func updateNote(note: Note, newTitle: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].title = newTitle
saveNotes()
}
}
override init() {
super.init()
if WCSession.isSupported() {
WCSession.default.delegate = self
WCSession.default.activate()
self.notes = loadNotes()
}
}
func session(
_ session: WCSession,
activationDidCompleteWith activationState: WCSessionActivationState,
error: Error?
) {
if let error = error {
print("Error al activar la sesión: (error.localizedDescription)")
} else {
print("Sesión activada con estado: (activationState)")
}
}
#if os(iOS)
func sessionDidBecomeInactive(_ session: WCSession) { }
func sessionDidDeactivate(_ session: WCSession) {
session.activate()
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
if let notesArray = message["notes"] as? [[String: Any]] {
let decoder = JSONDecoder()
if let data = try? JSONSerialization.data(withJSONObject: notesArray, options: []),
let notes = try? decoder.decode([Note].self, from: data) {
self.notes = notes
saveNotes()
}
}
}
#endif
private func saveNotes() {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(notes) {
if let defaults = UserDefaults(suiteName: "group.lucasleone.WatchNotesApp") {
defaults.set(encoded, forKey: "notes")
}
sendNotesToWatch(notes: notes)
}
}
private func loadNotes() -> [Note] {
if let defaults = UserDefaults(suiteName: "group.lucasleone.WatchNotesApp"),
let savedNotes = defaults.data(forKey: "notes") {
let decoder = JSONDecoder()
if let loadedNotes = try? decoder.decode([Note].self, from: savedNotes) {
return loadedNotes
}
}
return []
}
private func sendNotesToWatch(notes: [Note]) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(notes) {
let notesDict = try? JSONSerialization.jsonObject(with: encoded, options: []) as? [[String: Any]]
if WCSession.default.isReachable {
WCSession.default.sendMessage(["notes": notesDict ?? []], replyHandler: nil, errorHandler: { error in
print("Error enviando mensaje: (error.localizedDescription)")
})
}
}
}
}
</code>
import Combine
import Foundation
import WatchConnectivity
class NoteViewModel: NSObject, WCSessionDelegate, ObservableObject {
@Published var notes: [Note] = []
func addNote(title: String) {
let newNote = Note(title: title, subNotes: [])
notes.append(newNote)
saveNotes()
}
func addSubNote(to note: Note, title: String, content: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
let newSubNote = SubNote(title: title, content: content)
notes[index].subNotes.append(newSubNote)
saveNotes()
}
}
func removeNote(note: Note) {
notes.removeAll { $0.id == note.id }
saveNotes()
}
func removeSubNote(from note: Note, subNote: SubNote) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].subNotes.removeAll { $0.id == subNote.id }
saveNotes()
}
}
func updateNote(note: Note, newTitle: String) {
if let index = notes.firstIndex(where: { $0.id == note.id }) {
notes[index].title = newTitle
saveNotes()
}
}
override init() {
super.init()
if WCSession.isSupported() {
WCSession.default.delegate = self
WCSession.default.activate()
self.notes = loadNotes()
}
}
func session(
_ session: WCSession,
activationDidCompleteWith activationState: WCSessionActivationState,
error: Error?
) {
if let error = error {
print("Error al activar la sesión: (error.localizedDescription)")
} else {
print("Sesión activada con estado: (activationState)")
}
}
#if os(iOS)
func sessionDidBecomeInactive(_ session: WCSession) { }
func sessionDidDeactivate(_ session: WCSession) {
session.activate()
}
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
if let notesArray = message["notes"] as? [[String: Any]] {
let decoder = JSONDecoder()
if let data = try? JSONSerialization.data(withJSONObject: notesArray, options: []),
let notes = try? decoder.decode([Note].self, from: data) {
self.notes = notes
saveNotes()
}
}
}
#endif
private func saveNotes() {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(notes) {
if let defaults = UserDefaults(suiteName: "group.lucasleone.WatchNotesApp") {
defaults.set(encoded, forKey: "notes")
}
sendNotesToWatch(notes: notes)
}
}
private func loadNotes() -> [Note] {
if let defaults = UserDefaults(suiteName: "group.lucasleone.WatchNotesApp"),
let savedNotes = defaults.data(forKey: "notes") {
let decoder = JSONDecoder()
if let loadedNotes = try? decoder.decode([Note].self, from: savedNotes) {
return loadedNotes
}
}
return []
}
private func sendNotesToWatch(notes: [Note]) {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(notes) {
let notesDict = try? JSONSerialization.jsonObject(with: encoded, options: []) as? [[String: Any]]
if WCSession.default.isReachable {
WCSession.default.sendMessage(["notes": notesDict ?? []], replyHandler: nil, errorHandler: { error in
print("Error enviando mensaje: (error.localizedDescription)")
})
}
}
}
}
And in the watch, I tried this:
<code>struct HomeView: View {
@StateObject var viewModel = NoteViewModel()
var body: some View {
NavigationView {
List {
ForEach(viewModel.notes) { note in
NavigationLink(
destination: NoteDetailView(
note: note, viewModel: viewModel)
) {
Text(note.title)
}
}
}
.navigationTitle("Notas")
}
}
}
</code>
<code>struct HomeView: View {
@StateObject var viewModel = NoteViewModel()
var body: some View {
NavigationView {
List {
ForEach(viewModel.notes) { note in
NavigationLink(
destination: NoteDetailView(
note: note, viewModel: viewModel)
) {
Text(note.title)
}
}
}
.navigationTitle("Notas")
}
}
}
</code>
struct HomeView: View {
@StateObject var viewModel = NoteViewModel()
var body: some View {
NavigationView {
List {
ForEach(viewModel.notes) { note in
NavigationLink(
destination: NoteDetailView(
note: note, viewModel: viewModel)
) {
Text(note.title)
}
}
}
.navigationTitle("Notas")
}
}
}