Cloud DB, a service of AppGallery Connect, can keep your device-cloud data in sync, and provide you with unified data models, and various data management APIs. With bolstered data accessibility, reliability, consistency, and security, you can achieve seamless data synchronization between the device and cloud, to build apps that support device-cloud and multi-device data synergy, and ensure that services remain available even when users are offline.
In this codelab, you will create an iOS app that integrates Cloud DB of AppGallery Connect, which can listen on data changes and allows users to delete data.
An iPhone or a simulator for testing
To integrate Cloud DB of AppGallery Connect, you need to complete the following preparations:
Before integrating the Cloud DB SDK, you need to first enable Cloud DB. The procedure is as follows:
You need to integrate the Cloud DB SDK into your Xcode project with CocoaPods.
cd project-directory
pod init
target 'CloudDBDemo' do
pod 'AGConnectAuth'
pod 'AGConnectDatabase'
end
pod install
The following figure shows the result after installation.
You will create an app used for managing books and design its UI according to the following figure.
The layout code for the sign-in page is as follows:
@interface BMLoginView ()
@property (nonatomic, strong) UIImageView *iconImageView;
@property (nonatomic, strong) UILabel *tipLabel;
@property (nonatomic, strong) CAGradientLayer *gradientLayer;
@end
@implementation BMLoginView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self coreGradientLayer];
[self setupUI];
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.iconImageView.frame = CGRectMake((self.frame.size.width - 40) / 2, 20, 40, 40);
self.tipLabel.frame = CGRectMake(0, CGRectGetMaxY(self.iconImageView.frame) + 18, self.frame.size.width, 20);
}
- (void)setupUI {
UIImageView *iconImageView = [[UIImageView alloc] init];
iconImageView.image = [UIImage imageNamed:@"icon_account"];
[self addSubview:iconImageView];
self.iconImageView = iconImageView;
UILabel *tipLabel = [[UILabel alloc] init];
tipLabel.textAlignment = NSTextAlignmentCenter;
tipLabel.textColor = [UIColor darkGrayColor];
tipLabel.text = NSLocalizedString(@"LoginAdminText", nil);
[self addSubview:tipLabel];
self.tipLabel = tipLabel;
self.layer.cornerRadius = 5.f;
self.layer.masksToBounds = YES;
}
- (void)coreGradientLayer {
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.colors = @[(__bridge id)[UIColor grayColor].CGColor, (__bridge id)[UIColor whiteColor].CGColor, (__bridge id)[UIColor grayColor].CGColor];
gradientLayer.startPoint = CGPointMake(0, 0);
gradientLayer.endPoint = CGPointMake(1.0, 0);
gradientLayer.frame = self.bounds;
[self.layer insertSublayer:gradientLayer below:self.layer];
self.gradientLayer = gradientLayer;
}
- (void)loginSuccess {
self.tipLabel.text = @"Administrator";
}
@end
The sample code in this codelab uses the anonymous sign-in mode. Therefore, you need to enable the anonymous authentication mode of Auth Service in AppGallery Connect. Otherwise, sign-in fails.
AGCAuth *agcAuth = [AGCAuth getInstance];
NSLog(@"start agc inanonymously login");
if (agcAuth.currentUser == nil) {
NSLog(@"agc current user is nil");
HMFTask<AGCSignInResult *> *loginTask = agcAuth.signInAnonymously;
[[loginTask addOnSuccessCallback:^(AGCSignInResult *_Nullable result) {
NSLog(@"agc sign inanonymously success.");
self.loginState = YES;
if (complete) {
complete(YES, nil);
}
}] addOnFailureCallback:^(NSError *_Nonnull error) {
NSLog(@"agc sign inanonymously failed. error: %@", error);
if (complete) {
complete(NO, error);
}
}];
} else {
NSLog(@"agc has login.");
self.loginState = YES;
if (complete) {
complete(YES, nil);
}
}
Field | Type | Primary Key | Not Null | Encrypt | Default Value |
id | Integer | √ | √ | – | – |
bookName | String | – | – | – | – |
author | String | – | – | – | – |
price | Double | – | – | – | – |
publisher | String | – | – | – | – |
publishTime | Date | – | – | – | – |
shadowFlag | Boolean | – | – | – | true |
Add the exported Objective-C file to the local development environment. If the file already exists, replace it with the exported one. To ensure successful integration, do not modify the exported Objective-C file.
After adding the object type file, you can develop your app using Cloud DB. Before that, you need to initialize AGConnectCloudDB, and create a Cloud DB zone and an object type. You can check the sample code under each of the following steps:
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[AGCInstance startUp];
return YES;
}
[AGConnectCloudDB initEnvironment:&error];
self.agcConnectCloudDB = [AGConnectCloudDB shareInstance];
[self.agcConnectCloudDB createObjectType:[AGCCloudDBObjectTypeInfoHelper obtainObjectTypeInfo] error:&createError];
NSString *zoneName = @"QuickStartDemo";
AGCCloudDBZoneConfig *zoneConfig = [[AGCCloudDBZoneConfig alloc] initWithZoneName:zoneName syncMode:AGCCloudDBZoneSyncModeCloudCache accessMode:AGCCloudDBZoneAccessModePublic];
zoneConfig.persistence = YES;
__weak typeof(self) weakSelf = self;
[self.agcConnectCloudDB openCloudDBZone2:zoneConfig allowCreate:YES callback:^(AGCCloudDBZone * _Nullable zone, NSError * _Nullable error) {
if (error) {
NSLog(@"created cloud database zone failed with reson:%@", error);
} else {
weakSelf.dbZone = zone;
}
[self.agcConnectCloudDB enableNetwork:zoneName];
}];
You will need to create a listener named listenerHandler to listen on data changes. When data on the cloud changes, the listener is called immediately and a snapshot is generated by the system so that you can obtain data change information through the snapshot. Sample code:
- (void)subscribeSnapshotComplete:(void (^)(NSArray *bookList, NSError *error))complete {
AGCCloudDBQuery *query = [AGCCloudDBQuery where:[BookInfo class]];
[query equalTo:@YES forField:@"shadowFlag"];
[self.dbZone subscribeSnapshotWithQuery:query policy:AGCCloudDBQueryPolicyCloud listener:^(AGCCloudDBSnapshot *_Nullable snapshot, NSError *_Nullable error) {
if (snapshot != nil) {
NSArray *bookList = snapshot.snapshotObjects;
if (complete) {
complete(bookList, nil);
}
} else {
if (complete) {
complete(nil, error);
}
}
}];
}
You can delete a single object or a group of objects using executeDelete. Cloud DB will delete the corresponding data based on the primary key of the passed object without checking whether other attributes of the object are the same as that of the stored data. Sample code:
- (void)deleteAGCDataWithBookID:(NSString *)bookID complete:(void (^)(BOOL success, NSError *error))complete {
AGCCloudDBQuery *query = [AGCCloudDBQuery where:[BookInfo class]];
[query equalTo:@(bookID.integerValue) forField:@"id"];
__weak typeof(self) weakSelf = self;
[self.dbZone executeQuery:query policy:AGCCloudDBQueryPolicyCloud onCompleted:^(AGCCloudDBSnapshot *_Nullable snapshot, NSError *_Nullable error) {
if (snapshot != nil) {
[weakSelf.dbZone executeDelete:snapshot.snapshotObjects onCompleted:^(NSInteger count, NSError *_Nullable error) {
if (error) {
if (complete) {
complete(NO, error);
}
} else {
if (complete) {
complete(YES, nil);
}
}
}];
}
}];
}
Well done. You have successfully created an app that integrates Cloud DB of AppGallery Connect, and learned how to build an app that supports device-cloud data synergy using Cloud DB.