3

我在让这个东西工作时遇到了可怕的事情。我花了两天时间阅读 Salesforce 网站上的文档、分布式 SDK 中的示例代码,而且我的头通常都在碰壁。

最令人沮丧的部分是我认为我只是错过了登录屏幕,但我找不到任何可以告诉我如何制作的东西。据我所知,它只是一个指向 SF 登录页面的 UIWebView。

到目前为止,这是我能够弄清楚的:

  1. 将 SDK 添加到我的项目(SalesforceSDK、SalesforceOAuth、RestKit)并链接到Git 自述文件中提到的所有库。
  2. 包含"SFRestAPI.h"在我用来从服务器发送和接收数据的服务器通信类中。
  3. 使用随 SDK 分发的 XCode 模板中的代码调用 SFRestRequest:

    SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:@"SELECT Name FROM User LIMIT 10"];
    [[SFRestAPI sharedInstance] send:request delegate:self];
    
  4. 添加了委托方法:

#pragma mark - Salesforce REST API delegate methods

- (void)request:(SFRestRequest *)request didLoadResponse:(id)jsonResponse
{
    NSLog(@"%@", jsonResponse);
}

- (void)request:(SFRestRequest *)request didFailLoadWithError:(NSError*)error
{
    NSLog(@"%@", error);
}

- (void)requestDidCancelLoad:(SFRestRequest *)request
{
    NSLog(@"%@", request);
}

- (void)requestDidTimeout:(SFRestRequest *)request
{
    NSLog(@"%@", request);
}

5. 在控制台看到这个:

`2012-09-11 10:23:44.128 ClientApp[39697:c07] SFRestAPI::send: <SFRestRequest 0xd4a9cb0 
endpoint: /services/data 
method: GET 
path: /v23.0/query 
queryParams: {
  "q" : "SELECT Name FROM User LIMIT 10"
}`

没有调用 SFRestRequest 的委托方法。

这是没有用的:

使我的应用程序委托 SFNativeRestAppDelegate 的子类

这产生了大约 12 个重复符号错误:

duplicate symbol _OBJC_CLASS_$_SFNativeRestAppDelegate in:
    /Volumes/Wallace/Users/gromitt/Library/Developer/Xcode/DerivedData/ClientApp-bpccblcllzkzvudxtwutuqliagld/Build/Intermediates/ClientApp.build/Debug-iphonesimulator/ClientApp.build/Objects-normal/i386/SFNativeRestAppDelegate.o
    /Volumes/Wallace/Users/gromitt/Documents/Out to Lunch/ iOS Apps/ClientApp/ClientApp/dependencies/SalesforceSDK/libSalesforceSDK.a(SFNativeRestAppDelegate.o)
duplicate symbol _OBJC_IVAR_$_SFNativeRestAppDelegate._authViewController in:
    /Volumes/Wallace/Users/gromitt/Library/Developer/Xcode/DerivedData/ClientApp-bpccblcllzkzvudxtwutuqliagld/Build/Intermediates/ClientApp.build/Debug-iphonesimulator/ClientApp.build/Objects-normal/i386/SFNativeRestAppDelegate.o
    /Volumes/Wallace/Users/gromitt/Documents/Out to Lunch/ iOS Apps/ClientApp/ClientApp/dependencies/SalesforceSDK/libSalesforceSDK.a(SFNativeRestAppDelegate.o)
duplicate symbol _OBJC_IVAR_$_SFNativeRestAppDelegate._viewController in:
    /Volumes/Wallace/Users/gromitt/Library/Developer/Xcode/DerivedData/ClientApp-bpccblcllzkzvudxtwutuqliagld/Build/Intermediates/ClientApp.build/Debug-iphonesimulator/ClientApp.build/Objects-normal/i386/SFNativeRestAppDelegate.o
    /Volumes/Wallace/Users/gromitt/Documents/Out to Lunch/ iOS Apps/ClientApp/ClientApp/dependencies/SalesforceSDK/libSalesforceSDK.a(SFNativeRestAppDelegate.o)
