基于生活物聯(lián)網(wǎng)平臺的賬號及用戶SDK,您可以自定義自有品牌App的開放賬號OA(Open Account)模塊相關(guān)的用戶界面UI(User Interface),主要包括登錄頁面、注冊頁面、密碼重置頁面等。

前提條件

已完成賬號及用戶SDK的開發(fā),詳細操作,請參見賬號及用戶SDK

定制項

iOS App的OA UI定制項如下。

App界面圖示 可定制內(nèi)容
圖示 修改原生元素
  • 顯示手機區(qū)號(圖示中②)
  • 修改登錄和注冊按鈕的顏色(圖示中③)
  • 修改失敗提示樣式(圖示中④)
新增元素
  • 新增控件和單擊事件
  • 現(xiàn)有控件增加自定義的事件
  • 新增郵箱登錄方式(圖示中①)
  • 登錄密碼輸入次數(shù)超限后提示找回密碼(圖示中⑤)

顯示手機區(qū)號

登錄和注冊頁面中默認不顯示手機區(qū)號,如果您需要顯示手機區(qū)號,如+86,請根據(jù)以下步驟來操作。

  1. 打開ALBBOpenAccountLoginViewController.xib文件,選擇View > Wrapper View > Form View > Username View > Prefix Label
  2. 打開右側(cè)控制面板,選擇Prefix Label,并取消選中Hidden復(fù)選框。
    此時即可顯示手機區(qū)號。顯示區(qū)號
  3. 在命令區(qū)域,執(zhí)行pod Update命令,查看顯示效果。
    如果頁面中出現(xiàn)內(nèi)容重疊,請在ALBBOpenAccountLoginViewController.xib中更改相關(guān)約束,通過顯示和隱藏其他控件來調(diào)節(jié)顯示效果。

修改登錄和注冊按鈕的顏色

App的登錄和注冊按鈕默認為淺灰色,如果您需要修改App登錄和注冊按鈕的顏色,請根據(jù)以下步驟來操作。

  1. 注冊ALBBOpenAccountLoginViewDelegate相關(guān)代理。
  2. 生成并替換按鈕顏色的圖片。

    您可以通過放置圖片的方法來替換按鈕顏色,以下為您提供顏色生成圖片的擴展方法。

    #pragma mark - ALBBOpenAccountLoginViewDelegate
    - (void)loginViewDidLoad:(ALBBOpenAccountLoginViewController *)viewController {
        // 本示例中按鈕的三種狀態(tài)(正常、高亮、禁用)的顏色一致,您如需不一致,傳入不同圖片即可
        UIImage *bgImage = [UIImage ims_imageWithColor:[UIColor whiteColor];
        [viewController.submitButton setBackgroundImage:bgImage forState:UIControlStateNormal];
        [viewController.submitButton setBackgroundImage:bgImage forState:UIControlStateHighlighted];
        [viewController.submitButton setBackgroundImage:bgImage forState:UIControlStateDisabled];
    }
    
    // 分類方法
    + (UIImage *)ims_imageWithColor:(UIColor *)color {
      CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f);
      UIGraphicsBeginImageContext(rect.size);
      CGContextRef context = UIGraphicsGetCurrentContext();
      CGContextSetFillColorWithColor(context, [color CGColor]);
      CGContextFillRect(context, rect);
      UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
      UIGraphicsEndImageContext();
      return image;
    }

修改提示信息樣式

當OA模塊發(fā)生業(yè)務(wù)錯誤(如密碼錯誤)時,App會彈出相關(guān)提示信息的對話框。如果您需要修改該提示對話框的樣式,可以通過設(shè)置回調(diào)來實現(xiàn)。

[ALBBService(ALBBOpenAccountUIService) setHandleBizErrorCallback:^(NSString *errMsg) {
     UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:errMsg preferredStyle:UIAlertControllerStyleAlert];
    [controller addAction:[UIAlertAction actionWithTitle:@"確認" style:UIAlertActionStyleDefault handler:nil]];
    [[self getCurrentVC] presentViewController:controller animated:true completion:nil];
}];

其中,getCurrentVC方法可參見本文檔登錄密碼輸入超限后提示找回密碼getCurrentVC的方法。

新增控件和單擊事件

