• 微博项目笔记


    微博笔记:

    1.LaunchScreen

    /*

     *LaunchScreen:替代以前的启动图片

     *好处:

     *1.可以展示更多的内容

     *2.仅仅需要一张大尺寸的图片就好,然后伸缩适应图片

     *

     *启动的优先级:

     *启动图片的优先级低于 < LaunchScreen (图片不适合时记得调一下伸缩)

     *

     * 当模拟器尺寸不对的时候,第一时间找启动图片,模拟器的尺寸由启动图片决定(使用启动图片不用Xib的时候记得调整Info.plist 加载launchScreen的名称删掉)

     

     */

    2.-----------------------------

       //显示窗口

         [self.window makeKeyAndVisible];

        //makeKeyAndVisible 等价于,但是application.keyWindow = self.window只读

        //1.application.keyWindow = self.window;

     

       // 2.self.window.hidden = NO;

    3viewController的加载顺序——————————————————

      //1.UITabBarController View 是在UITabBarController控制器一创建就加载

     

        //2.UIViewController   的View是在加显示窗口的才加载显示,(用到的才会显示,属于懒加载(需要用到的时候才会加载))

     

    4 instancetype————————————————————

    //instancetype:默认会识别哪个类和子类调用,默认就会转为对应的类的对象

    5.id-----------------------------

     id (不建议使用):

     1.使用这个不能使用点语法

    2.所有的Set 和 Get 方法都能使用 ,不能识别出错误

     

    6.Dictionary 的新语法

    dic[NSForegroundColorAttributeName] = [UIColor orangeColor];

        //上面的等价于下面的着这种方法,键 = Value key的值直接在 UIKIT中找

     

       [dic setValue:[UIColor orangeColor]forKey:NSForegroundColorAttributeName];

    7.appearance 的介绍和使用特点————————————

     //appearances什么时候可以获获取外观标识,当这个类遵循UIAppearance协议的时候,比如:UIView

        //获取所有的tabBarItem  appearance:为全局外观的标始(不够严谨,会影响所有遵循UIAppearance协议的)

       // UITabBarItem *item = [UITabBarItem appearance];

        

        //self ->XDTabBarController

        //获取当前类下面的所有TabBarItem

        UITabBarItem *item = [UITabBarItem appearanceWhenContainedIn:self, nil];

        //设置模型的文本属性

        NSMutableDictionary *dic = [NSMutableDictionary dictionary];

        dic[NSForegroundColorAttributeName] = [UIColor orangeColor];

        

        //上面的等价于下面的着这种方法,键 = Value key的值直接在 UIKIT中找

        //[dic setValue:[UIColor orangeColor] forKey:NSForegroundColorAttributeName];

     

        [item setTitleTextAttributes:dic forState:UIControlStateSelected];

    //--------------------+(void)load 什么时候调用和作用-------

    //什么时候调用:程序一启动的时候就会把所有类加载到内存

    //作用:加载所有的类

    //+(void)load

    //{

    //

     

    //}

     

    //———————+(void)initialize什么时候调用和作用----------

    //什么时候调用:初次使用某个类或者子类的时候调用

    //作用:初始化类

    +(void)initialize

    {

    }

     

    //获取TabBar 全局外观属性,设置外观属性,设置文字属性

     //appearance:是一种协议 只要遵循 :UIAppearance就可以 所以当前的类归自己管理,使用appearanceWhenContainedIn

        UITabBarItem *item = [UITabBarItem appearance];

        NSMutableDictionary *attributes = [NSMutableDictionary dictionary];

        attributes[NSForegroundColorAttributeName] = [UIColor orangeColor];

     

         [item setTitleTextAttributes:attributes forState:UIControlStateSelected];

     

    //———————设置中间的按钮的位置

     //设置中间的按钮的位置

        self.plusButton.center = CGPointMake( w * 0.5, h * 0.5);

     

        //self.plusButton.bounds = CGRectMake(0, 0, self.plusButton.currentBackgroundImage.size.width, self.plusButton.currentBackgroundImage.size.height);

     //默认的按钮大小与背景图片一样

     //sizeToFit 会根据你的背景图片 Image和文字计算出最合适的位置

     

            [addButton sizeToFit];

     

    //————————item 模型的 求法

    //self.items 是UITabBarItem 的模型 ,有多少个子控制器就有多少个Item模型

    //————————TitleView 设置为搜索框—————

    1.如果要求在左边显示提示文字 ,则要使用可以使用占位符的,用UITextFile 代替 UIsearch ,要设置它的UITextFiled 的左边搜索按钮,则要设置 它的leftView , 但是要求有一定的距离,则先拉伸 ,在让图片自我调节位置。当设置UITextFiled 的上的左右视图时 :leftViewMode 一定要设置它的状态   

    //self(  UITextFiled  )

            //initWithImage:图标的大小会默认与图片一样

            UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"searchbar_textfield_search_icon"]];

            imageView.width += 10;

            imageView.contentMode = UIViewContentModeCenter;

            self.leftView = imageView;

            

            //一定要设置,想要显示左边的视图,一定要设置左边的视图模式

     

            self.leftViewMode = UITextFieldViewModeAlways;

     

    //————隐藏底部的标签栏————

      //Push 的时候隐藏底部的标签栏

        //hidesBottomBarWhenPushed:的前提条件是,system 自带的才可以使用

     

        self.hidesBottomBarWhenPushed = YES;

    //———————————创建XIb initWithNibName的实现步骤

     

     //1.先查看是否有XDOneView.xib的文件

        //2.第二步加载与控制器同名的XDOneViewController.xib 文件

        //创建一个默认几乎的透明的View

        XDOneViewController *one = [[XDOneViewController alloc]initWithNibName:nil bundle:nil];

    //等价于,因为init 它的底层会调用 initWithNibName

      XDOneViewController *one = [[XDOneViewController alloc]init];

    ------------------------------------------------------------------------------------------------------------

    //—————统一样式的左右导航按钮的时候———

    1.要在继承(UINavigationController)导航控制器d的类中,利用

    -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{

    if (self.viewControllers.count != 0) {//不是跟视图控制器

            //设置导航栏的内容

            //设置导航控制左右两边的按钮

            //左边的按钮

            //当设置的左边的返回按钮覆盖以后,不能实现滑动返回手势功能

            viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonItemWithImage:[UIImage imageNamed:@"navigationbar_back"] highImage:[UIImage imageNamed:@"navigationbar_back_highlighted"] target:self action:@selector(backToPre) forControlEvents:UIControlEventTouchUpInside];

            

            //右边的按钮

     

            viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem barButtonItemWithImage:[UIImage imageNamed:@"navigationbar_more"] highImage:[UIImage imageNamed:@"navigationbar_more_highlighted"] target:self action:@selector(backToRoot) forControlEvents:UIControlEventTouchUpInside];

    }

     //    CZLog(@"%s",__func__);

     

        [super pushViewController:viewController animated:animated];

    }

    #pragma mark 导航控制器左右两边的Item UIBarButtonItem Action

    -(void)backToPre

    {

        [self popViewControllerAnimated:YES];

    }

    -(void)backToRoot

    {

        [self popToRootViewControllerAnimated:YES];

    }

     

    2.当返回按钮被覆盖的时候,返回滑动手势则会失效

    1.要在继承(UINavigationController)导航控制器d的类中,viewDidLoad中设置它的导航控制器代理

    - (void)viewDidLoad {

        [super viewDidLoad];

      

        //保存原来的滑动手势代理

        _popDelegate = self.interactivePopGestureRecognizer.delegate;

        //导航控制器上的代理方法,实现判断是否回到跟控制器

        self.delegate = self;

      

        

     

    }

     

    //2.调用调用带有展示当前的ViewController 的代理方法,什么时候使用系统的滑动手势代理方法,什么时候不适用

    #pragma mark -------popDelegate 

    -(void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated

    {

        NSLog(@"%@",self.viewControllers[0]);//判断它是哪一个控制器

        if (viewController == self.viewControllers[0]) {//显示的是跟控制器

            //还原滑动返回手势

            self.interactivePopGestureRecognizer.delegate = _popDelegate;

        }else//不显示根视图控制器

        {

            //实现滑动返回功能

            //清空滑动返回收手势代理,就能实现返回滑动功能

            self.interactivePopGestureRecognizer.delegate = nil;

        

        }

     

    }

     

    ------------------------------------------------------------------------------------------------------------

    //------------可以循环利用的两个的中, TableView 与 colletionView  

     它们添加内容都是调用ContentView,

    //检查是否有新的版本

        //如果有新特性,进入新特性界面

        //还有一定要对CollectionView ,进行LayOut

    ------------------------------------------------------------------------------------------------------------

        

        //1.获取版当期的版本号

        NSString *currentVersion =  [NSBundle mainBundle].infoDictionary[@"CFBundleVersion"];

        

        //2.获取上一次的版本号

        NSString *lastVersion = [[NSUserDefaults standardUserDefaults] objectForKey:XDVersionKey];

        

        //3.判断版本号,是否要新定义

        if ([currentVersion isEqualToString:lastVersion]) {//当前版本号和上一次相同

            

            //创建tabBarController ,把它作为根视图控制器,支持设备旋转

            XDTabBarController  *tabBarController = [[XDTabBarController alloc] init];

                self.window.rootViewController = tabBarController;

            

        }else{//当前版本号和上一次的不相同,要从新特性界面进入

        

            XDNewFeatureController *newFeatureVC = [[XDNewFeatureController alloc] init];

            self.window.rootViewController = newFeatureVC;

            

            //保存当前的版本号,用编号设置

            [[NSUserDefaults  standardUserDefaults]setObject:currentVersion forKey:XDVersionKey];

        

        }

    //—————————偏好设置的优点————————

    //偏好设置存储的好处

    //1.不用自己管理文件名

    //2.快速进行键值对存储

     

    //———————————OAuth授权———————

    OAuth授权:让数据变得更安全

    流程:有数据提供商提供一个登陆网站,显示在第三方客户端上

    什么时候需要UAuth授权:1.需要获取第三方数据(新浪,腾讯,百度,豆瓣)

                                    2.第三方登录

                                     3.第三方分享

    注意:并不是任何软件都能OAuth授权,只有成为第三方的开发者,才能UAuth授权

    如何成为第三方开发者?

    //1.在百度上搜索 微博开放平台

    //2.登录自己的微博账号

    //3.点击微链接,选择移动开发,实名认证以后,点击继续创建

    //4.高级信息中填写OAuth授权设置

    //——————OAuth 授权的步骤——————

    授权步骤总结:

    1.获取未授权的Request Token<进入登陆界面>拼接的时候记得不要留空白

    2.获取用户授权的Request Token <点击授权>

    3.用授权的 Request Token 换取 Access Token 

    (得到这个 Access Token 就相当于得到一个“令牌”,通过此”令牌“请求

    就可以拥有资源的网站抓取任意有权限被抓取的资源)

     

    access_token:表示哪个软件在哪个用户下的标志符,获取了access_token就可以获取相应的数据提供商提供的数据

    uid:表示用户的唯一标识符

     

    //———开发步骤———————

    1.搭建开发界面

    2.展示数据

    3.处理对应的业务逻辑

    //—————————content-type:响应头的错误----

    /*

     "Request failed: unacceptable content-type: text/plain"

     1.AFN通过判断响应头,判断是否有解析数据的方式,content-type: 包含在响应头中,所以要修改AFN,让其包含text/plain解析方式

     

     */

    //———KVC的底层

    1.一个一个的遍历Key ,查找是否有 SetKey ,如果有的话直接赋值

    2.看是否有_key,如果有的话找到直接赋值

    3.遍历所有的key,给key 赋值

    4.如果key没有赋值,就会报错

     

    //————跟服务器打交道

    1.向服务器发送请求 -->一般的参照接口文档,跟接口文档打交道,就查阅接口文档(1.请求的Url 2.哪种类型的接口(GET,Post)3.返回的数据格式)

    2.服务器响应的数据-->解析数据,设计数据模型—>返回数据转换为模型

    3.展示数据,刷新数据

     

    //———————使用SDWebImage  的好处和注意点

    SDWebImage 的好处:

    1.属于异步请求,不会阻塞主线程(界面)

    2.自动创建缓存

    3.可以让图片循环利用

    注意点:因为自动创建缓存,很容易造成内存的警告

    解决的方法:

    -(void)applicationDidReceiveMemoryWarning:(UIApplication *)application

    {

       //停止所有的图片下载

        [[SDWebImageManager sharedManager] cancelAll];

        

        //清空所有缓存

        [[SDWebImageManager sharedManager].imageCache clearMemory];

     

     

    }

     

    //———下拉刷新数据 ,下拉添加更多的数据

     

     //添加下拉刷新控件

        [self.tableView  addHeaderWithTarget:self action:@selector(loadNewStatus)];

        

        //自动刷新微博数据

        [self.tableView  headerBeginRefreshing];

      //结束下拉刷新

     

            [self.tableView headerEndRefreshing];

         //最新数据的条数

            NSIndexSet *indexSets = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0,statuses.count)];

         //把最新的微博插入到前面,一定要数组的形式添加数据

            [self.statuses insertObjects:statuses atIndexes:indexSets];

     

     

            //添加上拉刷新控件

     

        [self.tableView addFooterWithTarget:self action:@selector(loadOtherStatus)];

     

     

        //since_id false int64 若指定此参数,则返回ID比since_id大的微博(即比since_id时间晚的微博),默认为0。

      if (self.statuses.count) {//有微博数据,需要下拉刷新

        params[@"since_id"] = [self.statuses[0]idstr];

        }

     

     //max_id false int64 若指定此参数,则返回ID小于或等于max_id的微博,默认为0。,默认为0

     

    1.注意点:一定要记得“-1”把重复的数据去掉

        if (self.statuses.count) {//有数据需要上拉获取(以前)更多的数据

            

     long long max_Id  =[[[self.statuses  lastObject] idstr]longLongValue]-1;

            params[@"max_id"] = [NSString stringWithFormat:@"%lld",max_Id];

            

     

        }

      //结束下拉刷新

     

            [self.tableView footerEndRefreshing];

       //不能使用addObjects: 必须把数组的元素加入

     

            [self.statuses addObjectsFromArray:statuses];

     

    //请求数据常规的开发步骤

    1.查看接口文档

    2.依据参数列表,设置参数模型

    3.依据结果列表设置结果模型

    4.拿到对应的工具类请求就好

     

    //设置软件的消息未读数

    //设置应用程序的未读数,记得要注册通知

     

            [UIApplication sharedApplication].applicationIconBadgeNumber =接收到消息数目( result.totalCount);

    1. applicationIconBadgeNumber 查看它的头文件 

    2.从头文件中可以知道它是对象 注册[UIApplication registerUserNotificationSettings:]

    3.在程序的启动页面,AppDelegate 写

    //注册微博程序未读消息通知

        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge categories:nil];

        [application registerUserNotificationSettings:settings];//通过这里可以推出要有UIUserNotificationSettings 对象的属性

     

    //点击tabBar Item 的时候 刷新微博 的逻辑 :不要当选中第一个按钮的时候都刷新,当自己想跳转到其他页面,再次点击刚刚的按钮的时候,又刷新,那原来的浏览的消息界面就改变了,所以要满足 两次选中的还是同一个按钮的时候才刷新 index == 0(这是指定) && self.selectedIndex == index

    //让程序一直处于运行,在后台播放

     

    //在真机的话要记得设置音频会话

    [/*

         //混合播放,会把后台的音乐混合播放

         AVF_EXPORT NSString *const AVAudioSessionCategoryAmbient;

         

         //单独播放,会先把后台的音乐先停下来,然后再播放

        AVF_EXPORT NSString *const AVAudioSessionCategorySoloAmbient;

        

       //进入后台就播放

        AVF_EXPORT NSString *const AVAudioSessionCategoryPlayback;

         */

        //在真机的后台播放音乐

        AVAudioSession *session = [AVAudioSession sharedInstance];

        

        //设置会话的类型,可以两种类型一起设置

        [session setCategory:AVAudioSessionCategoryPlayback error:nil];

        [session setCategory:AVAudioSessionCategorySoloAmbient error:nil];

        

        //激活

     

        [session setActive:YES error:nil];

    ]//这是加载程序的时候就设置

    //程序即将失去焦点的时候调用

    - (void)applicationWillResignActive:(UIApplication *)application {

        

       //设置播放器

        NSURL *url = [[NSBundle mainBundle] URLForResource:@"一次就好.mp3" withExtension:nil];

        AVAudioPlayer *player = [[AVAudioPlayer alloc]initWithContentsOfURL:url error:nil];

        //准备播放

        [player prepareToPlay];

        //无限播放

        player.numberOfLoops = -1 ;

        //播放

        [player play];

        

        //记得局部变量都要,强引用

        _player = player;

    }

     

    //当程序进入后台的时候调用

    - (void)applicationDidEnterBackground:(UIApplication *)application {

     

        //开启一个后台任务,时间不确定,优先级比较低,假如系统要关闭应用的时候,系统会优先关闭这个程序

        UIBackgroundTaskIdentifier ID =[application beginBackgroundTaskWithExpirationHandler:^{

            //结束后台的任务

            [application  endBackgroundTask:ID];

        }];

        

        //1.如何提高后台的优先级,欺骗苹果,设置播放程序

        

        //2.苹果系统会检测是否在播放音乐,当没有在播放音乐的时候,系统会关闭程序

        

        //3.微博:在即将失去焦点的时候会播放静音的音乐

     

    }

    //—————复杂的界面的开发步骤——————

    1.按照业务逻辑划分界面的结构(原创,转发,工具条)

    2.每一个结构都自定义控件

    3.在控件上先把所有划分的结构界面都添加上去

    4.计算每个控件的位置,如果以后碰到的内容是根据模型决定的,马上就搞个ViewModel视图模型(模型 + 控件的Frame)

    5.模型转视图模型

    6.给控件赋值视图模型

    7.调节界面(文字和颜色)

     

    //UIImageView 的 contentMode

    UIViewContentModeScaleToFill,//填充整个控件

    UIViewContentModeScaleAspectFit,//按比例缩放,且不会超出控件

    UIViewContentModeScaleAspectFill, //按比例缩放,且高度或则宽度有一个不超出控件,然后让图片的中心对齐控件中心

    UIViewContentModeCenter,//不会缩放图片,只会把图片的中心点和控件对齐

    //-------获取服务器的图片的时候,如果不清晰的话

     http://ww1.sinaimg.cn/thumbnail/61c99730jw1eyndx74f8pj20tz124aik.jpg

     http://ww1.sinaimg.cn/bmiddle

    /61c99730jw1eyndx74f8pj20tz124aik.jpg

     

    //当记不住Block 的格式时候 在 代码中敲 :inline 就会显示

     

    **********************************************************

    //当设置复杂的cell还是其他的先要划分结构,有哪几部分组成,划分成子控件(注意点:cell 的初始化 initWithStyle)

    1.先搭建框架

    2.搭建子类控件

    *****************************************************************************************************

    //重写创建Cell ,自定义创建cell:使用类方法

    +(instancetype)cellWithTableView:(UITableView *)tableView

    {

        static NSString *ID = @"cell”;

    //放回的cell 是否为闲置

         id cell = [tableView dequeueReusableCellWithIdentifier:ID];

        if (cell == nil) {

      //谁调用就初始化谁的类

          cell = [[self alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

        }

        

        return cell;

     

    }

    *****************************************************************************************************

    MVVM思想:

    /*

     1.cell的高度应该提前计算出来: 当一有数据的时候就要使用VM 设置Cell的大小

     2.cell 的高度 必须计算每个cell的子控件必须frame,才可以确定(类似字体的话,你通过字体的小设置Frame的同时,记得要设置控件的字体)

     2.在cell的setStatus方法计算cell的高度,会比较耗费性能

     

     解决的办法:MVVM思想

     M:模型

     V:视图

     VM:视图模型,(模型中包装模型+模型对应视图的Frame)

     */

    /*

     复杂的界面开发步骤:

     1.按照业务逻辑划分结构,(原创,转发,工具条)

     2.每一个结构,都自定义一个控件

     3.在控件上先把所有划分的结构添加上去

     4.计算每个控件的位置,如果碰见的内容是根据模型决定的,马上定义一个ViewModle(模型+模型的大小)

     5.模型转视图模型

     6.赋值

    7.调节界面(文字大小,颜色)

    8.一个结构一个结构的处理

     

     */

    /*

    1.可以直接传递数据,确定数据的放置的位置

    2.MVVM:如果一个控件循环利用,可以避免多次计算控件的Frame

    */

    *****************************************************************************************************

    常用的图片大小

    1.导航条的 高度:64点 @2x :128 @3x : 192 

    2.tabBar的高度: 49点

    3.导航条的子控件和tabBar 的子控件 Or 工具条的高度:35

    *****************************************************************************************************

    开发中注意的事项

    1.UIView 是设置不了 图片的,那先要转变成:UIImageView 这可以添加图片,但是要注意,记得设置交互

    self.userInteractionEnabled = YES;

    2.设置每一个cell 间的间距,不可以整个cell设置因为没有设置它的 X Y 是不确定的,所以可以设置cell 中的原创微博 的高度 下移 10 个间距 ,在设置tableView 的背景颜色就好

    *****************************************************************************************************

    时间的业务逻辑:(使用的框架为:NSDate+MJ

    //设置时间格式(由于使用点语法获取数据的,所以要重新设置Get方法)判断的技巧:不要从小的开始判断,要先判断大的,再依次判断小的

    -(NSString *)created_at

    {

        // Sat Mar 26 16:05:03 +0800 2016 微博给我们的时间格式

        //1.先要把字符串转化成 NSDate

        //转换 EEE MMM d HH:mm:ss Z yyyy

        //日期格式转换

        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

        formatter.dateFormat = @"EEE MMM d HH:mm:ss Z yyyy ";

        NSDate *creat_time = [formatter dateFromString:_created_at];

        if ([creat_time isThisYear]) {//今年

            //两天前

            if ([creat_time isToday]) {//今天

                NSDateComponents *cmp = [creat_time deltaWithNow];

                if (cmp.hour >= 1) {

                    return [NSString stringWithFormat:@"%ld小时前",cmp.hour];

                }else if(cmp.minute > 1)

                {

                    return [NSString stringWithFormat:@"%ld分钟前",cmp.minute];

                }else

                {

                    return @"刚刚";

                }

                

            }else if ([creat_time isYesterday])

            {//昨天

                formatter.dateFormat = @"昨天 HH:mm";

                return [formatter stringFromDate:creat_time];

            

            }else

            {//前天

                formatter.dateFormat = @"MM-dd HH:mm";

                return [formatter stringFromDate:creat_time];

            }

            

       

        }else{//不是今年

             formatter.dateFormat = @"yyyy-MM-dd HH:mm";

            return [formatter stringFromDate:creat_time];

        }

        

        return _created_at;

    }

    *****************************************************************************************************

    图片的contentMode经常使用的介绍

       /**

             * UIViewContentModeScaleToFill :将整个图片压缩到适合控件的大小

             UIViewContentModeScaleAspectFit :按比例缩放到不超出边框

             UIViewContentModeScaleAspectFill:按比例缩放到到一边(宽或高)不超出边界合适就不在改变

            UIViewContentModeCenterview 与图片的中心点对齐,不会居中

             *

             */

            imageView.contentMode = UIViewContentModeScaleAspectFill;

    //把多余的截掉

    imageView.clipsToBounds = YES;

    *****************************************************************************************************

    //九宫格的布局

    1.先求总体的Frame

       //配图

        if (_status.pic_urls.count) {

            CGFloat photosX = textX;

            CGFloat photosY = CGRectGetMaxY(_orignalTextFrame) + MDStatusCellMargin;

            CGSize photosSzie = [self setPhotosSizeWithCount:_status.pic_urls.count];

            _orignalPhotosFrame =(CGRect){{photosX,photosY},photosSzie};

            

            originalH = CGRectGetMaxY(_orignalPhotosFrame) + MDStatusCellMargin;

     

        }

    //计算大小的方法setPhotosSizeWithCount

    -(CGSize)setPhotosSizeWithCount:(NSInteger)count

    {

       //配图的列数

        NSInteger cols = count == 4?2:3;

        //配图行数(这是有计算公式的):行数 = (总数 - 1/列数 +1

        NSInteger rols = (count - 1) / cols + 1;

        CGFloat photosWH = 70;

        CGFloat photosW = photosWH * cols + (cols - 1) * MDStatusCellMargin;

        CGFloat photosH = photosWH * rols  + (rols - 1)* MDStatusCellMargin;

        CGSize photosSie = CGSizeMake(photosW, photosH);

        return photosSie;

     

    }

    //计算九宫格内部布局

    -(void)layoutSubviews

    {

        [super layoutSubviews];

        CGFloat x = 0;

        CGFloat y = 0;

        CGFloat w = 70;

        CGFloat margin = 10;

        CGFloat h = 70;

        int col = 0;

        int rol = 0;

        int cols = _pic_urls.count == 4?2:3;

        

        //计算要显示的图片的Frame

        for (int i = 0; i< _pic_urls.count; i++) {

            col = i % cols;

            rol = i / cols;

            UIImageView *imageV = self.subviews[i];

            x = col * (margin + w);

            y = rol * (margin + h);

            imageV.frame = CGRectMake(x, y ,  w, h);

        }

     

    }

    *****************************************************************************************************

    //图片浏览器设置

    //添加九个配图控件(要把传过来,利用属性传值)

    -(void)setUpAllChildVC

    {

        //九宫格中

        for (int i = 0; i < 9 ; i++) {

            UIImageView *imageView = [UIImageView alloc].init;

            /**

             * UIViewContentModeScaleToFill :将整个图片压缩到适合控件的大小

             UIViewContentModeScaleAspectFit :按比例缩放到不超出边框

             UIViewContentModeScaleAspectFill:按比例缩放到到一边(宽或高)不超出边界合适就不在改变

            UIViewContentModeCenterview 与图片的中心点对齐,不会居中

             *

             */

            //添加点图片手势按钮

            UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)];

            imageView.tag = i;

            //当使用UIImageView的时候,记得设置图片的交互

            imageView.userInteractionEnabled = YES;

            

            [imageView addGestureRecognizer:tap];

            imageView.contentMode = UIViewContentModeScaleAspectFill;

            //把超出边框的图片去掉

            imageView.clipsToBounds = YES;

            [self addSubview:imageView];

        }

     

    }

    //添加点图片手势按钮

    -(void)tapGesture:(UITapGestureRecognizer *)tap

    {

         //在手势的图片添加Tag,这可以知道获取的是第几张图片(通过手势可以获取点击的图片)

        UIImageView *imageV = (UIImageView *) tap.view;

        //点击图片的时候调用

        //创建图片浏览器

        int i = 0;

        NSMutableArray *array = [NSMutableArray array];

        for (MDPhotos *photos in _pic_urls) {

            //MDphotos 转换成 MJphoto

            //MJPhoto.h 的文件中 ,要实现的属性有

            //1.@property (nonatomic, strong) NSURL *url;

            //2.@property (nonatomic, strong) UIImageView *srcImageView; // 来源view(你点击那个图片)

            //3.@property (nonatomic, assign) int index; // 索引

            MJPhoto *mjPhotos = [[MJPhoto alloc] init];

            //图片不清晰时,可以键连接的改一下

            NSString *urlString = photos.thumbnail_pic.absoluteString;

            urlString = [urlString stringByReplacingOccurrencesOfString:@"thumbnail" withString:@"bmiddle"];

            mjPhotos.url = [NSURL URLWithString:urlString];

    //        NSLog(@"%@",photos.thumbnail_pic);

            mjPhotos.index = i ;

            mjPhotos.srcImageView = imageV;

            [array addObject:mjPhotos];

            i ++ ;

        }

        

        MJPhotoBrowser *browser = [[MJPhotoBrowser alloc] init];

        /*MJ头文件提示要实现的,以后使用框架的时候,要看头文件

         // 所有的图片对象(MJPhoto)

         @property (nonatomic, strong) NSArray *photos;

         // 当前展示的图片索引

         @property (nonatomic, assign) NSUInteger currentPhotoIndex;

         */

        browser.photos = array;//所有图片对象

        browser.currentPhotoIndex = imageV.tag ;

        //以后看到要显示到主窗口的 可以 考虑框架是否有 show(看框架头文件)

        [browser show];

        

     

     

     

    }

    *****************************************************************************************************UITextView 中输入的字体设置和水印的文字大小一样(textView 输入的位置x= 5,y = 8)

    UITextView 系统没有默认设置self.font 

    通过设置:

    -(instancetype)initWithFrame:(CGRect)frame

    {

        if (self = [super initWithFrame:frame]) {

            self.font = [UIFont systemFontOfSize:13];

           //self.placeHolderLable.font = font;  不要在这里设置,当外界改变(textView)的时候,也会改变

        }

        return self;

    }

    //再重写setFont设置placeHolderLable.font 可以跟着外面 改变

    -(void)setFont:(UIFont *)font

    {

        [super setFont:font];

        self.placeHolderLable.font = font;

     //避免在输入信息后在设置字体,这样字体的大小不符合lable Frame

     

        [self.placeHolderLable sizeToFit];

     

    }

    *****************************************************************************************************

    becomeFirstResponder //变成第一响应,

    resineFirstResponder  //放弃第一响应,

    响应机制多用在获取(或放弃)键盘行为

    ******************************************************************************

    判断是否有文本输入的时候可以使用通知

     //监听文本的输入(通知)

        /**

         *1.addObserver:需要监听的对象

         2.name:监听通知的名称

         3.object:监听谁发送通知 nil:谁发送都监听

         设置通知,要把它移除

         UITextViewTextDidChangeNotification:这是监听输入名称(需要记住的)

         *

         */

        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextViewTextDidChangeNotification object:nil];

    }

    -(void)textChange

    {    //监听是否有文本输入

        if (_textView.text.length) {//有文本输入

            _textView.hiddlePalceHolder = YES;   

        }else

        {//没有文本输入

            _textView.hiddlePalceHolder = NO;

        }

    }

    -(void)dealloc

    {    //移除通知

        [[NSNotificationCenter defaultCenter]removeObserver:self];

    }

    *****************************************************************************

     //设置图片的大小(有的图片上传的时候要大小限定)

    CGFloat compressionQuality 这是图片压缩系数

     

        UIImageJPEGRepresentation(<#UIImage *image#>, <#CGFloat compressionQuality#>)

    //这是压缩图格式

      NSData *data =  UIImagePNGRepresentation(image);

    *****************************************************************************

       //自动布局行高

     

        self.tableView.rowHeight = UITableViewAutomaticDimension;

    tableView:dequeueReusableCellWithIdentifier

     1.storyBoard 其实就是内部会帮你注册cell

         2.在ViewDidLoad 使用了(forIndexPath:)没有使用storyBoard ,要自己手动创建 [self.tableView registerClass:[自己的创建cell类 class] forCellReuserIdentifer:ID ];

     

       forIndexPath:不能使用自己创建的cell

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:<#@"reuseIdentifier"#> forIndexPath:indexPath];

        /*1.先从缓存池中取出数据

          2.判断Cell 有没有注册,有的话,直接创建cell

        3.没有创建就返回NIL

  • 相关阅读:
    Spring 学习笔记(4)依赖注入 DI
    05Spring之AOP
    01Spring核心概念
    06Spring之循环依赖
    04Spring之依赖注入
    09Spring 设计模式总结
    08Spring之事务
    01Servlet 回顾
    03Spring之Bean生命周期
    02Spring启动过程
  • 原文地址:https://www.cnblogs.com/meixian/p/5370943.html
Copyright © 2020-2023  润新知