2017.01.15前端
我就問你要是凱迪拉克車主你還會用高德麼?!(默默掏出褲兜裏的地鐵卡看了一眼。。)web
關於這兩點的技術實現後面會講sql
/** 大多狀況下默認的添加方式,直接添加到最頂層的控制器上 * title:彈出登陸框的提示語,如登陸後方可進行評論 * block:用戶被登陸框所阻攔的操做(注意循環引用) */
- (void)transferControlToPortalViewWithTitle:(NSString *)title block:(void(^)())block;
複製代碼
- (void)favoredBtnTapped:(UIButton *)sender {
// 若是是遊客帳戶,就提示用戶進行登陸操做,不然就進行正常的收藏按鈕點擊事件
if ([self.systemAccountManager isGuest]) {
[self.systemVCManager transferControlToPortalViewWithTitle:@"登陸後可進行收藏操做" block:^{
[weakSelf doFavoredAction];
}];
} else {
[self doFavoredAction];
}
}
複製代碼
[fatherVC addChildViewController:portalVC];
[fatherVC.view addSubview:portalVC.view];
複製代碼
此處更正一下,感謝 CZAnchor 提出的方法,這裏是能夠經過 present 方式實現的,代碼以下:小程序
UIViewController *rootVC = [UIApplication sharedApplication].keyWindow.rootViewController;
UIViewController *baseVC = rootVC;
while (baseVC.presentedViewController) {
baseVC = baseVC.presentedViewController;
}
if ([[UIDevice currentDevice].systemVersion floatValue] >= 8.0) {
portalVC.modalPresentationStyle = UIModalPresentationOverCurrentContext;
baseVC.definesPresentationContext = YES;
[baseVC presentViewController:portalVC animated:NO completion:^{}];
} else {
baseVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[baseVC presentViewController:portalVC animated:NO completion:^{}];
}
複製代碼
/** 遷移已下載的文件 */
#warning 關於遊客狀態下下載的內容,須要考慮兩部分:
1. 登陸的正式用戶以前未在本機上登陸過,建立用戶的下載路徑後直接將遊客的下載內容所有遷移過去(若只是登陸過沒有下載內容,就直接所有遷移過去);
2. 登陸的正式有用戶以前在本機登陸過並有下載內容,則須要將兩個路徑下的下載內容合併
- (void)transferDownLoadedFile {
// 獲取下載文件根路徑
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
NSString *libraryDir = [paths objectAtIndex:0];
NSString *rootFilePath = [NSString stringWithFormat:@"%@/%@",libraryDir,@"## 這裏是項目中下載文件的路徑 ##"];
// 分別獲取遊客和正式用戶的下載路徑(方便起見直接使用對應ID做爲路徑名稱)
NSString *guestPath = [NSString stringWithFormat:@"%@/%@", rootFilePath, self.accountManager.guestId];
NSString *userPath = [NSString stringWithFormat:@"%@/%@", rootFilePath, self.accountManager.userId];
// 獲取文件管理器
NSFileManager *manager = [NSFileManager defaultManager];
// 獲取遊客的下載文件數組
NSError *error = nil;
NSArray *guestFilesArr = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:guestPath error:&error];
if (error) {
NSLog(@"contentsOfDirectoryAtPath guestPath:%@", error);
}
// 遍歷遊客的文件
for (NSString *fileName in guestFilesArr) {
// 拼接處 該文件在 遊客狀態 && 正式用戶狀態 的存儲路徑
NSString *guestFileDir = [guestPath stringByAppendingPathComponent:fileName];
NSString *userFileDir = [userPath stringByAppendingPathComponent:fileName];
// 若是正式用戶 下載文件中不包含該文件,就建立一下
if (![manager fileExistsAtPath:userFileDir]) {
[manager createDirectoryAtPath:userFileDir withIntermediateDirectories:YES attributes:nil error:&error];
}
BOOL isDir;
if ([manager fileExistsAtPath:guestFileDir isDirectory:&isDir] && isDir) {
error = nil;
NSArray *childFiles = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:guestFileDir error:&error];
if (error) {
NSLog(@"contentsOfDirectoryAtPath dir:%@", error);
}
// 遍歷該文件夾內子文件,所有遷移到 正式用戶 名下的文件
for (NSString *childFile in childFiles) {
NSString *filePath = [guestFileDir stringByAppendingPathComponent:childFile];
NSString *destPath = [userFileDir stringByAppendingPathComponent:childFile];
error = nil;
[manager moveItemAtPath:filePath toPath:userFileDir error:&error];
if (error) {
DDLogError(@"moveItemAtPath to path error:%@", error);
//若是正式用戶下該文件存在(即用戶以前在本機登陸並下載過該文件)會報錯,那麼就將遊客路徑下的改文件刪除
[manager removeItemAtPath:filePath error:&error];
}
}
}
}
}
複製代碼
// 1. 獲取遊客的 db 文件路徑 guestDataBasePath
// 2. 打開遊客該 db 文件
fmDataQueue = [FMDatabaseQueue databaseQueueWithPath:path];
[fmDataQueue inDatabase:^(FMDatabase *fmDatabase) {
if ([fmDatabase open]) {
[fmDatabase setShouldCacheStatements:YES];
// 建立 SQL 語句
NSString *sqlStr = [NSString stringWithFormat:@"%@%@%@%@%@%@%@",
@"CREATE TABLE IF NOT EXISTS MYVIDEO (VIDEOID TEXT PRIMARY KEY ",
@",videoname TEXT",
@",info TEXT",
@",coverfilename TEXT",
@",urlpath TEXT")"];
BOOL isExecute = [fmDatabase executeUpdate:createStatement];
if (isExecute) {
// 若有必要,可檢查一下表結構是否已升級,此處再也不贅述
} else {
NSLog(@"error occured while creating MYVIDEO table");
}
} else {
NSLog(@"open datebase failed");
}
}
// 3. 查詢遊客帳戶下已下載的 video
// 建立空數組用於存放 video 對象
NSMutableArray *videoArray = [[NSMutableArray alloc] init];
[fmDataQueue inDatabase:^(FMDatabase *fmDatabase) {
// 書寫 sql 語句
NSString *query = [NSString stringWithFormat:@"SELECT videoid,videoname,info,coverfilename,urlpath, FROM MYVIDEO "];
NSString *sqlQuery;
if (wheresql != nil) {
sqlQuery = [NSString stringWithFormat:@"%@%@", query, wheresql];
} else {
sqlQuery = query;
}
// 按時間降序排序
sqlQuery = [sqlQuery stringByAppendingString:@" ORDER BY time DESC "];
FMResultSet *resultSet = [fmDatabase executeQuery:sqlQuery];
if ([fmDatabase hadError]) {
NSLog(@"FMDB Error %d: %@", [fmDatabase lastErrorCode], [fmDatabase lastErrorMessage]);
}
// 取出查詢的結果集
while ([resultSet next]) {
VideoClass *video = [[VideoClass alloc] init];
video.videoId = [resultSet stringForColumn:@"videoid"];
video.videoTitle = [resultSet stringForColumn:@"songname"];
video.videoDescription = [resultSet stringForColumn:@"info"];
video.coverFileName = [resultSet stringForColumn:@"coverfilename"];
video.path = [resultSet stringForColumn:@"urlpath"];
[videoArray addObject:video];
}
[resultSet close];
}];
// 4. 關閉遊客 db
[fmDataQueue inDatabase:^(FMDatabase* fmDatabase) {
if ([fmDatabase close]) {
NSLog(@"close MYVIDEO succes ....");
}
else {
NSLog(@"close MYVIDEO error");
}
}];
[fmDataQueue close];
fmDataQueue = nil;
// 5. 打開 正式用戶 下的 db 文件(獲取遊客 db 路徑後,代碼同上打開 遊客 db)
// 6. 將 遊客 下載的video 數據插入到 正式用戶的 db 中
[fmDataQueue inTransaction:^(FMDatabase *db, BOOL *rollback) {
[array enumerateObjectsUsingBlock:^(VideoClass *video, NSUInteger idx, BOOL * _Nonnull stop) {
[self insertOrUpdateCourse:video withDB:db];
// 建立插入數據的 sql 語句
NSString *insertSql = @"INSERT OR REPLACE INTO MYVIDEO (videoid,videoname,info,coverfilename,urlpath,) VALUES(?,?,?,?,?)";
BOOL result = [fmDatabase executeUpdate:insertSql,
video.videoId,
video.videoTitle,
video.videoDescription,
video.coverFileName,
video.urlPath];
if (!result) {
NSLog(@"操蛋!插入 MYVIDEO data failed");
} else {
NSLog(@"牛逼!Insert MYVIDEO data success, U did it!");
}
}];
}];
// 7. 合併數據庫成功後,根據遊客 db 路徑,刪除 遊客 db 文件
NSFileManager *fm = [NSFileManager defaultManager];
BOOL success = [fm removeItemAtPath:fullPath error:&error];
if (error) {
NSLog(@"怎麼會刪除失敗了,難道我姿式不對?delete file at path error:%@", error);
}
複製代碼
- (void)hidePortalView {
if (self.loginSucessBlock) {
self.loginSucessBlock();
}
UIView animateWithDuration:0.2 animations:^{
self.portalVC.view.alpha = 0;
} completion:^(BOOL finished) {
[self.portalVC.view removeFromSuperview];
[self.portalVC removeFromParentViewController];
}
}
複製代碼
- (void)signInWithAccountBtnTapped:(UIButton *)sender {
SignInController *signInVC = [[SignInController alloc] initWithType:InputViewLogin];
// 設置控制器的 modal 方式爲遵循當前控制器的環境,實現當前是橫(豎)屏就以橫(豎)屏方式modal
signInVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:signInVC animated:YES completion:nil];
}
複製代碼
// 根據狀態欄方向獲得當前頁面橫豎屏信息
UIDeviceOrientation deviceOrientation = (UIDeviceOrientation)[UIApplication sharedApplication].statusBarOrientation;
// 根據橫豎屏狀態,作出相應的 UI 層級調整,並作出相應標記
if (deviceOrientation == UIDeviceOrientationPortrait ||deviceOrientation ==
UIDeviceOrientationPortraitUpsideDown) {
[self doPortraitUIAdjustment];
self.isLandScape = NO;
} else {
[self doLandScapeUIAdjustment];
self.isLandScape = YES;
}
複製代碼
// 在橫屏狀態下,應該能夠隨設備重力感應進行 LandscapeRight 和 LandscapeLeft 兩個方向的自動翻轉
- (BOOL)shouldAutorotate {
if (self.isLandScape) {
return YES;
} else {
return NO;
}
}
// 若是是橫屏狀態,應該支持 LandscapeRight 和 LandscapeLeft 兩個方向,豎屏狀態下只支持 Portrait
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
if (self.isLandScape) {
return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
} else {
return UIInterfaceOrientationMaskPortrait;
}
}
// 默認的方向
-(UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
if (self.isLandScape) {
return UIInterfaceOrientationLandscapeRight;;
} else {
return UIInterfaceOrientationPortrait;
}
}
#warning 至此,橫豎屏適配算是大功告成了
複製代碼
大概的思路就是這些,因爲跟項目相關性比較大,並且代碼實現方式也比較簡單,所以木有 demo,若是有其餘問題歡迎在留言區進行交流api