當您需要在App中增加新的單擊事件時,例如新增一個Button控件的單擊事件,您可以根據(jù)以下步驟來操作。

  1. ALBBOpenAccountFindPwdViewController.xib中添加一個Button元素。例如,Button標題命名為:我是自定義的Button。
  2. xib目錄中添加一個如圖所示的Object控件。
    添加object

    添加成功后,如下圖所示。

    添加結(jié)果顯示
  3. 選擇File’s Owner,并單擊outletCollection對應(yīng)的加號(+),添加一個控制器,例如命名為Object。
  4. 按住鼠標從如圖所示的右下角拖至左上角,關(guān)聯(lián)Object控制器和outletCollection。
    連接

    此處outletCollection是一個NSArray,您也參照以下代碼,一次關(guān)聯(lián)多個Object控件。

    @property (nonatomic, strong) IBOutletCollection(NSObject)? NSArray *outletCollection;
  5. 新建一個類,例如命名為CustomController。
    該類繼承NSObject,設(shè)置Object控制器的Class參數(shù)值為CustomController創(chuàng)建類
  6. 在CustomController類中添加一個響應(yīng)函數(shù),例如命名為IBAction。
    -(IBAction)CustomButtonClick {
        NSLog(@"來自 Custom Button 的Click");
    }
  7. 將新建的Object與新建的Class相關(guān)聯(lián),如下圖所示。
    關(guān)聯(lián)操作
  8. 按住鼠標從如圖所示的右下角拖至左上角,關(guān)聯(lián)Button的單擊事件和CustomController類,即選擇CustomButtonClick函數(shù)作為Button單擊事件的響應(yīng)函數(shù)。
    關(guān)聯(lián)事件
  9. 單擊CustomController對應(yīng)的Button,驗證單擊事件。

    如果打印出以下日志則表示單擊事件可正常使用。如果您需要單擊Button后跳轉(zhuǎn)其他頁面,可自行實現(xiàn)。

    日志

現(xiàn)有控件增加自定義事件

當您需要對現(xiàn)有控件增加自定義事件時,例如統(tǒng)計某控件的單擊次數(shù)等,您可以參考以下示例方法來更改OA內(nèi)部邏輯并增加自定義事件。

說明 通常不建議您通過Runtime方式來修改非主動暴露的業(yè)務(wù)邏輯,建議您優(yōu)先聯(lián)系技術(shù)支持,確認是否有新版本SDK支持該功能,或者提交該功能的需求申請。
//以統(tǒng)計按鈕單擊次數(shù)的邏輯為例
@implementation ALBBOpenAccountSetPwdViewController (aspect)

