I'm developing an app, and I need save data, so im using Core Data, and unfortunately in not a Core Data expert
When I run the app for the first time, it works and saves the data (I checked the *.sqlit file), but if re-run the app give me this erros
2020-09-12 02:52:02.539123+0100 photoUniq_ios_v3[6106:338281] -[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0
2020-09-12 02:52:02.539730+0100 photoUniq_ios_v3[6106:338281] [error] fault: exception raised during multi-threaded fetch -[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0 ((null))
CoreData: fault: exception raised during multi-threaded fetch -[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0 ((null))
2020-09-12 02:52:02.539958+0100 photoUniq_ios_v3[6106:338281] [error] CoreData: exception raised during multi-threaded fetch -[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0 ((null))
2020-09-12 02:52:02.540290+0100 photoUniq_ios_v3[6106:338281] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000174c2a0> , -[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0 with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLFetchRequestContext: 0x60000174c2a0> , -[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0 with userInfo of (null)
2020-09-12 02:52:02.589331+0100 photoUniq_ios_v3[6106:338281] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x600000a562e0'
...
libc++abi.dylib: terminating with uncaught exception of type NSException
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[photoUniq_ios_v3.PUWorkspace initWithCoder:]: unrecognized selector sent to instance 0x60000344d3e0'
terminating with uncaught exception of type NSException
I have an environment object
SceneDelegate.swift
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView
.environmentObject(PU(ctx: context))
.environmentObject(PartialSheetManager())
)
PU.swift
class PU: NSManagedObject{
let id = UUID()
var defaultWorkspace:PUWorkspace{
self.cd_xWorkspaces!.first!
}
init(ctx:NSManagedObjectContext?) {
super.init(entity: PUPhotouniq.entity(), insertInto: ctx)
self.cd_xGallary = PUGallary(ctx: self.managedObjectContext)
self.cd_xWorkspaces = Array()
self.cd_xWorkspaces!.add(PUWorkspace(ctx: self.managedObjectContext))
}
}
PUWorkpace.swift
import Foundation
import SwiftUI
import CoreData
class PUWorkspace:NSManagedObject {
let id = UUID()
#NSManaged var cd_nome:String?
#NSManaged var cd_porcessedxFoldres:[PUFolder]?
#NSManaged var cd_xFoldres:[PUFolder]?
#NSManaged var cd_originalxFoldres:[PUFolder]?
#Published var cd_cover:UIImage = UIImage() //Init
var defaultFolder:PUFolder{
cd_xFoldres!.first ?? PUFolder(ctx: self.managedObjectContext)
}
init(ctx:NSManagedObjectContext?) {
super.init(entity: Self.entity(), insertInto: ctx)
self.cd_cover = UIImage.defaultImage
self.cd_nome = String.defaultName
self.cd_xFoldres = []
self.cd_xFoldres!.add(PUFolder(ctx: self.managedObjectContext))
self.cd_originalxFoldres = []
self.cd_porcessedxFoldres = []
}
}
and a few functions
to fetch the data
#FetchRequest(entity: PU.entity(), sortDescriptors: []) var photoUniq2:FetchedResults<PU >
what can cause the error and how I can solve it?
Related
I have the following taskGroup, using the async/await concurrency in Swift 5.5, where I iterate over meters, fetching onboardingMeter from Core Data. This works ok in around 4 out of 5 times, but then crashes the iOS app. I am testing this with deleting the app from the iOS device, and run the onboarding from the start. Sometimes I can run this with no problems 4 or 5 or 6 times in a row, then it suddenly crashes with the following error:
2021-09-05 09:11:01.095537+0200 Curro[12328:1169419] [error] error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null)
CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[__NSCFSet addObject:]: attempt to insert nil with userInfo (null)
2021-09-05 09:11:01.095954+0200 Curro[12328:1169419] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFSet addObject:]: attempt to insert nil'
*** First throw call stack:
(0x1857b105c 0x19dc63f64 0x1858ba538 0x1858c5df8 0x1857c68bc 0x18ce313d8 0x18cd13314 0x18cd140cc 0x105616700 0x105626a90 0x185769ce4 0x185723ebc 0x1857373c8 0x1a0edd38c 0x1880dae9c 0x187e58864 0x18d36da2c 0x18d29ab70 0x18d27bf2c 0x1048bba04 0x1048bbab0 0x10551da24)
libc++abi: terminating with uncaught exception of type NSException
This is the code where it fails, the let onboardingMeter = await OnboardingMeter.fromMeterDict is never returned, I don't see the second print statement when it fails.
Is this an error in the Swift beta, or have I made any mistake here? I will try again when a new iOS 15 beta arrives, and when the official release of iOS 15 comes out.
await withTaskGroup(of: OnboardingMeter.self) { group in
for (number, codableAddress) in meters {
group.addTask {
print("The following statement sometimes fails to return an onboarding meter, resulting in a crash")
let onboardingMeter = await OnboardingMeter.fromMeterDict(number, address: codableAddress, in: moc)
print("onboardingMeter:", onboardingMeter)
return onboardingMeter
}
}
for await meter in group {
onboardingMeters.append(meter)
}
}
The OnboardingMeter.fromMeterDict function:
extension OnboardingMeter {
static func fromMeterDict(_ number: String, address: CodableAddress, in moc: NSManagedObjectContext) async -> OnboardingMeter {
let me: OnboardingMeter = await moc.findOrCreateInstance(of: self, predicate: NSPredicate(format: "number == \(number)"))
let address = await Address.createOrUpdate(from: address, in: moc)
await moc.perform {
me.address = address
me.number = number
}
return me
}
}
and findOrCreateInstance:
func findOrCreateInstance<T: NSManagedObject>(of type: T.Type, predicate: NSPredicate?) async -> T {
if let found = await self.findFirstInstance(of: type, predicate: predicate) {
return found
} else {
return T(context: self)
}
}
Although I'd need to see more code to confirm this, I believe that you're returning a managed object that is already registered to a managed object context. It is only valid to refer to such registered objects within the closure of a perform call. If you need to refer to a managed object between different execution contexts, either make use of the object ID and refetch as needed, or make use of the dictionary representation option of the fetch request:
let request: NSFetchRequest = ...
request.resultType = NSManagedObjectIDResultType // or NSDictionaryResultType
return request.execute()
I'd strongly encourage you to watch this video from WWDC. At the minute 10:39 they're talking exactly about this.
I am trying to save the data to CoreData using the saveSelectedQuestion function inside the CoreDataManager class, but I am getting the error found in the console output. I have given a custom model to the questions property as seen in the CoreData Entity. How can I save data to CoreData using a custom model. Can I use Dictionary while saving data in CoreData? [QuestionSections.RawValue : String]
You can review the model I added to the CoreData Entity below.
I can't save data to CoreData. Why ?
You can check this project on github link. It's a pretty simple one-page project. I just can't save data.
GitLab Project : Core Data Test Project
Console Output:
2021-08-21 20:59:52.440497+0300 CoreDataTest[34727:2823184] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-21 20:59:52.440702+0300 CoreDataTest[34727:2823184] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281574900
2021-08-21 20:59:52.440945+0300 CoreDataTest[34727:2823184] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-21 20:59:52.441055+0300 CoreDataTest[34727:2823184] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e5c0c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e5c0c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
2021-08-21 20:59:52.441137+0300 CoreDataTest[34727:2823184] [error] error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
2021-08-21 20:59:52.441352+0300 CoreDataTest[34727:2823184] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-21 20:59:52.441465+0300 CoreDataTest[34727:2823184] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281574900
2021-08-21 20:59:52.441648+0300 CoreDataTest[34727:2823184] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-21 20:59:52.441731+0300 CoreDataTest[34727:2823184] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e5c0c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e5c0c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
2021-08-21 20:59:52.441799+0300 CoreDataTest[34727:2823184] [error] error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
2021-08-21 20:59:52.441982+0300 CoreDataTest[34727:2823184] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-21 20:59:52.442071+0300 CoreDataTest[34727:2823184] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281574900
2021-08-21 20:59:52.442269+0300 CoreDataTest[34727:2823184] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-21 20:59:52.442373+0300 CoreDataTest[34727:2823184] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e5c0c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e5c0c0> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
2021-08-21 20:59:52.442451+0300 CoreDataTest[34727:2823184] [error] error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
CoreData: error: -executeRequest: encountered exception = <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo = (null)
2021-08-21 20:59:52.453864+0300 CoreDataTest[34727:2823184] [general] 'NSKeyedUnarchiveFromData' should not be used to for un-archiving and will be removed in a future release
2021-08-21 20:59:52.454083+0300 CoreDataTest[34727:2823184] -[CoreDataTest.QuestionList encodeWithCoder:]: unrecognized selector sent to instance 0x281574900
2021-08-21 20:59:52.454309+0300 CoreDataTest[34727:2823184] *** -[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
2021-08-21 20:59:52.454399+0300 CoreDataTest[34727:2823184] [error] error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e58000> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
CoreData: error: SQLCore dispatchRequest: exception handling request: <NSSQLSaveChangesRequestContext: 0x280e58000> , <shared NSKeyedUnarchiveFromData transformer> threw while encoding a value. with userInfo of (null)
Failed to save selected category: A Core Data error occurred.
Core Data Entity:
Core Data Manager:
class CoreDataManager {
static var shared = CoreDataManager()
let persistentContainer: NSPersistentContainer
init() {
persistentContainer = NSPersistentContainer(name: "QuestionsCoreData")
persistentContainer.loadPersistentStores { description, error in
if let error = error {
fatalError("Core Data Stre failed: \(error.localizedDescription)")
}
}
}
func searchInCategory(id: String) -> [QuestionCD] {
let fetchRequest: NSFetchRequest<QuestionCD> = QuestionCD.fetchRequest()
let search = NSPredicate(format: "ANY id == %#", id)
print("search: \(search)")
fetchRequest.predicate = search
do {
return try persistentContainer.viewContext.fetch(fetchRequest)
} catch {
print("no Data \n")
return []
}
}
func saveSelectedQuestion(questionTitle: String, id: String, questions: [QuestionList]) {
let questionsCD = QuestionCD(context: persistentContainer.viewContext)
questionsCD.title = questionTitle
questionsCD.id = id
questionsCD.questions = questions
do {
try persistentContainer.viewContext.save()
} catch {
print("Failed to save selected category: \(error.localizedDescription)")
}
}
func getSelectedQuestion(questionID: String) -> QuestionCD {
let fetchRequest: NSFetchRequest<QuestionCD> = QuestionCD.fetchRequest()
let search = NSPredicate(format: "id == %#", questionID)
print("search: \(search)")
fetchRequest.predicate = search
print("request predicate: \(String(describing: fetchRequest.predicate))")
do {
return try persistentContainer.viewContext.fetch(fetchRequest).first ?? QuestionCD()
} catch {
return QuestionCD()
}
}
}
My Model:
class QuestionContainer: NSObject, Codable {
var questionCategories: [Question]
init(questionCategories: [Question]) {
self.questionCategories = questionCategories
}
}
public class Question: NSObject, Codable {
var title: String
var id: String
var questions: [QuestionList]
init(title: String, id: String, questions: [QuestionList]) {
self.title = title
self.id = id
self.questions = questions
}
}
public class QuestionList: NSObject, Codable {
init(id: String, question: String, isQuestionImage: Bool, isSectionImage: Bool, imageURL: String, imageData: Data? = nil, sections: [QuestionSections.RawValue : String], selected: String, correct: String) {
self.id = id
self.question = question
self.isQuestionImage = isQuestionImage
self.isSectionImage = isSectionImage
self.imageURL = imageURL
self.imageData = imageData
self.sections = sections
self.selected = selected
self.correct = correct
}
var id: String
var question: String
var isQuestionImage, isSectionImage: Bool
var imageURL: String
var imageData: Data?
var sections: [QuestionSections.RawValue : String]
var selected: String
var correct: String
}
enum QuestionSections: String, Codable, Hashable {
case A = "A"
case B = "B"
case C = "C"
case D = "D"
}
I'm creating PDF files on my app, And having a memory issue when merging PDF pages together. After running Instrument Allocations I can see that all the undisposed data is at: private func addPageToMainPdf(left: Bool) -> Bool. The instrument points to the PDFDocument creation within the function, but I can't tell why its not disposed of.
Function using most memory:
private func addPageToMainPdf(left: Bool) -> Bool //MEMORY LEAK
{
if left
{
if let firstPDFDocument = PDFDocument(url: exportPath().url)
{
let pages = firstPDFDocument.pageCount
if let secondPDFDocument = PDFDocument(url: exportPathLeft().url)
{
if let page = secondPDFDocument.page(at: 0)
{
firstPDFDocument.insert(page, at: pages)
firstPDFDocument.write(to: exportPath().url) // Uses gigabytes of exponential memory until app crashes, release pool fixes the problem but function takes at least 4 times as long now.
return true
}
}
}
}//cropped out rest of the code for right pages for other files
}
//Supporting Code:
func exportPath() -> (url: URL, string: String, fileName: String)
{
let fileName = "MasterFile.pdf"
let Manager = FileManager.default
let fileURL = try! Manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent(fileName)
return (fileURL, fileURL.path, fileName)
}
private func exportPathLeft() -> (url: URL, string: String, fileName: String)
{
let fileName = "tempLeft.pdf"
let Manager = FileManager.default
let fileURL = try! Manager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true).appendingPathComponent(fileName)
return (fileURL, fileURL.path, fileName)
}
iOSAppName(22955,0x16e277000) malloc: can't allocate region
:*** mach_vm_map(size=262144, flags: 100) failed (error code=3)
iOSAppName(22955,0x16e277000) malloc: *** set a breakpoint in malloc_error_break to debug
iOSAppName(22955,0x16e277000) malloc: can't allocate region
:*** mach_vm_map(size=262144, flags: 100) failed (error code=3)
iOSAppName(22955,0x16e277000) malloc: *** set a breakpoint in malloc_error_break to debug
2021-02-26 21:45:15.540187+0000 iOSAppName[22955:11122435] *** Terminating app due to uncaught exception 'NSMallocException', reason: 'Failed to grow buffer'
*** First throw call stack:
(0x1ac64c878 0x1c0ba2c50 0x1ac6c2518 0x1ac6b977c 0x1ac561088 0x1ac586e68 0x1ac586c70 0x1adfd35b0 0x1ae1b75fc 0x1adeddf84 0x1adf163dc 0x1adf161a8 0x1ae1b26c8 0x1ae094b7c 0x1ae0948a8 0x1adfddc78 0x1ae1f8b64 0x1ae1f9164 0x1ade9f434 0x1ade9fc78 0x1df4c1114 0x1df4c0eac 0x1df4abb5c 0x1df4b0d84 0x102634d24 0x102655848 0x10260d998 0x102403814 0x1022ebda8 0x10219eiOSAppName(22955,0x16e277000) malloc: can't allocate region
:*** mach_vm_map(size=262144, flags: 100) failed (error code=3)
iOSAppName(22955,0x16e277000) malloc: *** set a breakpoint in malloc_error_break to debug
iOSAppName(22955,0x16e277000) malloc: can't allocate region
:*** mach_vm_map(size=262144, flags: 100) failed (error code=3)
iOSAppName(22955,0x16e277000) malloc: *** set a breakpoint in malloc_error_break to debug
2021-02-26 21:45:15.540187+0000 iOSAppName[22955:11122435] *** Terminating app due to uncaught exception 'NSMallocException', reason: 'Failed to grow buffer'
*** First throw call stack:
(0x1ac64c878 0x1c0ba2c50 0x1ac6c2518 0x1ac6b977c 0x1ac561088 0x1ac586e68 0x1ac586c70 0x1adfd35b0 0x1ae1b75fc 0x1adeddf84 0x1adf163dc 0x1adf161a8 0x1ae1b26c8 0x1ae094b7c 0x1ae0948a8 0x1adfddc78 0x1ae1f8b64 0x1ae1f9164 0x1ade9f434 0x1ade9fc78 0x1df4c1114 0x1df4c0eac 0x1df4abb5c 0x1df4b0d84 0x102634d24 0x102655848 0x10260d998 0x102403814 0x1022ebda8 0x10219e654 0x10809fbcc 0x1080a16c0 0x1080a40ec 0x1080b4ae0 0x1080b5488 0x1f5a647c8 0x1f5a6b75c)
libc++abi.dylib: terminating with uncaught exception of type NSException
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
*** Terminating app due to uncaught exception 'NSMallocException', reason: 'Failed to grow buffer'
terminating with uncaught exception of type NSException654 0x10809fbcc 0x1080a16c0 0x1080a40ec 0x1080b4ae0 0x1080b5488 0x1f5a647c8 0x1f5a6b75c)
libc++abi.dylib: terminating with uncaught exception of type NSException
warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available.
*** Terminating app due to uncaught exception 'NSMallocException', reason: 'Failed to grow buffer'
terminating with uncaught exception of type NSException
So my solution was to use autorelasepool when writing to main document file. I'm not sure why the main document doesn't get released automatically. But this technically fixes the problem. New issue is that this slows the process down by at least 4 times.
_ = autoreleasepool
{
firstPDFDocument.write(to: exportPath().url)
}
If anyone has a solution to speed this up or a faster way to add pages to main pdf document. I'd appreciate it. Using Time Profiler writing to main document line uses 94% of all time for the function.
I am getting the following error message when I run my Swift code;
2019-11-11 15:59:58.737125+0000 GoSiteUK[53192:1746609] -[__SwiftValue MKCoordinateValue]: unrecognized selector sent to instance 0x60000037c720
2019-11-11 15:59:58.741797+0000 GoSiteUK[53192:1746609] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__SwiftValue MKCoordinateValue]: unrecognized selector sent to instance 0x60000037c720'
This code previously worked fine some weeks ago but is now not working with nothing changed.
let destinationPlacemark = MKPlacemark(coordinate: CLLocationCoordinate2D(latitude: 50.0, longitude: 1.0))
let destinationMapItem = MKMapItem(placemark: destinationPlacemark)
destinationMapItem.openInMaps(launchOptions: [
MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving,
MKLaunchOptionsMapCenterKey : CLLocationCoordinate2D(latitude: 51.0, longitude: 0.5)
] )
I expect the Maps app to open and no error messages.
I tried adding an item to an arrar and saving in Userdefault but the app crashed and I would love anyone to point me to what I am doing wrong
private func putArray(_ value: GMSAutocompletePrediction?, forKey key: String) {
guard let value = value else {
return
}
log("THE MESSAGE \(value)", .fuck)
var newArray = getArray(forKey: key)
log("THE MESSAGE ARRAY \(newArray)", .fuck)
if newArray.contains(value) {
newArray.remove(at: newArray.firstIndex(of: value)!)
} else {
newArray.append(value)
}
storage.setValue(NSKeyedArchiver.archivedData(withRootObject: newArray), forKey: key)
}
error from crash
[GMSAutocompletePrediction encodeWithCoder:]: unrecognized selector sent to instance 0x2818f9ce0
2019-09-26 13:40:07.300856+0100 MAX.NG Staging Debug[4440:1410011] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[GMSAutocompletePrediction encodeWithCoder:]: unrecognized selector sent to instance 0x2818f9ce0'
GMSAutocompletePrediction doesn't conform to NSCoding so you can't save it to user defaults , you may extract important details from it and make a custom model to save