swift: EXC_BAD_ACCESS with using Realm and FolioReaderKit - ios

I installed FolioReaderKit using Cocoapods to read epub book. I'm trying to highlight text and add it to a list of highlights. But when I do this I get this error and my app crashes:
Thread 1: EXC_BAD_ACCESS (code=257, address=0x41c4a1c96ae55d46)
line:
value = RLMGetOptional(static_cast<RLMOptionalBase *>(object_getIvar(obj, prop.swiftIvar)));
in RLMAccessor.mm:
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 if (prop.swiftIvar == RLMDummySwiftIvar) {
// FIXME: An invalid property which we're pretending is nil until 4.0
// https://github.com/realm/realm-cocoa/issues/5784
return NSNull.null;
}
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;
}
How to fix it?

Related

CloudKit CKError extension not available in Objective-C?

I read somewhere here that CKError is not available in Objective-C, and I concur. For instance, this extension is available in Swift.
#available(OSX 10.10, iOS 8.0, watchOS 3.0, *)
extension CKError {
/// Retrieve partial error results associated by item ID.
public var partialErrorsByItemID: [AnyHashable : Error]? { get }
/// The original CKRecord object that you used as the basis for
/// making your changes.
public var ancestorRecord: CKRecord? { get }
/// The CKRecord object that was found on the server. Use this
/// record as the basis for merging your changes.
public var serverRecord: CKRecord? { get }
/// The CKRecord object that you tried to save. This record is based
/// on the record in the CKRecordChangedErrorAncestorRecordKey key
/// but contains the additional changes you made.
public var clientRecord: CKRecord? { get }
/// The number of seconds after which you may retry a request. This
/// key may be included in an error of type
/// `CKErrorServiceUnavailable` or `CKErrorRequestRateLimited`.
public var retryAfterSeconds: Double? { get }
}
The problem is that I need these objects in my Objective-C project.
I've somehow (I believe) managed to get the partialErrorsByItemID in Objective-C by making a category for NSError and a little comprehension of the documentation of CKError.h, like so:
CKErrorCode ckErrorCode = (CKErrorCode) _code;
if (ckErrorCode == CKErrorPartialFailure) {
// When a CKErrorPartialFailure happens this key will be set in the error's userInfo dictionary.
// The value of this key will be a dictionary, and the values will be errors for individual items with the keys being the item IDs that failed.
NSDictionary *dicError = _userInfo;
if ([dicError objectForKey:CKPartialErrorsByItemIDKey] != nil) {
NSDictionary *dic = (NSDictionary *)[dicError objectForKey:CKPartialErrorsByItemIDKey];
for (NSString* key in dic) {
NSError *newError = dic[key];
if (code == newError.code) {
match = YES;
}
}
} else {
return NO;
}
}
But again, my problem is how to get the objects serverRecord and the clientRecord. Any idea?
Here's an Objective-C category that replicates most of the CKError structure of Swift. I didn't add errorCode, localizedDescription or errorUserInfo since NSError already provides those as code, localizedDescription, and userInfo.
CloudKitExtensions.h
#import <CloudKit/CloudKit.h>
NS_ASSUME_NONNULL_BEGIN
extern const double UnknownRetrySeconds;
#interface NSError (CKError)
- (NSDictionary<id, NSError *> * _Nullable)partialErrorsByItemID;
- (CKRecord * _Nullable)ancestorRecord;
- (CKRecord * _Nullable)clientRecord;
- (CKRecord * _Nullable)serverRecord;
- (double)retryAfterSeconds; // returns UnknownRetrySeconds if not available
#end
NS_ASSUME_NONNULL_END
CloudKitExtensions.m
#import "CloudKitExtensions.h"
const double UnknownRetrySeconds = -1;
#implementation NSError (CKError)
- (NSDictionary<id, NSError *> * _Nullable)partialErrorsByItemID {
if ([self.domain isEqualToString:CKErrorDomain] && self.code == CKErrorPartialFailure) {
return self.userInfo[CKPartialErrorsByItemIDKey];
} else {
return nil;
}
}
- (CKRecord * _Nullable)ancestorRecord {
if ([self.domain isEqualToString:CKErrorDomain] && self.code == CKErrorServerRecordChanged) {
return self.userInfo[CKRecordChangedErrorAncestorRecordKey];
} else {
return nil;
}
}
- (CKRecord * _Nullable)clientRecord {
if ([self.domain isEqualToString:CKErrorDomain] && self.code == CKErrorServerRecordChanged) {
return self.userInfo[CKRecordChangedErrorClientRecordKey];
} else {
return nil;
}
}
- (CKRecord * _Nullable)serverRecord {
if ([self.domain isEqualToString:CKErrorDomain] && self.code == CKErrorServerRecordChanged) {
return self.userInfo[CKRecordChangedErrorServerRecordKey];
} else {
return nil;
}
}
- (double)retryAfterSeconds {
if ([self.domain isEqualToString:CKErrorDomain]) {
NSNumber *delayVal = self.userInfo[CKErrorRetryAfterKey];
return delayVal ? [delayVal doubleValue] : UnknownRetrySeconds;
} else {
return UnknownRetrySeconds;
}
}
#end

Cannot access more than one value from function using PromiseKit Swift

