Customize the OA UI for an iOS app
Using the account and user software development kit (SDK) from IoT Platform, you can customize the user interface (UI) of the Open Account (OA) module for your branded app. These customizations apply to pages such as logon, registration, and password reset.
Prerequisites
Complete the development with the account and user SDK. For more information, see Account and user SDK.Customization items
You can customize the following items of the OA UI for an iOS app.
| App interface diagram | Customizable content |
Modify native elements
|
|
Add new elements
|
Display the phone area code
By default, the logon and registration pages do not show the phone area code. To display an area code, such as +86, perform the following steps.
- Open the ALBBOpenAccountLoginViewController.xib file and select .
- Open the control panel on the right, select Prefix Label, and clear the Hidden check box.
The phone area code is now displayed.
- In the command area, run the pod Update command to see the result.
If content overlaps on the page, change the related constraints in ALBBOpenAccountLoginViewController.xib. You can adjust the layout by showing or hiding other controls.
Change the color of the logon and registration buttons
The logon and registration buttons are light gray by default. To change their color, perform the following steps.
- Register the ALBBOpenAccountLoginViewDelegate delegate.
- Generate and replace the image for the button color.
You can replace the button color by providing an image. The following example shows an extension method that generates an image from a color.
#pragma mark - ALBBOpenAccountLoginViewDelegate - (void)loginViewDidLoad:(ALBBOpenAccountLoginViewController *)viewController { // In this example, the button color is the same for all three states: Normal, Highlighted, and Disabled. To use different colors, pass different images. 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]; } // Category method + (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; }
Change the style of prompt messages
When a business error occurs in the OA module, such as an incorrect password, the app displays a dialog box with a prompt message. To change the style of this dialog box, set a callback.
[ALBBService(ALBBOpenAccountUIService) setHandleBizErrorCallback:^(NSString *errMsg) {
UIAlertController *controller = [UIAlertController alertControllerWithTitle:nil message:errMsg preferredStyle:UIAlertControllerStyleAlert];
[controller addAction:[UIAlertAction actionWithTitle:@"Confirm" style:UIAlertActionStyleDefault handler:nil]];
[[self getCurrentVC] presentViewController:controller animated:true completion:nil];
}];
For the getCurrentVC method, see the getCurrentVC method in the Prompt the user to retrieve their password after too many failed logon attempts section of this document.
Add controls and click events
To add a new click event to the app, such as a click event for a new Button control, perform the following steps.
- Add a Button element in ALBBOpenAccountFindPwdViewController.xib. For example, name the button title 'I am a custom Button'.
- In the xib folder, add an Object control as shown in the following figure.
After the control is added, the result is shown in the following figure.
- Select File’s Owner and click the plus sign (+) next to outletCollection to add a controller. For example, name the controller Object.
- Click and drag from the lower right to the upper left as shown in the figure to associate the Object controller with outletCollection.
Here, outletCollection is an NSArray. You can also refer to the following code to associate multiple Object controls at once.
@property (nonatomic, strong) IBOutletCollection(NSObject)? NSArray *outletCollection; - Create a new class. For example, name it CustomController.
This class inherits from NSObject. Set the Class parameter of the Object controller to CustomController.
- In the CustomController class, add an IBAction response function.
-(IBAction)CustomButtonClick { NSLog(@"Click from Custom Button"); } - Associate the new Object with the new Class, as shown in the following figure.
- Click and drag from the lower right to the upper left as shown in the figure to associate the button's click event with the CustomController class. This selects the CustomButtonClick function as the response function for the button's click event.
- Click the custom button to verify the click event.
If the following log is printed, the click event works correctly. To navigate to another page after the button is clicked, you must implement the navigation logic.
Add custom events to existing controls
To add a custom event to an existing control, such as counting the number of clicks on a control, refer to the following example. It demonstrates how to change the internal logic of the OA module and add a custom event.
// Example of logic for counting button clicks
@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];
// Handle the click counting logic
}
@end
Add logon with an email address
If you want your app to support logon with an email address, you must develop the related features. These include email logon (① in the diagram), email registration (② in the diagram), and forgot email password (③ in the diagram).
- (Optional) Copy the two email-related xib files from the account and user SDK bundle to your project directory.
If you have already developed email-related features, you can skip this step.
The email-related xib files are shown in the following figure. The header file is
#import <ALBBOpenAccountCloud/ALBBOpenAccountSDK.h>.
- Add the email logon method to the app's logon page.
Email logon and phone number logon can share the same logon box. To do this, you can hide the phone area code and add code to determine whether the input is an email address or a phone number. To differentiate them in the UI, you must implement the logic yourself.
- Add the email registration feature.
- Confirm the account and user SDK version.
pod 'AlicloudALBBOpenAccount', '3.4.0.39' // Supported in version 3.4.0.39 and later - Add an Email Registration button to the logon page.
To do this, see the Add controls and click events section in this document.
- Call the controller to display the email registration page.
id uiService = ALBBService(ALBBOpenAccountUIService); [uiService showEmailRegisterInNavigationController:self.navigationController success:nil failure:nil];
- Confirm the account and user SDK version.
- Add the forgot email password feature.
If a user logs on with an email address and forgets the password, they must retrieve it using their email.
- Confirm the account and user SDK version.
pod 'AlicloudALBBOpenAccount', '3.4.0.39' // Supported in version 3.4.0.39 and later - Add a Forgot Email Password button to the logon page.
To do this, see the Add controls and click events section in this document.
- Call the controller to display the forgot password page.
id<ALBBOpenAccountUIService> uiService = ALBBService(ALBBOpenAccountUIService); [uiService showFindPasswordInNavigationController:self.navigationController success:nil failure:nil];
- Confirm the account and user SDK version.
Prompt the user to retrieve their password after too many failed logon attempts
If a user exceeds the maximum number of logon attempts, the app restricts further actions and prompts the user to retrieve their password. If the logon account is a phone number, the user is redirected to the forgot phone password page. If it is an email address, the user is redirected to the forgot email password page.
Two methods are available to display a prompt for logon password retrieval after the logon attempt limit is reached.
- Upgrade the SDK
The latest version of the account and user SDK supports this feature by default. You can enable this feature by upgrading the SDK. No extra steps are needed after the upgrade.
pod 'AlicloudALBBOpenAccount', '3.4.0.39' // Supported in version 3.4.0.39 and later - Add the feature code logic
You can also implement this feature using reflection and a Runtime custom redirection.
// Use the runtime to create a replacement method. Redirect the private method showFindPasswordView of ALBBOpenAccountLoginViewController to the custom method 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); }); } /** Display the password retrieval method sheet */ - (void)findPwdStyleChoose { __weak typeof(self) weakSelf = self; UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Select the password type you want to change" message:nil preferredStyle:UIAlertControllerStyleActionSheet]; UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { }]; UIAlertAction *phoneAction = [UIAlertAction actionWithTitle:@"Forgot phone password?" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { id<ALBBOpenAccountUIService> uiService = ALBBService(ALBBOpenAccountUIService); [uiService showFindPasswordInNavigationController:[weakSelf getCurrentVC].navigationController success:nil failure:nil]; }]; UIAlertAction *emailAction = [UIAlertAction actionWithTitle:@"Forgot email password?" 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; }
More UI customizations
To customize the UI further, such as by modifying more native elements, you can implement them based on the following information.
- The account and user SDK exposes all xib components. Each xib file corresponds to a feature page.
While maintaining the interaction logic of the Alibaba Cloud account, you can modify any of the following xib files to change the page layout, adjust control styles, add new controls, and perform other UI customizations.

