realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.27k stars 2.14k forks source link

Realm Crashing on Read/ Write operator bool() const #5781

Closed dipkasyap closed 6 years ago

dipkasyap commented 6 years ago

Goals

Prevent crash

Expected Results

DB Operates normally

Actual Results

Crahsed


# OS Version: 11.3.1 (15E302)
# Device: iPhone 6 Plus
# RAM Free: 7.8%
# Disk Free: 60.8%

#0. Crashed: com.apple.main-thread
0  Realm                          0x102968468 RLMGetOptional + 60
1  Realm                          0x102908a54 RLMAccessorContext::propertyValue(objc_object*, unsigned long, RLMProperty*) + 804
2  Realm                          0x10290a568 RLMAccessorContext::value_for_property(objc_object*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long) + 156
3  Realm                          0x102957a40 realm::Object realm::Object::create<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, std::__1::shared_ptr<realm::Realm> const&, realm::ObjectSchema const&, objc_object* __strong, bool, realm::BasicRow<realm::Table>*) + 2908
4  Realm                          0x102956d44 RLMAddObjectToRealm + 596
5  RealmSwift                     0x1033b7a98 _T010RealmSwift0A0C3addyAA6ObjectC_Sb6updatetF + 724
6  MyAppName                      0x100d02a04 TodayVC.(getDataFromServer(Bool, isServerSync : Bool) -> ()).(closure #1).(closure #1) (TodayVC.swift:400)
7  RealmSwift                     0x1033b7350 _T010RealmSwift0A0C5writeyyyKcKF + 80
8  MyAppName                      0x100d02014 TodayVC.(getDataFromServer(Bool, isServerSync : Bool) -> ()).(closure #1) (TodayVC.swift:398)
9  MyAppName                      0x1011166bc static MyAppNameDaysDataModel.get(UIViewController, withMessage : String, withCompletion : (MyAppNameDaysDataModel?) -> (), withError : () -> ()) -> () empty-list Bool (MyAppNameDaysDataModel.swift:119)
10 MyAppName                      0x101094198 APIManager.getTodaysData(UIViewController, withProgressMessage : String?, withCmpletion : (Bool, MyAppNameDaysDataModel?) -> ()) -> () empty-list DataResponse empty-list withCmpletion (APIManager.swift:190)
11 MyAppName                      0x1010947d4 DataResponse<MyAppNameDaysDataModel> (APIManager.swift)
12 Alamofire                      0x101b40f80 _T09Alamofire11DataRequestC8responseACXDSo13DispatchQueueCSg5queue_x0D10SerializeryAA0B8ResponseVy16SerializedObjectQzGc17completionHandlertAA0biH8ProtocolRzlFyycfU_yycfU_ + 236
13 Alamofire                      0x101b0bda8 _T0Ieg_IeyB_TR + 52
14 libdispatch.dylib              0x183cdcb24 _dispatch_call_block_and_release
15 libdispatch.dylib              0x183cdcae4 _dispatch_client_callout
16 libdispatch.dylib              0x183ce96e0 _dispatch_main_queue_callback_4CF$VARIANT$mp
17 CoreFoundation                 0x184393070 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
18 CoreFoundation                 0x184390bc8 __CFRunLoopRun + 2272
19 CoreFoundation                 0x1842b0da8 CFRunLoopRunSpecific + 552
20 GraphicsServices               0x186293020 GSEventRunModal + 100
21 UIKit                          0x18e29178c UIApplicationMain + 236
22 MyAppName                      0x100e4fb10 main (AppDelegate.swift:23)
23 libdyld.dylib                  0x183d41fc0 start + 4

--

#0. Crashed: com.apple.main-thread
0  Realm                          0x102968468 RLMGetOptional + 60
1  Realm                          0x102908a54 RLMAccessorContext::propertyValue(objc_object*, unsigned long, RLMProperty*) + 804
2  Realm                          0x10290a568 RLMAccessorContext::value_for_property(objc_object*, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, unsigned long) + 156
3  Realm                          0x102957a40 realm::Object realm::Object::create<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, std::__1::shared_ptr<realm::Realm> const&, realm::ObjectSchema const&, objc_object* __strong, bool, realm::BasicRow<realm::Table>*) + 2908
4  Realm                          0x102956d44 RLMAddObjectToRealm + 596
5  RealmSwift                     0x1033b7a98 _T010RealmSwift0A0C3addyAA6ObjectC_Sb6updatetF + 724
6  MyAppName                      0x100d02a04 TodayVC.(getDataFromServer(Bool, isServerSync : Bool) -> ()).(closure #1).(closure #1) (TodayVC.swift:400)
7  RealmSwift                     0x1033b7350 _T010RealmSwift0A0C5writeyyyKcKF + 80
8  MyAppName                      0x100d02014 TodayVC.(getDataFromServer(Bool, isServerSync : Bool) -> ()).(closure #1) (TodayVC.swift:398)
9  MyAppName                      0x1011166bc static MyAppNameDaysDataModel.get(UIViewController, withMessage : String, withCompletion : (MyAppNameDaysDataModel?) -> (), withError : () -> ()) -> () empty-list Bool (MyAppNameDaysDataModel.swift:119)
10 MyAppName                      0x101094198 APIManager.getTodaysData(UIViewController, withProgressMessage : String?, withCmpletion : (Bool, MyAppNameDaysDataModel?) -> ()) -> () empty-list DataResponse empty-list withCmpletion (APIManager.swift:190)
11 MyAppName                      0x1010947d4 DataResponse<MyAppNameDaysDataModel> (APIManager.swift)
12 Alamofire                      0x101b40f80 _T09Alamofire11DataRequestC8responseACXDSo13DispatchQueueCSg5queue_x0D10SerializeryAA0B8ResponseVy16SerializedObjectQzGc17completionHandlertAA0biH8ProtocolRzlFyycfU_yycfU_ + 236
13 Alamofire                      0x101b0bda8 _T0Ieg_IeyB_TR + 52
14 libdispatch.dylib              0x183cdcb24 _dispatch_call_block_and_release
15 libdispatch.dylib              0x183cdcae4 _dispatch_client_callout
16 libdispatch.dylib              0x183ce96e0 _dispatch_main_queue_callback_4CF$VARIANT$mp
17 CoreFoundation                 0x184393070 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
18 CoreFoundation                 0x184390bc8 __CFRunLoopRun + 2272
19 CoreFoundation                 0x1842b0da8 CFRunLoopRunSpecific + 552
20 GraphicsServices               0x186293020 GSEventRunModal + 100
21 UIKit                          0x18e29178c UIApplicationMain + 236
22 MyAppName                      0x100e4fb10 main (AppDelegate.swift:23)
23 libdyld.dylib                  0x183d41fc0 start + 4

#1. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x18400feb4 _pthread_wqthread + 928
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#2. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x18400feb4 _pthread_wqthread + 928
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#3. com.apple.uikit.eventfetch-thread
0  libsystem_kernel.dylib         0x183e4fe08 mach_msg_trap + 8
1  libsystem_kernel.dylib         0x183e4fc80 mach_msg + 72
2  CoreFoundation                 0x184392e40 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x184390908 __CFRunLoopRun + 1568
4  CoreFoundation                 0x1842b0da8 CFRunLoopRunSpecific + 552
5  Foundation                     0x184d25674 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6  Foundation                     0x184d254dc -[NSRunLoop(NSRunLoop) runUntilDate:] + 84
7  UIKit                          0x18df767e4 -[UIEventFetcher threadMain] + 136
8  Foundation                     0x184e35efc __NSThread__start__ + 1040
9  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
10 libsystem_pthread.dylib        0x184011110 _pthread_body + 290
11 libsystem_pthread.dylib        0x18400fb10 thread_start + 4

#4. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x18400feb4 _pthread_wqthread + 928
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#5. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x18400feb4 _pthread_wqthread + 928
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#6. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x18400feb4 _pthread_wqthread + 928
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#7. RLMRealm notification listener
0  libsystem_kernel.dylib         0x183e5434c kevent + 8
1  Realm                          0x102830214 realm::_impl::ExternalCommitHelper::listen() + 412
2  Realm                          0x10283470c realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0::operator()() const + 28
3  Realm                          0x1028346e4 _ZNSt3__112__async_funcIZN5realm5_impl20ExternalCommitHelperC1ERNS2_16RealmCoordinatorEE3$_0JEE9__executeIJEEEvNS_15__tuple_indicesIJXspT_EEEE + 64
4  Realm                          0x102834698 std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0>::operator()() + 24
5  Realm                          0x1028345a8 std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >::__execute() + 36
6  Realm                          0x102835294 std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >::*)(), std::__1::__async_assoc_state<void, std::__1::__async_func<realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >*> >(void*, void*) + 496
7  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
8  libsystem_pthread.dylib        0x184011110 _pthread_body + 290
9  libsystem_pthread.dylib        0x18400fb10 thread_start + 4

#8. com.twitter.crashlytics.ios.MachExceptionServer
0  MyAppName                      0x10114a2a0 CLSProcessRecordAllThreads
1  MyAppName                      0x10114a2a0 CLSProcessRecordAllThreads
2  MyAppName                      0x10114a15c CLSProcessRecordAllThreads
3  MyAppName                      0x101139628 CLSHandler
4  MyAppName                      0x1011342d8 CLSMachExceptionServer
5  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
6  libsystem_pthread.dylib        0x184011110 _pthread_body + 290
7  libsystem_pthread.dylib        0x18400fb10 thread_start + 4

#9. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x18400feb4 _pthread_wqthread + 928
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#10. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x1840100a0 _pthread_wqthread + 1420
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#11. Thread
0  libsystem_pthread.dylib        0x18400fb04 start_wqthread + 122

#12. com.apple.NSURLConnectionLoader
0  libsystem_kernel.dylib         0x183e4fe08 mach_msg_trap + 8
1  libsystem_kernel.dylib         0x183e4fc80 mach_msg + 72
2  CoreFoundation                 0x184392e40 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x184390908 __CFRunLoopRun + 1568
4  CoreFoundation                 0x1842b0da8 CFRunLoopRunSpecific + 552
5  CFNetwork                      0x184bbe4b0 -[__CoreSchedulingSetRunnable runForever] + 220
6  Foundation                     0x184e35efc __NSThread__start__ + 1040
7  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
8  libsystem_pthread.dylib        0x184011110 _pthread_body + 290
9  libsystem_pthread.dylib        0x18400fb10 thread_start + 4

#13. com.squareup.SocketRocket.NetworkThread
0  libsystem_kernel.dylib         0x183e4fe08 mach_msg_trap + 8
1  libsystem_kernel.dylib         0x183e4fc80 mach_msg + 72
2  CoreFoundation                 0x184392e40 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x184390908 __CFRunLoopRun + 1568
4  CoreFoundation                 0x1842b0da8 CFRunLoopRunSpecific + 552
5  Foundation                     0x184d25674 -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 304
6  MyAppName                      0x101262b40 -[_FSRRunLoopThread main]
7  Foundation                     0x184e35efc __NSThread__start__ + 1040
8  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
9  libsystem_pthread.dylib        0x184011110 _pthread_body + 290
10 libsystem_pthread.dylib        0x18400fb10 thread_start + 4

#14. Thread
0  libsystem_kernel.dylib         0x183e71d84 __workq_kernreturn + 8
1  libsystem_pthread.dylib        0x1840100a0 _pthread_wqthread + 1420
2  libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#15. com.apple.CFSocket.private
0  libsystem_kernel.dylib         0x183e71538 __select + 8
1  CoreFoundation                 0x18439b378 __CFSocketManager + 644
2  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
3  libsystem_pthread.dylib        0x184011110 _pthread_body + 290
4  libsystem_pthread.dylib        0x18400fb10 thread_start + 4

#16. Thread
0  libsystem_pthread.dylib        0x18400fb04 start_wqthread + 122

#17. NSOperationQueue 0x10448e2a0 (QOS: UTILITY)
0  CoreFoundation                 0x184394c24 _CFRelease + 192
1  CoreFoundation                 0x1842b514c -[__NSArrayI dealloc] + 64
2  CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
3  CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
4  CoreFoundation                 0x1842b514c -[__NSArrayI dealloc] + 64
5  CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
6  CoreFoundation                 0x1842b514c -[__NSArrayI dealloc] + 64
7  CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
8  CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
9  CoreFoundation                 0x1842b514c -[__NSArrayI dealloc] + 64
10 CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
11 CoreFoundation                 0x1842bc5b4 -[__NSDictionaryI dealloc] + 136
12 libobjc.A.dylib                0x1835c213c (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 844
13 CoreFoundation                 0x1842b0aac _CFAutoreleasePoolPop + 28
14 Foundation                     0x184d53f60 -[__NSOperationInternal _start:] + 1540
15 libdispatch.dylib              0x183cdcae4 _dispatch_client_callout
16 libdispatch.dylib              0x183ce41f4 _dispatch_block_invoke_direct$VARIANT$mp
17 libdispatch.dylib              0x183cdcae4 _dispatch_client_callout
18 libdispatch.dylib              0x183ce41f4 _dispatch_block_invoke_direct$VARIANT$mp
19 libdispatch.dylib              0x183ce40e0 dispatch_block_perform$VARIANT$mp
20 Foundation                     0x184e14750 __NSOQSchedule_f + 376
21 libdispatch.dylib              0x183cdcae4 _dispatch_client_callout
22 libdispatch.dylib              0x183ce4f18 _dispatch_continuation_pop$VARIANT$mp
23 libdispatch.dylib              0x183ce3850 _dispatch_async_redirect_invoke$VARIANT$mp
24 libdispatch.dylib              0x183ce9d30 _dispatch_root_queue_drain
25 libdispatch.dylib              0x183ce9a80 _dispatch_worker_thread3
26 libsystem_pthread.dylib        0x18400ffac _pthread_wqthread + 1176
27 libsystem_pthread.dylib        0x18400fb08 start_wqthread + 4

#18. com.apple.CoreMotion.MotionThread
0  libsystem_kernel.dylib         0x183e4fe08 mach_msg_trap + 8
1  libsystem_kernel.dylib         0x183e4fc80 mach_msg + 72
2  CoreFoundation                 0x184392e40 __CFRunLoopServiceMachPort + 196
3  CoreFoundation                 0x184390908 __CFRunLoopRun + 1568
4  CoreFoundation                 0x1842b0da8 CFRunLoopRunSpecific + 552
5  CoreFoundation                 0x184300b28 CFRunLoopRun + 116
6  CoreMotion                     0x1898919dc CLStartStopAdvertisingBeacon + 231572
7  libsystem_pthread.dylib        0x184011220 _pthread_body + 272
8  libsystem_pthread.dylib        0x184011110 _pthread_body + 290
9  libsystem_pthread.dylib        0x18400fb10 thread_start + 4

Screen shots

screen shot 2018-05-24 at 11 32 39 am screen shot 2018-05-24 at 11 36 48 am screen shot 2018-05-24 at 11 37 24 am

Steps to Reproduce

Realm data read or write producing this issue, First my realm version was 3.0.2 at that time some users of app were facing this issue (not all users were facing this issue), Now i decided to upgrade library via cocoapod and mad 3.5.0 it is crashing on every build

Code Sample

do {
try uiRealm.write {
uiRealm.add(response)
}
}
catch  {
print("could not write")
}

Version of Realm and Tooling

Realm framework version: ? 3.5.0

Xcode version: Version 9.3 (9E145)

iOS/OSX version: 11.2.1 (iOS)

Dependency manager + version: CocoaPod 1.5.2

tgoyne commented 6 years ago

Can you either reduce this to a standalone repro case, or share the source to your application which runs into problems? Without that it will be difficult to make any progress.

dipkasyap commented 6 years ago

Thank you for replay, i can share my modal class . Do you wish me to do so ? As i have mentioned before, it was crashing on some users when the realm version was 3.0.2 , but when i upgraded the realm to version 3.5.0 on same code , with out changing any code/ modal class it is crashing on every attempt.

tgoyne commented 6 years ago

Just the model classes are unlikely to reveal anything interesting.

dipkasyap commented 6 years ago

@tgoyne What is the solution for me then? believe there is some serious issue with library. Could you please provide clue what might be the reason of crash?

tgoyne commented 6 years ago

Yes, this probably a Realm bug. If it is crashing every time, then you should be able to reduce it to a standalone piece of code which hits the problem which you could share with us.

dipkasyap commented 6 years ago

/************************* Realm Issue method block *************************/
id RLMAccessorContext::propertyValue(__unsafe_unretained id const obj, size_t propIndex,
__unsafe_unretained RLMProperty *const prop) {
    // Property value from an NSArray
    if ([obj respondsToSelector:@selector(objectAtIndex:)]) {
        return propIndex < [obj count] ? [obj objectAtIndex:propIndex] : nil;
    }

    // Property value from an NSDictionary
    if ([obj respondsToSelector:@selector(objectForKey:)]) {
        return [obj objectForKey:prop.name];
    }

    // Property value from an instance of this object type
    id value;
    if ([obj isKindOfClass:_info.rlmObjectSchema.objectClass] && prop.swiftIvar) {
        if (prop.array) {
            return static_cast<RLMListBase *>(object_getIvar(obj, prop.swiftIvar))._rlmArray;
        }
        else { // optional
            value = RLMGetOptional(static_cast<RLMOptionalBase *>(object_getIvar(obj, prop.swiftIvar)));
        }
    }
    else {
        // Property value from some object that's KVC-compatible
        value = RLMValidatedValueForProperty(obj, [obj respondsToSelector:prop.getterSel] ? prop.getterName : prop.name,
                                             _info.rlmObjectSchema.className);
    }
    return value ?: NSNull.null;
}

/**************************************************/

/************************ MY Modal class **************************/

import Foundation
import ObjectMapper
import AlamofireObjectMapper
import ObjectMapper_Realm
import RealmSwift

// MARK: - Enum Meals Type
enum MealsType:String {
    case nonVeg="nonVeg",veg="vegetarian",vegan = "vegan"
}

class Model: Object, Mappable {
    @objc dynamic var name:String? = nil

    required convenience init?(map: Map) {
        self.init()
    }

    func mapping(map: Map) {
        name <- map["name"]
    }
}

class MyAppNameDaysDataModel:Object, Mappable {

    ///This variable tracks training all stage compeleted or not,
    ///if hasData = false this means there are no data further available so
    ///we consider the training or all stages are completed
    ///if hasData = true then we will fetch new data from server and then replace the offlice cache
    var hasData = true

    //error handling vars
    private var errorStatus : Bool?
    private var messageString: String?

    var message: String? {
        get {
            return messageString
        }
    }

    var error: Bool? {
        get {
            return errorStatus
        }
    }

    //Normal vars
    @objc dynamic var name: String? = ""
    @objc dynamic var code: String? = nil
    @objc dynamic var color: String? = nil
    @objc dynamic var descriptions: String? = nil
    @objc dynamic var menuTitle: String? = nil
    @objc dynamic var infoTitle: String? = nil
    @objc dynamic var info: String? = nil
    @objc dynamic var currentDay: Int = 1
    @objc dynamic var currentStage: Int = 1
    @objc dynamic var workOutSummary: String? = nil
    @objc dynamic var image: String? = nil
    @objc dynamic var timeStamp: String? = nil

    var days = List<DayResponseModel>()

    required convenience init?(map: Map) {
        self.init()
    }

    func mapping(map: Map) {

        //flag var
        hasData <- map["data.has_data"]

        //error vars
        errorStatus <- map["error"]
        messageString <- map["message"]

        //Regualr vars
        name <- map["data.training_program_info.name"]
        code <- map["data.training_program_info.code"]
        color <- map["data.training_program_info.color"]
        descriptions <- map["data.training_program_info.description"]
        menuTitle <- map["data.training_program_info.menu_title"]
        infoTitle <- map["data.training_program_info.info_title"]
        info <- map["data.training_program_info.info"]
        currentStage <- map["data.current_day_info.stage"]
        currentDay <- map["data.current_day_info.day"]
        workOutSummary <- map["data.current_day_info.workout_summary"]
        image <- map["data.current_day_info.image"]

        timeStamp <- map["data.training_completed_timestamp"]

        //update current training type
        if let code = code {
            UserDefaultsHandler().setToUD(key: UDkey.trainingProgram.rawValue, value: code as AnyObject)
        }

        days <- (map["data.days"], ListTransform<DayResponseModel>())

    }

    // MARK: - Geter 
    class func get(_ viewController: UIViewController, withMessage message:String = "Loading data", withCompletion completion:@escaping (MyAppNameDaysDataModel?)->(), withError error:@escaping ()->() ) {

        APIManager(urlString: MyAppNameURL.URLGetTodayInfo, method: .get).getTodaysData(viewController, withProgressMessage: message) { (success,MyAppNameDaysDataModel ) in

            if success {
                completion(MyAppNameDaysDataModel)

            } else {
                //show error or retry
                completion(nil)
            }
        }
    }

}

class DayResponseModel:Object, Mappable {

    @objc dynamic var id: String? = nil
    @objc dynamic var stage: String? = nil
    @objc dynamic var day : String? = nil
    @objc dynamic var workoutSummary: String? = nil
    @objc dynamic var messageQuote:String?
    @objc dynamic var messageQuoteTitle:String?
    @objc dynamic var messageImageUrl:String?

    @objc dynamic var trainingThemeGym: String? = nil
    @objc dynamic var trainingThemeHome: String? = nil
    var trainingTheme: String {
        get {
            if (UserLoginInfo.getUserInfo()?.trainingEnvironment) ?? .gym  == .gym {
                return self.trainingThemeGym ?? ""
            } else {
                return self.trainingThemeHome ?? ""
            }
        }
    }

    @objc dynamic var trainingThemeDescriptionGym: String? = nil
    @objc dynamic var trainingThemeDescriptionHome: String? = nil
    var trainingThemeDescription: String {
        get {
            if (UserLoginInfo.getUserInfo()?.trainingEnvironment)! == .gym {
                return self.trainingThemeDescriptionGym!
            } else {
                return self.trainingThemeDescriptionHome!
            }
        }
    }

    @objc dynamic var image: String? = nil

    @objc dynamic var isToday: Bool = false
    @objc dynamic var todayCandidate: Bool = false
    @objc dynamic var isCompleted: Bool = false

    var mealsOfDay = List<MealsOptionsModel>()
    @objc dynamic var trainingOfDay : TrainingModel? = nil

    ///view manipulation var
    @objc dynamic var currentTrainingIndex:Int = 0

    func getAllMeals() -> [MealModel] {
        var meals:[MealModel] = [MealModel]()
        let mealsOfDay = Array(self.mealsOfDay)

        for meal in mealsOfDay {
            let options = meal.mealsOption

            for option in options {
                meals.append(option)
            }
        }

        return meals
    }

    func getActiveMealsOfDay() -> [MealModel] {

        var meals:[MealModel] = [MealModel]()

        let mealsOfDay = Array(self.mealsOfDay)
        for aMeal in mealsOfDay {
            meals.append(aMeal.getActiveMeal()!)
        }

        return meals

    }

    var isExpanded: Bool = false
    var currentOpennedIndex:Int = -1

    required convenience init?(map: Map) {
        self.init()
    }

    func mapping(map: Map) {
        id <- map["id"]
        stage <- map["stage"]
        day <- map["day"]
        workoutSummary <- map["workout_summary"]
        image <- map["image"]
        isToday <- map["today"]
        isCompleted <- map["completed"]

        trainingThemeGym <- map["theme_name_gym"]
        trainingThemeHome <- map["theme_name_home"]

        trainingThemeDescriptionGym <- map["theme_description_gym"]
        trainingThemeDescriptionHome <- map["theme_description_home"]

        messageQuoteTitle <- map["training_quote.title"]
        messageQuote <- map["training_quote.quote"]
        messageImageUrl <- map["training_quote.image"]

        let userInfo = UserLoginInfo.getUserInfo()
        let dietRequirement = userInfo?.dietRequirement
        let key = "meals.\(dietRequirement!.lowercased())"

        mealsOfDay <- (map[key], ListTransform<MealsOptionsModel>())

        //Training
        trainingOfDay <- map["workouts"]
    }

}

class MealsOptionsModel:Object, Mappable{

    var mealsOption = List<MealModel>()

    /// showIndex is the index value of current meals among meals options array
    @objc dynamic var showIndex: Int = 0 {
        didSet {
            if oldValue != self.showIndex {

                let meals = self.mealsOption

                for i in 0...meals.count-1 {
                    if self.showIndex == i {
                        meals[i].isSelected = true
                    } else {
                        meals[i].isSelected = false
                    }
                }
            }
        }
    }

    required convenience init?(map: Map) {
        self.init()
    }

    func mapping(map: Map) {

        ///all meals of the day
        mealsOption <- (map["options"], ListTransform<MealModel>())

        ///Current meal tracker for future use
        showIndex <- map["show_index"]
    }

    func getActiveMeal() -> MealModel? {

        if uiRealm.objects(MyAppNameDaysDataModel.self).first == nil {
            print("Nullvalue of objectg...... Need to handlled accordingly....DIP")
            return nil
        }

        let meals = self.mealsOption
        let index = self.showIndex
        return meals[index]
    }

    func replaceMeal(_ then:(_ replaced:Bool,_ mealId:String?, _ isOldMeal:Bool?)->()) {

        for index in 0...self.mealsOption.count-1 {

            if self.mealsOption[index].isSelected {

                if uiRealm.isInWriteTransaction  {
                    do {
                        try uiRealm.commitWrite()
                    }
                    catch {
                        print("Unableto commit")
                        then(false,nil,false)
                    }
                }

                uiRealm.beginWrite()
                guard self.showIndex != index else { then(false,nil,true); return }
                self.showIndex = index
                do {
                    try uiRealm.commitWrite() }
                catch {
                    print("Unableto commit")
                    then(false,nil,false)
                }
                then(true,self.mealsOption[index].id,false)
                return
            } else {
                if index+1 == self.mealsOption.count {
                    then(false,nil,false)
                }
            }
        }
    }

    func rollBackReplaceProcess() {

        do {
            try uiRealm.commitWrite()
        } catch {
            print("Unable to commit")
        }

        uiRealm.beginWrite()
        for index in 0...self.mealsOption.count-1 {
            self.mealsOption[index].isSelected = index == self.showIndex
        }
        do {
            try uiRealm.commitWrite()
        } catch {
            print("Unable to roll back commit")
        }
    }
}

class UnitMeasure:Object, Mappable{

    @objc dynamic var ingridient: String? = nil
    @objc dynamic var quantity: CGFloat = 0.0
    @objc dynamic var unit: String? = nil

    required convenience init?(map: Map) {
        self.init()
    }

    func mapping(map: Map) {
        ingridient <- map["ingridient"]
        quantity <- map["quantity"]
        unit <- map["unit"]
    }

}

class MealModel:Object, Mappable {

    @objc dynamic  var id: String?
    @objc dynamic  var title : String?
    @objc dynamic  var descriptions: String?
    @objc dynamic  var tags: String?
    @objc dynamic  var tips: String?
    @objc dynamic  var PreparationTime: String?
    @objc dynamic  var servings: String?
    @objc dynamic  var calories : Int = 0
    @objc dynamic  var ingredientsMetric: String?
    @objc dynamic  var ingredientsImperial: String?

    var ingredients: String {
        let unit =  MeasurementUnit(rawValue: UserDefaultsHandler().getUDValue(key: Units_of_Measure) as? Int ?? 1 )
        if unit == .metric {
            return ingredientsImperial! //ingredientsMetric!
        } else {
            return ingredientsImperial ??  ingredientsMetric!
        }
    }

    @objc dynamic  var mealNo : Int = 1
    @objc dynamic  var steps : String? = nil

    @objc dynamic  var favouredMeal: Bool = false
    @objc dynamic  var image : String?

    public let imperialIngridients = List<StringObject>() // Should be declared with `let`
    public let metricIngridients = List<StringObject>() // Should be declared with `let`
    public let dietShortCode = List<StringObject>() // Should be declared with `let`

    var impericalQuantity = List<UnitMeasure>()
    var metricQuantity = List<UnitMeasure>()

    @objc dynamic var isSelected = false {
        didSet {
        }
    }

    required convenience init?(map: Map) {
        self.init()
    }

    func mapping(map: Map) {

        id <- map["id"]
        title <- map["title"]
        descriptions <- map["description"]
        tags <- map["tags"]
        tips <- map["tips"]
        PreparationTime <- map["preparation_time"]
        servings <- map["servings"]
        calories <- map["calories"]
        mealNo <- map["meal_no"]

        // MARK: - converting array into string with new line
        var stepArray: [String]?
        stepArray <- map["steps"]
        steps = (stepArray?.joined(separator:"\n"))!

        favouredMeal <- map["favoured_meal"]
        image <- map["image"]

        //handling array for realm
        var dietShortCode: [String]? = nil
        dietShortCode <- map["diet_shortcode"] // Maps to local variable

        dietShortCode?.forEach { option in // Then fill options to `List`
            let value = StringObject()
            value.value = option
            self.dietShortCode.append(value)
        }

        var metricIngridients: [String]? = nil
        metricIngridients <- map["ingridients.metric"] // Maps to local variable

        metricIngridients?.forEach { option in // Then fill options to `List`
            let value = StringObject()
            value.value = option
            self.metricIngridients.append(value)
        }

        var imperialIngridients: [String]? = nil
        imperialIngridients <- map["ingridients.imperial"] // Maps to local variable

        imperialIngridients?.forEach { option in // Then fill options to `List`
            let value = StringObject()
            value.value = option
            self.imperialIngridients.append(value)
        }

        self.ingredientsMetric = metricIngridients?.joined(separator: "\n")
        self.ingredientsImperial = imperialIngridients?.joined(separator: "\n")

        metricQuantity <- (map["ingridients.metric_quantity"], ListTransform<UnitMeasure>())
        impericalQuantity <- (map["ingridients.imperial_quantity"], ListTransform<UnitMeasure>())
    }
}

/************************ End MY Modal class **************************/

/******************** Realm accessing Method Block class ***************/

// Method to flush
func flushDataBase() {

    if uiRealm.isInWriteTransaction {
        do {
            try uiRealm.commitWrite()
        } catch {
            print("Unable to commit")
        }
    }

    if syncRealm.isInWriteTransaction {
        do {
            try syncRealm.commitWrite()
        } catch {
            print("Unable to commit")
        }
    }

    do {
        try syncRealm.write {
            syncRealm.deleteAll()
        }
    } catch {
        print("Unable to flush -sync DB... Retrying")
        flushDataBase()
    }

    do {
        try uiRealm.write {
            uiRealm.deleteAll()
        }
    } catch {
        print("Unable to flush DB... Retrying")
        flushDataBase()
    }
}

//This method to prepare Realm on case of removeAll called previously
func prepareSyncEngine() {

    func isDataExists()->Bool {
        let data = syncRealm.objects(UserSyncModal.self)
        let alldata = data.first

        if alldata != nil {
            return true
        } else {
            return false
        }
    }

    if !isDataExists() {
        do {
            try syncRealm.write {

                let sync =  UserSyncModal()
                AppDataProvider.shared.syncEngine = sync
                syncRealm.add(AppDataProvider.shared.syncEngine!)
            }
        }catch {
            print("Unablet to write data")
        }
    } else {

        let sync = syncRealm.objects(UserSyncModal.self)
        AppDataProvider.shared.syncEngine = sync.first
        print("Sync table exist...")
    }

    //Countries
    Countries.loadCountriesList { (countries, success) in
        if success {
            self.countries = countries
        }
    }
}
}

//Realm accessing method
// MARK: - get Todays Info
@objc private func getTodayinfo(_ syncing: Bool = false, isServerSync: Bool = false ) {

    print(Realm.Configuration.defaultConfiguration.fileURL!)

    func loadOfflineData(_ then:@escaping (_ loadOffline:Bool)->()) {
        self.blur()

        let data = uiRealm.objects(MyAppNameDaysDataModel.self)
        let alldata = data.first

        if alldata != nil {
            //has data on offline

            if AppDataProvider.shared.isSyncRequired() || isServerSync {

                AppDataProvider.shared.sync(self, then: { [weak self] (success, error) in
                    if success {
                        self?.isSyncing = true
                        //self?.getTodayinfo(true)

                    } else {

                        guard let syncError = error?.syncError else {
                            then(true)
                            return
                        }

                        if syncError {

                            if uiRealm.isInWriteTransaction {
                                do {
                                    try uiRealm.commitWrite()
                                } catch {
                                    print("Unable to commit")
                                }
                            }

                            //sync engine clearing
                            do {
                                try uiRealm.write {
                                    uiRealm.delete(AppDataProvider.shared.syncEngine!)
                                }
                            }
                            catch  {
                                print("could not write")
                            }
                        }
                        //self?.getDataFromServer(true, isServerSync: true)
                    }

                    then(false) // needs to refetch data

                })
            } else {

                then(true)//offline cache had data
            }
        } else {
            //no data on offline

            let vc: TapToReloadViewController = UIStoryboard(storyboard: .noInternetConnection).instantiateViewController()
            self.tapToReloadVC = vc

            self.reachability = Reachability()!
            reachability?.whenUnreachable = { [weak self] _ in
                if self?.presentedViewController != nil {
                }else{
                    self?.present((self?.tapToReloadVC)!, animated: true, completion: nil)
                }
                print("Not reachable")
            }

            do {
                try reachability?.startNotifier()
            } catch {
                print("Unable to start notifier")
            }

            then(false)//no data on offline, fetch from server
        }
    }

    let syncRequired = UserDefaultsHandler().getUDValue(key: UDkey.isSyncing.rawValue) as? Bool ?? false

    loadOfflineData { [weak self] (loadOffline) in
        if loadOffline && !syncRequired {
            AppDataProvider.shared.allData = Array(uiRealm.objects(MyAppNameDaysDataModel.self)).first
            if !uiRealm.isInWriteTransaction {
                AppDataProvider.shared.hasTodaysTrainingFinisehd {
                    self?.setUpApi(data: AppDataProvider.shared.allData)
                }
                self?.presentedViewController?.dismiss(animated: true, completion: nil)
            }
        } else  {
            self?.getDataFromServer(true, isServerSync: true)
        }
    }
}

func getDataFromServer(_ syncing: Bool = false, isServerSync: Bool = false ) {
    self.blur()

    let isSyncing = (UserDefaultsHandler().getUDValue(key: UDkey.isSyncing.rawValue) as? Bool ?? false) || syncing
    self.isSyncing = isSyncing

    MyAppNameDaysDataModel.get(self, withMessage: isSyncing ? "Syncing data" : "Loading data" , withCompletion: { [weak self] (response) in

        UserDefaultsHandler().removeUD(key: UDkey.isSyncing.rawValue)

        if let response = response {

            guard response.hasData else {
                print("Needs to handle this.....")
                let story = UIStoryboard(name: StoryboardName.Training.rawValue, bundle: nil)
                let vc1 = story.instantiateViewController(withIdentifier: StoryboardID.StageCompletionVCID.rawValue )as! StageCompletionVC
                self?.present(vc1, animated: true, completion: nil)
                return
            }

            //Prepare Realm
            flushDataBase()
            AppDataProvider.shared.prepareSyncEngine()

            do {
                try uiRealm.write {
                    uiRealm.add(response) // This is the line where realm crahes
                }
            }
            catch  {
                print("could not write")
            }

            self?.getTodayinfo()

        } else {

            ProgressHud.hideProgressHUD()
            self?.unblur()

            Banner.show("Some thing went wrong!", andSubtitle: "Please try again later", andColor: UIColor.appDefaultColor)
            let vc: TapToReloadViewController = UIStoryboard(storyboard: .noInternetConnection).instantiateViewController()
            self?.tapToReloadVC = vc
            self?.reachability = Reachability()!
            self?.present((self?.tapToReloadVC)!, animated: true, completion: nil)
        }

    }) { [weak self]  in
        ProgressHud.hideProgressHUD()
        self?.unblur()
        Banner.show("Opps", andSubtitle: "Server not responding..")
    }
}

/******************** End accessing Method Block ***************/

@tgoyne Please have a look

tgoyne commented 6 years ago

Thanks, I'll see if I can reproduce the issue.

dipkasyap commented 6 years ago

@tgoyne Any progress ? My App is in production and facing big loss.

tgoyne commented 6 years ago

It looks like the problem is that the private var messageString: String? property is not being handled correctly. String? is a support type so it's not being automatically ignored, but because it's not @objc it's being misdetected and initialized incorrectly.

While I'm working on a fix for this you should be able to work around it by explicitly telling Realm not to touch the private properties by adding them to ignoredProperties (i.e. override class func ignoredProperties() -> [String] { return ["hasData", "errorStatus", "messageString"] } for the DaysDataModel.

dipkasyap commented 6 years ago

I downgraded to 3.4.0 its working on same code base. There is some serious issue on lib, Which is not providing actual error to swift wrapper.

Installing Realm 3.4.0 (was 3.5.0 and source changed to `https://github.com/CocoaPods/Specs.git` from `https://github.com/cocoapods/specs.git`)

And it stoped to crash on

             do {
                     try uiRealm.write {
                     uiRealm.add(response)
                      }
                }
                    catch  {
                      print("could not write")
                  }

Any way let me try to use ignoredProperties on 3.5.0 , i will update on this soon. Also i have a question regarding primary key, does is make any problem if i am not using primary key on my db ?

ptsiogas commented 5 years ago

Hi there,

Why is this issue closed? I am facing the same issue in version 3.12.0. Is there any workaround?

bmunkholm commented 5 years ago

@ptsiogas Please create a new issue with all details then (and refer to this one).