TemplateClass.m
+ (AnyPromise *) promisefunctionReturnThreeValus:(NSString *)sampleName {
return [self anotherPromiseFunction:sampleName].then(^(NSMutableDictionary *sampleDict) {
DataArray *data = [DataArray dataArrayFromDict:sampleDict];
PropertyArray *property = [PropertyArray PropertyArrayFromDict:sampleDict];
if ([sampleDict objectForKey:NAME])
{
NameModel *name = [[NameModel alloc]initWithDictionary:[responseDict objectForKey:NAME]];
return (PMKManifold(data,property,name));
}
else
{
return (PMKManifold(data,property,nil));
}
});
}
well i can able to access this from objc using the below code
[TemplateClass promisefunctionReturnThreeValus:#"hello"].then(^(DataArray *data,PropertyArray *property,NameModel *name) {
//Here i can able to access the three values data,property and name
}
But when i try to access this from swift
TemplateClass.promisefunctionReturnThreeValus(sampleName: "hello").then{ data,property,name in
// it show me error " Contextual closure type '(Any?) -> AnyPromise' expects 1 argument, but 3 were used in closure body "
}
i can able to access only data but not the other two
i also tried debug it and print through log it show only the data of DataArray Object
lldb output
<DataArray : 0x1c0631340 count:1 value:{
"id" = 3631;
}
>

How to fetch the key value and apply the condition in keys of dictionary?

in my project i want to fetch the key value from the dictionary along with the condition that if key value is Yes then tick image shown and if the key value is no then cross image shown. i am trying to get the key value but not getting the value.
please help me to solve this problem. i am sharing my snapshot n codes
NSDictionary *strName9 = [productDict objectForKey:#"hand_emb"];
inside StrName9 below dictionary i fetched
"hand_emb" = {
1 = {
key = lengha;
value = yes;
};
2 = {
key = Pyjami;
value = no;
};
};
now what to do after this please help me.
What you are accessing is NSDictionary not NSString so replace it with following snippet which iterates through all the elements of NSDictionary.
Objective C
NSDictionary *dict = productDict[#"hand_emb"];
[dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop)
{
if([obj isKindOfClass:[NSDictionary class]])
{
NSLog(#"key : %#",obj[#"key"]);
NSLog(#"value : %#",obj[#"value"]);
if([obj[#"value"] isEqualToString:#"yes"])
{
// *** Write code to show tick ***
}
else
{
// *** Write code to show cross ***
}
}
}];
Swift
var dict: [NSObject : AnyObject] = productDict["hand_emb"]
dict.enumerateKeysAndObjectsUsingBlock({(key: AnyObject, obj: AnyObject, stop: Bool) -> Void in
if obj.isKindOfClass([NSObject : AnyObject]) {
NSLog("key : %#", obj["key"])
NSLog("value : %#", obj["value"])
if (obj["value"] == "yes") {
// *** Write code to show tick ***
}
else {
// *** Write code to show cross ***
}
}
})

if(objc_getAssociatedObject(self, &Key)) return true for nil object

How can I test that objc_getAssociatedObject is nil? The following says element is not nil but the associated object has never been set before nor been accessed.
static char orderedElementKey = 11;
if (objc_getAssociatedObject(self, &orderedElementKey) != nil)
{
NSLog(#"element is not nil");
return objc_getAssociatedObject(self, &orderedElementKey);
}
NSLog(#"elelement was nil !");
static char orderedElementKey = 11;
//objc_setAssociatedObject(self, &orderedElementKey, #"value", OBJC_ASSOCIATION_RETAIN);
if (objc_getAssociatedObject(self, &orderedElementKey) != nil)
{
NSLog(#"Element: %#", objc_getAssociatedObject(self, &orderedElementKey));
}
else
{
NSLog(#"element nil !");
}
prints "Element nil !" while removing the comment on objc_setAssociatedObject() prints "Element: value". How is your code different?

About NSArray nil crash error

How to avoid this crash error!Crash in main thread Log is
ProcessArray:()
ProcessArray == 0
-[NSNull length]: unrecognized selector sent to instance 0x3c4e1090
my code:
ProcessArray = [EventSheetDetailArray valueForKey:#"Process"];
NSLog(#"ProcessArray:%#",ProcessArray);
if (ProcessArray.count > 0 ) {
NSLog(#"ProcessArray != 0");
[self ProcessJSONDateFormat];
}else{
NSLog(#"ProcessArray == 0");
}
I change judge below!
id value = [EventSheetDetailArray valueForKey:#"Process"];
if ( ![[NSNull null] isEqual:value] )
{
ProcessArray = value;
NSLog(#"1111111");
}else{
NSLog(#"2222222");
}
But always run NSLog(#"1111111") this line!
Regardless of whether any value!
Validate the return value from [EventSheetDetailArray valueForKey:#"Process"]
id value = [EventSheetDetailArray valueForKey:#"Process"];
if ( ![[NSNull null] isEqual:value] )
{
ProcessArray = value;
}
OR
id value = [EventSheetDetailArray valueForKey:#"Process"];
if ( [value isKindOfClass:[NSArray class]] )
{
ProcessArray = value;
}
then you can call NSArray member functions, don't just assume it is NSArray..
The answer is actually quite simple.
if([ProcessArray count] != [NSNULL NULL]) {
if (ProcessArray.count > 0 ) {
NSLog(#"ProcessArray != 0");
[self ProcessJSONDateFormat];
}else {
NSLog(#"ProcessArray == 0");
}
}else {
NSLog(#"NULL...insert some value");
}
Sorry!I found the cause of the error,Because my other code have error, That caused crash main thread -[NSNull length] reason!
If your array is empty then you can't check for count otherwise it will crash.I faced the same issue.Just use "if(!(array==nil))".This is true when your array is empty otherwise it will move to else part.

Resources