react-native-ar / react-native-arkit

React Native binding for iOS ARKit
MIT License
1.73k stars 139 forks source link

Using ARKit as optional framework and SCNHitTestSearchModeAll #166

Open michbil opened 6 years ago

michbil commented 6 years ago

I'm using ARKit as optional framework for my app. After recent update i've noticed that app started crashing under iOS 10.

dyld: Symbol not found: _SCNHitTestOptionSearchMode

After some research i've found that problem is caused by selector @(SCNHitTestSearchModeAll). SCNHitTestSearchModeAll is available only in iOS 11. If i comment selector, everything starting ok.

- (NSDictionary *)getSceneObjectsHitResult:(const CGPoint)tapPoint  {
    NSDictionary *options = @{
                              SCNHitTestRootNodeKey: self.localOrigin,
                              SCNHitTestSortResultsKey: @(YES),
                              SCNHitTestOptionSearchMode: @(SCNHitTestSearchModeAll)
                              };
    NSArray<SCNHitTestResult *> *results = [_arView hitTest:tapPoint options:options];
    NSMutableArray * resultsMapped = [self mapHitResultsWithSceneResults:results];
    NSDictionary *result = getSceneObjectHitResult(resultsMapped, tapPoint);
    return result;
}

What's the best way to isolate this selector? and make it used only in iOS11?

macrozone commented 6 years ago

you can use this: https://github.com/HippoAR/react-native-arkit/blob/8f872ea40d89e1f4b205a96e12ec93edf0079345/ios/RCTARKit.m#L241

this does a runtime check

just change it to 11.0 or so

michbil commented 6 years ago

I tried


- (NSDictionary *)getSceneObjectsHitResult:(const CGPoint)tapPoint  {
    if (@available(iOS 11.0, *)) {
    NSDictionary *options = @{
                              SCNHitTestRootNodeKey: self.localOrigin,
                              SCNHitTestSortResultsKey: @(YES),
                              SCNHitTestOptionSearchMode: @(SCNHitTestSearchModeAll)
                              };
    NSArray<SCNHitTestResult *> *results = [_arView hitTest:tapPoint options:options];
    NSMutableArray * resultsMapped = [self mapHitResultsWithSceneResults:results];
    NSDictionary *result = getSceneObjectHitResult(resultsMapped, tapPoint);
    return result;
    } else {
        return nil;
    }
}

but no luck, its still crashes at starutp, because once compiled runtime is searching for this symbol. This code is not executed in iOS10 in any way, that's why run time check doesn't help. I think we need to replace @(SCNHitTestSearchModeAll) with some dynamic import statement, but i'm not so good at Objective-C to figure out it myself.

macrozone commented 6 years ago

it should work with this runtime check. Does xcode give you any warning, if you change the target to ios 10 or so?

michbil commented 6 years ago

@macrozone not sure about warnings, but this change solved issue:


  NSDictionary *options = @{
                              SCNHitTestRootNodeKey: self.localOrigin,
                              SCNHitTestSortResultsKey: @(YES),
                              @"SCNHitTestOptionSearchMode": @(SCNHitTestSearchModeAll)
                              };
    NSArray<SCNHitTestResult *> *results = [_arView hitTest:tapPoint options:options];
    NSMutableArray * resultsMapped = [self mapHitResultsWithSceneResults:results];
    NSDictionary *result = getSceneObjectHitResult(resultsMapped, tapPoint);
    return result;```