【问题标题】:Can anyone help me setting up the Salesforce Mobile SDK for iOS?谁能帮我设置适用于 iOS 的 Salesforce 移动 SDK?
【发布时间】:2012-09-11 14:41:19
【问题描述】:

让这个东西工作起来我真的很难过。我花了两天时间阅读了 Salesforce 网站上的文档、分布式 SDK 中的示例代码,而且我的头通常都在碰壁。

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

以下是我目前能够弄清楚的:

  1. 将 SDK 添加到我的项目(SalesforceSDK、SalesforceOAuth、RestKit)并链接到Git readme 中提到的所有库。
  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)

感谢任何帮助。提前致谢。

【问题讨论】:

    标签: ios mobile sdk salesforce


    【解决方案1】:

    Targets-> build Settings —> 其他 Linker Flags

    按照 Rest Kit 教程中的说明,我们添加了一个名为 -ObjC-all_load 的标志,现在将其编辑为仅显示 -ObjC,然后应用程序就像一个魅力一样工作。

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

    【讨论】:

      【解决方案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.hSFOAuthCoordinator.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 身份验证页面。

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

      【讨论】:

        【解决方案3】:

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

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

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

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

        如果您有进一步的后续问题,您还可以通过 developerforce.com 的 the Mobile board 向人们咨询。

        【讨论】:

        • 感谢您的回复,但这并不能消除错误。我关闭了 XCode 并在您推荐的两个地方清空了 DerivedData。我还从模拟器中删除了该应用程序以进行全新安装。没有快乐。
        【解决方案4】:

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

        @interface GSK_SFADataSyncManager : NSObject

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

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-12-16
          • 1970-01-01
          • 2020-05-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-22
          相关资源
          最近更新 更多