- The SDK exposes all ViewControllers and the references to the UI controls of each ViewController.
Take the ALBBOpenAccountLoginViewController UI control for the logon page as an example. The control includes the following elements.
@interface ALBBOpenAccountLoginViewController : ALBBOpenAccountBaseController @property (assign, nonatomic) BOOL isNeedBackButtonHidden; // Reserved for external references @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; // Go to the country list - (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 - The SDK exposes the lifecycle callbacks for each ViewController. This helps you customize the UI controls of the ViewController.
Take ALBBOpenAccountLoginViewDelegate as an example. It is used as follows.
- Set a delegate for the logon interface.
[ALBBService(ALBBOpenAccountUIService) setLoginViewDelegate:self]; - Define the ALBBOpenAccountLoginViewDelegate delegate protocol.
@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 - Use the delegate method to change the content.
- (void)loginViewDidLoad:(ALBBOpenAccountLoginViewController *) viewController{ viewController.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"login" style:UIBarButtonItemStyleDone target:nil action:nil]; }
- Set a delegate for the logon interface.
To customize content other than native elements, refer to the following information.
FAQ
- Question 1
Q: When I use the account and user SDK, the app crashes with the following message.

A: Move the xib directory from ALBBOpenAccountUI.framework to your main project directory.
- Question 2
Q: After the account and user SDK is initialized successfully, I click the logon button in the app, but I am not redirected to the correct page.

A: In the example, the view controller is not added to the navigation stack, so the attempt to push the logon page fails. You can present the logon page in the following way.
[uiService presentLoginViewController:self success:^(ALBBOpenAccountSession *currentSession) { } failure:^(NSError *error) { }]; - Question 3
Q: The SDK API reports an error: Http load fail.
A: Open the info.plist file of your project and configure the App Transport Security (ATS) settings.




