年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 17980|回复: 34

[新浪微博] ios实战开发之仿新浪微博(第一讲:新特性展示)

[复制链接]
  • TA的每日心情
    奋斗
    2022-12-13 21:26
  • 签到天数: 371 天

    [LV.9]以坛为家II

    发表于 2014-4-11 23:06:54 | 显示全部楼层 |阅读模式
    本帖最后由 Sian 于 2015-7-13 09:12 编辑

    1、效果展示



    2、设计说明
    2.1 规范文件结构,总体思想:将类单独创建文件夹分类管理,图片、音频等资源分类管理,如图:
    001.png
    002.png

    2.2 ios程序运行过程解释,参考:ios程序运行过程解析
    2.3 新特性展示思路,参考:ios实战开发之UIScrollView图片浏览器
    2.4 细节加工
    2.4.1 创建UIImage的Category,新创建一个方法来自适应iphone不同尺寸屏幕的图片展示
    2.4.2 创建全局宏,抽取常用代码及变量的统一定义与修改,编写一个Common.h文件

    3、关键代码
    SAAppDelegate.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  SAAppDelegate.h
    //  SianWeibo
    //
    //  Created by yusian on 14-4-10.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @class SAViewController;
    
    @interface SAAppDelegate : UIResponder <UIApplicationDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    
    @property (strong, nonatomic) SAViewController *viewController;
    
    @end
    

    SAAppDelegate.m
    [Objective-C] 纯文本查看 复制代码
    //
    //  SAAppDelegate.m
    //  SianWeibo
    //
    //  Created by yusian on 14-4-10.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //
    
    #import "SAAppDelegate.h"
    #import "SANewfeatureController.h"
    #import "SAMainController.h"
    
    @implementation SAAppDelegate
    
    #pragma mark 应用程序加载完毕后调用
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // 创建一个窗口
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        
        /*****************************************************************/
        
        // 版本号在info.plist中的key值
        NSString *key = (NSString *)kCFBundleVersionKey;
        
        // 从info.plist中取出当前版本号
        NSString *version = [NSBundle mainBundle].infoDictionary[key];
        
        // 从沙盒中取出上次存储的版本号
        NSString *saveVersion = [[NSUserDefaults standardUserDefaults] objectForKey:key];
        
        // 判断是否为第一次使用该版本,如果是则进入新特性展示,否则直接进入微博主界面
        if ([version isEqualToString:saveVersion]) {
            // NSLog(@"使用过的版本");
            self.window.rootViewController = [[SAMainController alloc] init];       // 非第一次使用该版本直接进入主界面视图
        
        } else {
            [[NSUserDefaults standardUserDefaults] setObject:version forKey:key];   // 将新的版本号写入到沙盒中
            [[NSUserDefaults standardUserDefaults] synchronize];                    // 立即同步
    
            // NSLog(@"第一次使用该版本");
            self.window.rootViewController = [[SANewfeatureController alloc] init]; // 第一次使用该版本进入新特性视图
        }
        
        /*****************************************************************/
        
        // 将窗口设置为显示,keyWindow为主窗口,只有主窗口才能与用户交互
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    #pragma mark 程序被挂起时调用
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
        // NSLog(@"程序被挂起");
    }
    
    #pragma mark 程序进入后台时调用
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
        // NSLog(@"程序进入后台");
    }
    
    #pragma mark 应用再次进入前台时调用
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
        // NSLog(@"程序进入前台");
    }
    
    #pragma mark 处于活动状态时调用
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        // NSLog(@"程序被激活");
    }
    
    #pragma mark 程序被终结时调用
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
        // NSLog(@"程序被终结时调用");
    }
    
    @end
    

    SANewfeatureController.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  SANewfeatureController.h
    //  SianWeibo
    //
    //  Created by yusian on 14-4-10.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface SANewfeatureController : UIViewController
    
    @end
    

    SANewfeatureController.m
    [Objective-C] 纯文本查看 复制代码
    //
    //  SANewfeatureController.m
    //  SianWeibo
    //
    //  Created by yusian on 14-4-10.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //  版本新特性界面
    
    #import "SANewfeatureController.h"
    #import "UIImage+SA568h.h"
    #import "SAMainController.h"
    #define kPicCount 4
    #define kPageControlW 150
    
    @interface SANewfeatureController () <UIScrollViewDelegate>
    {
        UIPageControl   *_pageControl;
        CGSize          _size;
    }
    
    @end
    
    @implementation SANewfeatureController
    
    #pragma mark 自定义view
    - (void)loadView
    {
        // self.view直接使用UIImageView设置ImageView尺寸与位置
        UIImageView *imageView = [[UIImageView alloc] init];
        imageView.image = [UIImage fullScreenImage:@"new_feature_background.png"];
        imageView.frame = [UIScreen mainScreen].bounds;
        imageView.userInteractionEnabled = YES;                 // 开启当前控件与用户交互
        self.view = imageView;                                  // 基本View设置为新创建ImageView
    }
    
    #pragma mark 视图加载完毕后调用
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        _size = [UIScreen mainScreen].bounds.size;              // 全局定义一个屏幕宽高值供后续使用
        UIScrollView *scrollView = [self creatScrollView];      // 创建一个scrollView
        UIPageControl *pageControl = [self creatPageControl];   // 创建一个pageControl
        
        [self.view addSubview:pageControl];                     // pageControl加载到视图
        [self.view addSubview:scrollView];                      // scrollView加载到视图
    }
    
    #pragma mark - 控件添加方法
    #pragma mark 添加scrollView控件
    - (UIScrollView *)creatScrollView       // 控件的创建单独抽象成方法
    {
        // 创建scrollView设置尺寸位置及相关属性
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        scrollView.frame = self.view.bounds;
        scrollView.contentSize = CGSizeMake(_size.width * kPicCount, 0);
        scrollView.pagingEnabled = YES;
        scrollView.showsHorizontalScrollIndicator = NO;
        scrollView.delegate = self;
        
        //  创建新特性图片设置尺寸位置并添加到scrollView
        for (int i = 0; i < kPicCount; i++) {
            UIImageView *imageView = [[UIImageView alloc] init];
            [scrollView addSubview:imageView];
            NSString *imageName = [NSString stringWithFormat:@"new_feature_%d.png", i + 1];
            imageView.image = [UIImage fullScreenImage:imageName];
            imageView.frame = CGRectMake(_size.width * i, 0, _size.width, _size.height);
            // 最后一张图片上添加两个子视图(分享选项与体验微博按钮)
            if ( i == kPicCount - 1) {
                imageView.userInteractionEnabled = YES;         // 开启当前imageView用户交互属性
                [self addShareButton:imageView];                // 调用方法创建分享选项视图
                [self addStartButton:imageView];                // 调用方法创建体验微博按钮视图
            }
        }
        return scrollView;
    }
    
    #pragma mark 添加pageControl控件
    - (UIPageControl *)creatPageControl     // 控件的创建单独抽象成方法
    {
        UIPageControl *pageControl = [[UIPageControl alloc] init];
        pageControl.center = CGPointMake(_size.width * 0.5, _size.height * 0.95);
        pageControl.bounds = CGRectMake(0, 0, kPageControlW, 0);
        pageControl.numberOfPages = kPicCount;
        
        // pageControl指示符颜色用图片代替,效果更美观
        UIImage *checkedPointImage = [UIImage imageNamed:@"new_feature_pagecontrol_checked_point.png"];
        pageControl.currentPageIndicatorTintColor = [UIColor colorWithPatternImage:checkedPointImage];
        UIImage *pointImage = [UIImage imageNamed:@"new_feature_pagecontrol_point.png"];
        pageControl.pageIndicatorTintColor = [UIColor colorWithPatternImage:pointImage];
        
        // scrollView的代理方法中可设置pageControl的当前页属性,将创建好的pageControl赋值给成员变量全局访问
        _pageControl = pageControl;
        return pageControl;
    }
    
    #pragma mark - 按钮添加方法
    #pragma mark 分享按钮添加
    - (void)addShareButton:(UIImageView *)imageView         // 新特性展示最后一张图片中"分享"视图单独抽象成方法
    {
        // 用按钮来实现"分享"视图
        UIButton *shareButton = [UIButton buttonWithType:UIButtonTypeCustom];
        shareButton.adjustsImageWhenHighlighted = NO;       // 去除按钮的高亮效果
        
        // 设置按钮两个状态,循环点击时循环切换
        UIImage *shareNomalImage = [UIImage imageNamed:@"new_feature_share_false.png"];
        UIImage *shareSelectedImage = [UIImage imageNamed:@"new_feature_share_true.png"];
        [shareButton setBackgroundImage:shareNomalImage forState:UIControlStateNormal];
        [shareButton setBackgroundImage:shareSelectedImage forState:UIControlStateSelected];
        
        // 设置按钮尺寸位置
        shareButton.center = CGPointMake(_size.width * 0.5, _size.height * 0.7);
        CGSize shareBtnSize = shareNomalImage.size;
        shareButton.bounds = CGRectMake(0, 0, shareBtnSize.width, shareBtnSize.height);
        shareButton.selected = YES;                         // 默认为已选择状态
        
        // 创建按钮监听事件,每次点击都修改一次selected状态
        [shareButton addTarget:self action:@selector(shareButtonEven:) forControlEvents:UIControlEventTouchUpInside];
        [imageView addSubview:shareButton];
    }
    
    #pragma mark 立即体验按钮添加
    - (void)addStartButton:(UIImageView *)imageView         // 新特性展示最后一张图片中"体验"按钮单独抽象成方法
    {
        // 创建按钮,设置尺寸宽高等属性
        UIButton *startButton = [UIButton buttonWithType:UIButtonTypeCustom];
        UIImage *startNomalImage = [UIImage imageNamed:@"new_feature_finish_button.png"];
        UIImage *startHighlightImage = [UIImage imageNamed:@"new_feature_finish_button_highlighted.png"];
        [startButton setBackgroundImage:startNomalImage forState:UIControlStateNormal];
        [startButton setBackgroundImage:startHighlightImage forState:UIControlStateHighlighted];
        startButton.center = CGPointMake(_size.width * 0.5, _size.height * 0.8);
        CGSize startBtnSize = startNomalImage.size;
        startButton.bounds = (CGRect){CGPointZero, startBtnSize};
        
        // 按钮监听事件,点击该按钮进入微博主界面
        [startButton addTarget:self action:@selector(startButtonEven:) forControlEvents:UIControlEventTouchUpInside];
        [imageView addSubview:startButton];
    
    }
    
    #pragma mark - 按钮事件处理方法
    #pragma mark 分享按钮事件处理
    -(void)shareButtonEven:(UIButton *)button               // "分享"按钮事件处理
    {
        button.selected = !button.selected;
        // 按钮的selected属性取反,实现循环点击-选择或取消分享
    }
    
    #pragma mark 立即体验按钮事件处理
    -(void)startButtonEven:(UIButton *)button               // "体验"按钮事件处理
    {
        // 该按钮事件使程序切换到微博主界面
        self.view.window.rootViewController = [[SAMainController alloc] init];
    }
    
    #pragma mark - scrollView代理方法
    -(void)scrollViewDidScroll:(UIScrollView *)scrollView   // 利用代理方法计算出pageControl中当前当前页属性
    {
        _pageControl.currentPage =  scrollView.contentOffset.x / scrollView.frame.size.width;
        // contentOffset.x的值除以视图宽度得到的整数相当于当前的页码
    }
    
    @end

    SAMainController.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  SAMainController.h
    //  SianWeibo
    //
    //  Created by yusian on 14-4-11.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //
    
    #import <UIKit/UIKit.h>
    
    @interface SAMainController : UIViewController
    
    @end
    

    SAMainController.m
    [Objective-C] 纯文本查看 复制代码
    //
    //  SAMainController.m
    //  SianWeibo
    //
    //  Created by yusian on 14-4-11.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //  主程序界面
    
    #import "SAMainController.h"
    
    @interface SAMainController ()
    
    @end
    
    @implementation SAMainController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        // 临时Table
        self.view.backgroundColor = [UIColor whiteColor];
        UILabel *tempLable = [[UILabel alloc] init];
        tempLable.center = self.view.center;
        tempLable.bounds = CGRectMake(0, 0, self.view.frame.size.width * 0.8, 50);
        tempLable.text = @"微博主界面建设中...";
        tempLable.textColor = [UIColor blueColor];
        tempLable.textAlignment = NSTextAlignmentCenter;
        tempLable.font = [UIFont systemFontOfSize:25];
        [self.view addSubview:tempLable];
        
    }
    
    @end
    

    UIImage+SA568h.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  UIImage+SA568h.h
    //  SianWeibo
    //
    //  Created by yusian on 14-4-11.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //  分类实现iphone5自动加载568h@2x尺寸图片
    
    #import <UIKit/UIKit.h>
    
    @interface UIImage (SA568h)
    
    + (UIImage *)fullScreenImage:(NSString *)string;
    
    @end
    

    UIImage+SA568h.m
    [Objective-C] 纯文本查看 复制代码
    //
    //  UIImage+SA568h.m
    //  SianWeibo
    //
    //  Created by yusian on 14-4-11.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //
    
    #import "UIImage+SA568h.h"
    
    @implementation UIImage (SA568h)
    
    + (UIImage *)fullScreenImage:(NSString *)string
    {
        // 根据屏幕高度判断iphone5
        if (isIPhone5) {
            
            // 1、获取文件扩展名
            NSString *ext = [string pathExtension];
            
            // 2、去掉文件扩展名
            string = [string stringByDeletingPathExtension];
            
            // 3、添加iphone5特殊文件名串
            string = [string stringByAppendingString:@"-568h@2x"];
            
            // 4、添加扩展名
            string = [string stringByAppendingPathExtension:ext];
        
        }
        return [self imageNamed:string];
    }
    
    @end
    

    SACommon.h
    [Objective-C] 纯文本查看 复制代码
    //
    //  SACommon.h
    //  SianWeibo
    //
    //  Created by yusian on 14-4-10.
    //  Copyright (c) 2014年 小龙虾论坛. All rights reserved.
    //  公共头文件
    
    // 判断是否为iphone5的宏
    #define isIPhone5 ([UIScreen mainScreen].bounds.size.height == 568)
    
    // 用MyLog替代NSLog,调试时输出日志,正式发布时自动取消日志输出代码
    #ifdef DEBUG
    #define MyLog(...) NSLog(__VA_ARGS__)
    #else
    #define MyLog(...)
    #endif
    

    4、源代码下载
    游客,如果您要查看本帖隐藏内容请回复


    相关主题链接
    1、ios实战开发之仿新浪微博(第一讲:新特性展示)
    2、ios实战开发之仿新浪微博(第二讲:主框架搭建)
    3、ios实战开发之仿新浪微博(第三讲:更多界面搭建)
    4、ios实战开发之仿新浪微博(第四讲:OAuth认证)
    5、ios实战开发之仿新浪微博(第五讲:微博数据加载)
    6、ios实战开发之仿新浪微博(第六讲:微博数据展示一)
    7、ios实战开发之仿新浪微博(第七讲:微博数据展示二)
    8、ios实战开发之仿新浪微博(第八讲:微博数据展示三)
    9、ios实战开发之仿新浪微博(第九讲:微博功能完善一)
    10、ios实战开发之仿新浪微博(第十讲:微博功能完善二)
    11、ios实战开发之仿新浪微博(第十一讲:微博功能完善三)
    12、ios实战开发之仿新浪微博(小龙虾发布版)
  • TA的每日心情
    倒霉
    2014-11-11 21:18
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    发表于 2014-10-14 00:20:53 | 显示全部楼层
    今天突然发现了这个非常棒的主页{:soso_e113:}

    该用户从未签到

    发表于 2014-10-23 20:26:14 | 显示全部楼层
    大赞这篇神贴!

    该用户从未签到

    发表于 2014-11-17 11:05:35 | 显示全部楼层
    持续关注,先下载看看!
  • TA的每日心情
    发光
    2014-11-26 14:19
  • 签到天数: 4 天

    [LV.2]偶尔看看I

    发表于 2014-11-19 13:03:05 | 显示全部楼层
    要是再加上一点教程,就完美了,是好东西
  • TA的每日心情
    开心
    2015-1-5 14:55
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2015-1-5 17:25:59 | 显示全部楼层
    尽管有点iOS的知识,我还在学习中...

    该用户从未签到

    发表于 2015-3-18 15:00:59 | 显示全部楼层
    :loveliness:好网站,好贴!加油~
  • TA的每日心情
    高兴
    2015-10-10 10:21
  • 签到天数: 44 天

    [LV.5]常住居民I

    发表于 2015-6-13 15:28:36 | 显示全部楼层
    好好学习学习楼主的这套教程,谢谢楼主的分享。
  • TA的每日心情
    高兴
    2015-10-10 10:21
  • 签到天数: 44 天

    [LV.5]常住居民I

    发表于 2015-6-14 14:21:38 | 显示全部楼层
    SAAppDelegate中的属性viewController没有用到。

    该用户从未签到

    发表于 2015-7-17 17:27:44 | 显示全部楼层
    不错,谢谢楼主贡献
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-4-20 03:23 , Processed in 0.055267 second(s), 26 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表