duplicate symbol _OBJC_IVAR_$_SFNativeRestAppDelegate._window in:
    /Volumes/Wallace/Users/gromitt/Library/Developer/Xcode/DerivedData/ClientApp-bpccblcllzkzvudxtwutuqliagld/Build/Intermediates/ClientApp.build/Debug-iphonesimulator/ClientApp.build/Objects-normal/i386/SFNativeRestAppDelegate.o
    /Volumes/Wallace/Users/gromitt/Documents/Out to Lunch/ iOS Apps/ClientApp/ClientApp/dependencies/SalesforceSDK/libSalesforceSDK.a(SFNativeRestAppDelegate.o)
duplicate symbol _OBJC_METACLASS_$_SFNativeRestAppDelegate in:
    /Volumes/Wallace/Users/gromitt/Library/Developer/Xcode/DerivedData/ClientApp-bpccblcllzkzvudxtwutuqliagld/Build/Intermediates/ClientApp.build/Debug-iphonesimulator/ClientApp.build/Objects-normal/i386/SFNativeRestAppDelegate.o
    /Volumes/Wallace/Users/gromitt/Documents/Out to Lunch/ iOS Apps/ClientApp/ClientApp/dependencies/SalesforceSDK/libSalesforceSDK.a(SFNativeRestAppDelegate.o)
duplicate symbol _kDefaultLoginHost in:
    /Volumes/Wallace/Users/gromitt/Library/Developer/Xcode/DerivedData/ClientApp-bpccblcllzkzvudxtwutuqliagld/Build/Intermediates/ClientApp.build/Debug-iphonesimulator/ClientApp.build/Objects-normal/i386/SFNativeRestAppDelegate.o
    /Volumes/Wallace/Users/gromitt/Documents/Out to Lunch/ iOS Apps/ClientApp/ClientApp/dependencies/SalesforceSDK/libSalesforceSDK.a(SFAccountManager.o)
ld: 6 duplicate symbols for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

任何帮助表示赞赏。提前致谢。

4

4 回答 4

3

目标-> 构建设置-> 其他链接器标志

正如在 Rest Kit 教程中指定的那样,我们更改添加了一个名为-ObjC-all_loadnow edit 的标志,它只显示-ObjC,然后应用程序就像一个魅力一样工作。

希望这对那些将来面临这个问题的人有所帮助。

于 2012-11-19T11:36:02.533 回答
2

所以这有点尴尬,但我不希望人们一直试图回答这个问题,所以这里是:

我在我的应用程序中添加了两个 SFNativeAppDelegate.h 副本。我正在查看 SF Mobile SDK 中包含的文件,我一定跳过了它。所以我第二次添加了它,这就是我的问题开始的时候。