+ (void)load {
    Method originalMethod = class_getInstanceMethod(self, @selector(submitPassword));
    Method newMethod = class_getInstanceMethod(self, @selector(newSubmitPassword));

    BOOL addMethod = class_addMethod(self, @selector(submitPassword), method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
    if (addMethod) {
        class_replaceMethod(self, @selector(newSubmitPassword), method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
    } else {
        method_exchangeImplementations(originalMethod, newMethod);
    }
}

- (void)newSubmitPassword {

    [self newSubmitPassword];
   //處理統(tǒng)計次數(shù)邏輯

}

@end

新增郵箱登錄方式

如果您需要App支持郵箱方式登錄,您需要開發(fā)郵箱相關(guān)的功能,包括郵箱登錄(圖示中①)、郵箱注冊(圖示中②)、忘記郵箱密碼(圖示中③)等。

郵箱登錄方式
  1. (可選)從賬號及用戶SDK的Bundle中拷貝郵箱相關(guān)的兩個xib文件到工程目錄下。

    如果您之前開發(fā)過郵箱相關(guān)的功能,可直接跳過該步驟的操作。

    郵箱相關(guān)的xib文件如下圖所示,其中頭文件為#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>

    郵箱的xia文件
  2. 在App登錄頁面增加郵箱登錄的方式。

    郵箱登錄與手機號登錄可以共用同一個登錄框,此時您只需要將手機區(qū)號隱藏,并在代碼中判斷輸入的內(nèi)容是郵箱還是手機號即可。如果您需要在UI上區(qū)分,可自行實現(xiàn)。

  3. 新增郵箱注冊功能。
    1. 確認賬號及用戶SDK版本。
      pod 'AlicloudALBBOpenAccount', '3.4.0.39' //3.4.0.39及以上版本都支持
    2. 在登錄頁面增加郵箱注冊按鈕。
      請參見本文檔中新增控件和單擊事件來實現(xiàn)。
    3. 調(diào)用控制器彈出郵箱注冊頁面。
      id uiService = ALBBService(ALBBOpenAccountUIService);
      [uiService showEmailRegisterInNavigationController:self.navigationController success:nil failure:nil];
  4. 新增忘記郵箱密碼功能。
    通過郵箱方式登錄App時,如果忘記了郵箱注冊的密碼,需要通過郵箱找回密碼。
    1. 確認賬號及用戶SDK版本。
      pod 'AlicloudALBBOpenAccount', '3.4.0.39' //3.4.0.39及以上版本都支持
    2. 在登錄頁面增加忘記郵箱密碼按鈕。
      請參見本文檔中新增控件和單擊事件來實現(xiàn)。
    3. 調(diào)用控制器彈出忘記密碼頁面。
      id<ALBBOpenAccountUIService> uiService = ALBBService(ALBBOpenAccountUIService);
      [uiService showFindPasswordInNavigationController:self.navigationController success:nil failure:nil];

登錄密碼輸入次數(shù)超限后提示找回密碼

登錄App時,如果輸入登錄密碼的次數(shù)達到上限,App會限制繼續(xù)操作,并提示找回密碼。登錄賬號如果是手機號碼則跳轉(zhuǎn)至手機忘記密碼頁面;如果是郵箱則跳轉(zhuǎn)至郵箱忘記密碼頁面。

登錄超次后找回密碼

有兩種方案可實現(xiàn)登錄密碼輸入次數(shù)超限后提示找回密碼,您任選一種即可。

說明 如果您同時添加了以下兩種方案,則僅生效第二種方案。運行App后,添加功能代碼邏輯的方式(即反射+Runtime自定義跳轉(zhuǎn)的方式)會修改SDK中的業(yè)務(wù)邏輯。
  • 升級SDK

    最新版本賬號及用戶SDK中已默認支持該能力,您可以通過升級SDK來實現(xiàn)該功能。完成SDK升級后,您無需額外操作。

    pod 'AlicloudALBBOpenAccount', '3.4.0.39'  //3.4.0.39及以上版本都支持
  • 添加該功能代碼邏輯

    您還可以通過反射+Runtime自定義跳轉(zhuǎn)的方式來實現(xiàn)該功能。

    // 通過runtime方式做一個方法來替換,將ALBBOpenAccountLoginViewController的私有方法showFindPasswordView轉(zhuǎn)到自己定義的方法findPwdStyleChoose中
    + (void)load {
        static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            Method findPwdMethod = class_getInstanceMethod([self class], @selector(findPwdStyleChoose));
            IMP findPwdNewImp = method_getImplementation(findPwdMethod);
            const char * typeEncodeing = method_getTypeEncoding(findPwdMethod);
            class_replaceMethod([ALBBOpenAccountLoginViewController class], NSSelectorFromString(@"showFindPasswordView"), findPwdNewImp, typeEncodeing);
        });
    }
    
    /**
     顯示找回密碼方式sheet
     */
    - (void)findPwdStyleChoose {
        __weak typeof(self) weakSelf = self;
        UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"請選擇你要修改的密碼類型" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
        UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
        }];
    
        UIAlertAction *phoneAction = [UIAlertAction actionWithTitle:@"忘記手機密碼?" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
            id<ALBBOpenAccountUIService> uiService = ALBBService(ALBBOpenAccountUIService);
            [uiService showFindPasswordInNavigationController:[weakSelf getCurrentVC].navigationController success:nil failure:nil];
        }];
    
        UIAlertAction *emailAction = [UIAlertAction actionWithTitle:@"忘記郵箱密碼?" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
            id<ALBBOpenAccountUIService> uiService = ALBBService(ALBBOpenAccountUIService);
            [uiService showEmailFindPasswordInNavigationController:[self getCurrentVC].navigationController success:nil failure:nil];
        }];
        [alert addAction:cancelAction];
        [alert addAction:phoneAction];
        [alert addAction:emailAction];
        [[self getCurrentVC] presentViewController:alert animated:YES completion:nil];
    }
    
    - (UIViewController *)getCurrentVC {
        UIViewController *result = nil;
    
        UIWindow *window = [[UIApplication sharedApplication] keyWindow];
        if (window.windowLevel != UIWindowLevelNormal) {
            NSArray *windows = [[UIApplication sharedApplication] windows];
            for (UIWindow *temp in windows) {
                if (temp.windowLevel == UIWindowLevelNormal) {
                    window = temp;
                    break;
                }
            }
        }
    
        result = window.rootViewController;
    
        while (result.presentedViewController) {
            result = result.presentedViewController;
        }
    
        if ([result isKindOfClass:[UITabBarController class]]) {
            result = [(UITabBarController *)result selectedViewController];
        }
    
        if ([result isKindOfClass:[UINavigationController class]]) {
            result = [(UINavigationController *)result visibleViewController];
        }
        return result;
    }

更多UI定制

