iOS小项目-云知道(天气预报)

引子

之前曾经做过一个渣渣天气预报,链接,无论是UI搭建还是业务逻辑都非常感人……总结就是一个字:“丑”,不久前看到 ManoBoo大大的 壁纸天气,有种眼前一亮的感觉,再回想自己做第一个天气预报项目时候种种别出心裁 瞎搞 的设计方案,一瞬间羞愤欲死 (但是很快就缓过来了),决定临摹一个出来。


预览
iOS小项目-云知道(天气预报)_第1张图片
gif-1.gif
gif-2.gif
gif-3.gif
gif-4.gif
gif-5.gif
gif-6.gif

懒癌发作……先不码字了,挖个坑先


初始界面

1 . 首先在进入App的时候进行判断,看是不是第一次加载App,如果是的话,需要从初始化一下热门城市的配置。

// 在AppDelegate中执行这段代码,判断并初始化热门城市列表
- (void)setInitData{
    BOOL isFirstStart;
    id obj = [[NSUserDefaults standardUserDefaults] objectForKey:IsFirstStartKey];
    if (obj == nil) {
        isFirstStart = YES;
    }else {
        isFirstStart = NO;
    }
    
    if (isFirstStart ) {
        [[CKCityManager shareInstance] setupHotCities];//配置热门城市列表
        isFirstStart = NO;
        // 存储YES至 对应的Key
        [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:isFirstStart] forKey:IsFirstStartKey];
    }
}


CKCityManager 是一个全局的单例类,用来储存及操作之后的城市选择

包含下面几个方法,基本能够囊括项目中的需求。
// 初始化
+ (instancetype)shareInstance;

/** 是否已有选择的城市 */
- (BOOL)hasSelectedCity;

/** 初始化热门城市(8个) */
- (void)setupHotCities;

/** 返回热门城市列表 */
- (NSArray *)getHotCities;

/** 存储选定的城市 */
- (void)saveCityWithModel:(CKCityModel *)model;

/** 返回已经选定的城市 */
- (NSArray *)savedCities;

代码相对来说都不算太复杂,都是一些根据设定好的key值,再使用NSUserDefaults 读取相关的Key值之类的操作。

2 . 根控制器 CKHomeWeatherController

这个页面用来展示全局 (已选择) 城市的天气概况,仿照ManoBoo大大的思想,隐藏掉NavigationBar (只是隐藏,实际上仍然存在),取消使用tabbar进行页面跳转操作,改用一个动画效果弹出的按钮来搞定基本的页面操作。

iOS小项目-云知道(天气预报)_第2张图片
页面层级预览.png

底部那4个一排就是按钮组,最后面蓝色的指纹按钮是basicOperationButton(BOB),另外三个是功能性按钮,正常为隐藏状态,BOB被点击时,其会弹出并呈扇形排布在BOB上方,再次点击后隐藏。

具体执行起来与普通的按钮状态取反很相似,动画效果一开始比较懵,理清楚思路后发现也不算很难。

- (void)showButtonsArray {
    
    WeakSelf;
    if (_showOperationButtons) {
        _showOperationButtons = NO;
        [weakSelf.operationBtnArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            UIButton *btn = (UIButton *)obj;
            CGRect frame = weakSelf.operationButton.frame;
            float duration = 0.0;
            [UIView animateWithDuration:0.4 delay:duration options:UIViewAnimationOptionCurveEaseInOut animations:^{
                btn.alpha = 0.0;
                btn.frame = frame;
                btn.transform = CGAffineTransformMakeRotation(M_PI);
            } completion:^(BOOL finished) {
                
            }];
        }];
    }else{
        _showOperationButtons = YES;
        [weakSelf.operationBtnArray enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            UIButton *button = (UIButton *)obj;
            //更改后 frame
            CGRect frame = button.frame;
            frame.size.width = frame.size.height = 44;
            //延时
            float duration = 0.0;
            
            switch (idx) {
                case 0: {
                    frame.origin.x -= 50 * sqrt(2);
                    frame.origin.y -= 50 * sqrt(2);
                }
                    break;
                case 1: {
                    frame.origin.y -= 100;
                    duration = 0.1;
                }
                    break;
                case 2: {
                    frame.origin.x += 50 * sqrt(2);
                    frame.origin.y -= 50 * sqrt(2);
                    duration = 0.25;
                }
                    break;
            }
            // 按延迟 将三个button 按顺序依次弹出
            [UIView animateWithDuration:0.4 delay:duration options:UIViewAnimationOptionCurveEaseInOut animations:^{
                button.alpha = 1.0;
                button.frame = frame;
                button.transform = CGAffineTransformMakeRotation(M_PI * 2);
            } completion:nil];
        }];
    }
}

// 具体按钮点击的Push操作 
- (void)aboutMe {
    [self showButtonsArray]; // 也调用一次上面的方法,达到隐藏按钮队列的作用
    AboutMeController *meVc = [[AboutMeController alloc] init];
    [self.navigationController pushViewController:meVc
                                         animated:YES];
}

// 老实说刚读源码的时候看着sqrt一脸懵逼,后来发现原始就是开平方……感叹一下早期学的都还给老师了
// 突然想到自己的Note3,手写笔抽出来的时候也会显示出一个类似的扇形操作界面。

因为只是一个将按钮显示出来的动画,不存在什么交叉target,相对来说比较独立。

3 . nullDataView

如果在进入根控制器后解析不到selectedCities,则加载nullDataView到界面。

// 设置无数据时显示的界面
- (void)setupNullDataView {
    if (![[CKCityManager shareInstance] hasSelectedCity]) {
        if (!_nullView) {
            _nullView = [[NullDataView alloc] initWithFrame:[UIScreen mainScreen].bounds];
            [self.view addSubview:_nullView];
        }
        _nullView.hidden = NO;
        _tableView.hidden = YES;
    } else { // 如果不是第一次进入App,显示tableView 并加载数据
        _nullView.hidden = YES;
        _tableView.hidden = NO;
        [self loadNewData];
    }
}

// 一开始思路有问题……导致选取了城市后pop页面回来仍然显示nullDataView 

秉承的思想是 viewDidLoad和viewWillAppear 这俩方法,
viewDidLoad中只负责addSubView ,具体的setup loadNewData ,刷新页面都放在viewWillAppear 中解决 。


懒癌发作……睡一觉再说

你可能感兴趣的:(iOS小项目-云知道(天气预报))