我现在可以工作了。这是我所做的:

  1. 使用 SalesForce 项目模板创建本机应用程序。
  2. 在 Finder 中转到您的本机应用程序目录。将dependencies目录复制到现有项目中。
  3. 在 XCode 中打开 Native 项目并将 Settings.bundle 复制到现有项目中。抓住SFAuthorizingViewController.xib你在那里的时间。关闭本机项目。你不再需要它了。
  4. 打开现有应用的 plist 文件。添加一个名为 的键SFDCOAuthLoginHost,并将其设置为 test.salesforce.com 或 login.salesforce.com
  5. 在您现有的应用程序委托中,SFNativeAppDelegate.h包含SFOAuthCoordinator.hSFOAuthCredentials.h
  6. 从此更改接口声明行:

    @interface YourAppDelegate : UIResponder <UIApplicationDelegate>
    

    ...对此:

    @interface YourAppDelegate : SFNativeRestAppDelegate
    
  7. 向 YourAppDelegate 添加两个属性:

    @property (nonatomic, readonly) SFOAuthCoordinator *coordinator;
    @property (nonatomic, retain) SFAuthorizingViewController *authViewController;
    
  8. 转到 YouAppDelegate.m。添加以下行:

    // Fill these in when creating a new Remote Access client on Force.com
    static NSString *const RemoteAccessConsumerKey = @"...yourConsumerKeyGoesHere...";
    static NSString *const OAuthRedirectURI = @"https://test.salesforce.com/services/oauth2/success";
    
  9. 也添加这些方法(授权协调器是我缺少的秘诀)

      #pragma mark - Salesforce.com login helpers
    
        - (NSString*)remoteAccessConsumerKey {
            return RemoteAccessConsumerKey;
        }
    
        - (NSString*)oauthRedirectURI {
            return OAuthRedirectURI;
        }
    
        -(NSString *)oauthLoginDomain {
            return @"test.salesforce.com";
        }
    
        -(void)login{
           [self.coordinator authenticate];
        }
    
        - (void)logout {
            [self.coordinator revokeAuthentication];
            [self.coordinator authenticate];
        }
    
        - (void)loggedIn {
            //provide the Rest API with a reference to the coordinator we used for login
            [[SFRestAPI sharedInstance] setCoordinator:self.coordinator];
            //[[SFRestAPI sharedInstance] setApiVersion:@"24.0"];
        }
    
        - (UIViewController*)newRootViewController {
            NSLog(@"You must override this method in your subclass");
            [self doesNotRecognizeSelector:@selector(newRootViewController)];
            return nil;
        }
    
        - (SFOAuthCoordinator*)coordinator {
            //create a new coordinator if we don't already have one
            if (nil == _coordinator) {
    
                NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];
                NSString *loginDomain = [self oauthLoginDomain];
                NSString *accountIdentifier = [self userAccountIdentifier];
                //here we use the login domain as part of the identifier
                //to distinguish between eg  sandbox and production credentials
                NSString *fullKeychainIdentifier = [NSString stringWithFormat:@"%@-%@-%@",appName,accountIdentifier,loginDomain];
    
    
                SFOAuthCredentials *creds = [[SFOAuthCredentials alloc]
                                             initWithIdentifier:fullKeychainIdentifier
                                             clientId: [self remoteAccessConsumerKey] encrypted:NO ];
    
    
                creds.domain = loginDomain;
                creds.redirectUri = [self oauthRedirectURI];
    
                SFOAuthCoordinator *coord = [[SFOAuthCoordinator alloc] initWithCredentials:creds];
                coord.scopes = [[self class] oauthScopes];
    
                coord.delegate = self;
                _coordinator = coord;
            }
    
            return _coordinator;
        }
    

现在您已准备好使用 SFRestAPI 进行调用。如果用户尚未登录,第一次尝试使用时会出现 SalesForce 身份验证页面。

感谢所有试图提供帮助的人。再次,超级尴尬。

于 2012-09-20T13:18:19.837 回答
0

让我们从SFNativeRestAppDelegate问题开始,因为最终,您希望从该类继承,以便您可以“免费”获得身份验证。

假设您实际上并没有在您开发的应用程序中的某个地方定义 SFNativeRestAppDelegate,看起来您可能存在导致您所看到的冲突的构建状态问题。当我在 DerivedData 文件夹中看到引用的静态库和随机符号之间的重复符号问题时,我通常会采取以下措施:

  1. 关闭 Xcode。
  2. 完全清除 DerivedData(rm -rf ~/Library/Developer/Xcode/DerivedData/*——这是临时构建数据,将在您的下一次 Xcode 构建中重新生成)。
  3. 或者,删除我的应用程序 ( ) 的 Xcode 项目状态数据rm -rf MyProjectDir/MyProjectDir.xcodeproj/project.xcworkspace/ MyProjectDir/MyProjectDir.xcodeproj/xcuserdata/,以确保我的项目状态是干净的。

当您能够从 SFNativeRestAppDelegate 继承时,所有身份验证链接都应该在幕后发生,包括设置[SFRestAPI sharedInstance]对服务进行经过身份验证的调用所需的凭据。看起来无法从 SFNativeRestAppDelegate 继承是您问题的症结所在。完成后,您为 REST API 访问描述的模式看起来是正确的。

如果您有进一步的后续问题,您还可以在 developerforce.com 上咨询移动板上的人员。

于 2012-09-11T19:02:53.270 回答
0

您是否使用 SFRestAPI 委托设置了类?

@interface GSK_SFADataSyncManager : NSObject < SFRestDelegate >

SFRestRequest *request = [[SFRestAPI sharedInstance] requestForQuery:query];
[[SFRestAPI sharedInstance] send:request delegate:self]; 

尝试从构建设置中清除搜索路径...您是否还有其他库?

于 2012-09-19T16:26:23.033 回答