如果您還需定制更多的UI,例如修改更多原生元素,您可以根據(jù)以下內(nèi)容自行實現(xiàn)。

  • 賬號及用戶SDK開放了所有xib組件,每個xib對應(yīng)相應(yīng)的功能頁。

    您可以在保證云賬號交互邏輯的基礎(chǔ)上,通過修改以下任意xib文件,實現(xiàn)改變頁面布局、調(diào)整控件樣式、新增控件等一系列自定義UI的操作。

    xib目錄
  • SDK開放了所有ViewController,以及每一個ViewController的UI控件的引用。

    以登錄頁面對應(yīng)的UI控件ALBBOpenAccountLoginViewController為例,控件中包括以下元素。

    @interface ALBBOpenAccountLoginViewController : ALBBOpenAccountBaseController
    @property (assign, nonatomic) BOOL isNeedBackButtonHidden;
    
    //預(yù)留的外掛引用
    @property (nonatomic, strong) IBOutletCollection(NSObject)  NSArray *outletCollection;
    
    // wrapper
    @property (weak, nonatomic) IBOutlet ALBBOpenAccountWrapperView *wrapperView;
    // form
    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightOfFormView;
    
    //locale
    @property (weak, nonatomic) IBOutlet UILabel *prefixLabel;
    @property (weak, nonatomic) IBOutlet UIButton *prefixIcon;
    // username
    @property (weak, nonatomic) IBOutlet UILabel *usernameLabel;
    @property (weak, nonatomic) IBOutlet UITextField *usernameField;
    @property (weak, nonatomic) IBOutlet UIButton *historyButton;
    @property (weak, nonatomic) IBOutlet UITableView *historyView;
    @property (weak, nonatomic) IBOutlet NSLayoutConstraint *heightOfHistoryView;
    // password
    @property (weak, nonatomic) IBOutlet UIView *passwordView;
    @property (weak, nonatomic) IBOutlet UILabel *passwordLabel;
    @property (weak, nonatomic) IBOutlet UITextField *passwordField;
    @property (weak, nonatomic) IBOutlet UIButton *visibleButton;
    
    // control
    @property (weak, nonatomic) IBOutlet UIButton *submitButton;
    
    
    - (IBAction)submitLogin;
    // 前往國家列表
    - (IBAction)prefixNumberChoose:(id)sender;
    
    // sso
    - (IBAction)taobaoSSO:(id)sender;
    #ifdef WECHAT_SSO
    - (IBAction)weChatSSO:(id)sender;
    #endif
    - (IBAction)weiBoSSO:(id)sender;
    - (IBAction)qqSSO:(id)sender;
    
    @property (weak, nonatomic) IBOutlet UIButton *registerLinkBtn;
    @property (weak, nonatomic) IBOutlet UIButton *findPwdLinkBtn;
    - (IBAction)showRegisterView;
    - (IBAction)showFindPasswordView;
    @end
  • SDK開放了每一個ViewController的生命周期回調(diào),便于您定制ViewController的UI控件。

    以ALBBOpenAccountLoginViewDelegate為例,使用方式如下。

    1. 設(shè)置一個登錄界面的代理。
      [ALBBService(ALBBOpenAccountUIService) setLoginViewDelegate:self];
    2. 設(shè)置ALBBOpenAccountLoginViewDelegate代理方式。
      @protocol ALBBOpenAccountLoginViewDelegate <NSObject>
      
      @optional
      - (void)loginViewDidLoad:(ALBBOpenAccountLoginViewController *) viewController;
      - (void)loginViewWillAppear:(ALBBOpenAccountLoginViewController *) viewController;
      - (void)loginViewDidAppear:(ALBBOpenAccountLoginViewController *) viewController;
      - (void)loginViewWillDisappear;
      - (void)loginViewDidDisappear;
      
      - (void)loginViewWillLayoutSubviews:(ALBBOpenAccountLoginViewController *) viewController;
      - (void)loginViewDidLayoutSubviews:(ALBBOpenAccountLoginViewController *) viewController;
      
      @end
    3. 使用代理方法改變內(nèi)容。
      - (void)loginViewDidLoad:(ALBBOpenAccountLoginViewController *) viewController{
      viewController.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc]   initWithTitle:@"login" style:UIBarButtonItemStyleDone target:nil action:nil];
      }

如果您還需定制除原生元素以外的內(nèi)容,可以參考以下信息來實現(xiàn)。

常見問題

  • 問題一

    Q:使用賬號及用戶SDK時,Crash出現(xiàn)以下提示。

    Crash提示

    A:將ALBBOpenAccountUI.framework中的xib目錄放置到主工程目錄下即可。

  • 問題二

    Q:賬號及用戶SDK初始化成功后,單擊App登錄按鈕,沒有成功跳轉(zhuǎn)至相應(yīng)的頁面。

    登錄跳轉(zhuǎn)失敗提示

    A:示例中VC未加入到導(dǎo)航棧,所以推送登錄頁面會失敗。可以用如下方式推出登錄頁面。

    [uiService presentLoginViewController:self success:^(ALBBOpenAccountSession *currentSession) {
    
            } failure:^(NSError *error) {
    
            }];
  • 問題三

    Q:SDK接口報錯,提示:Http load fail。

    A:打開工程的info.plist文件,設(shè)置ATS配置即可。

    設(shè)置ATS