iOS快速打企业包ipa

注意:因为是打企业ipa测试包,必须要有299$的企业证书,否则不可以

  1. 清理缓存,在Xcode菜单栏的Product中选择clean
    Mou icon
  2. 选择编译环境,要在 release 环境下
    Mou icon
    Mou icon
  3. 在配置文件的 Buid Settings/Code Signing 分别配置发布证书和描述文件
    Mou icon
    Mou icon
  4. 在配置文件的 General team 配置发布证书,并且注意 Bundle Identifier 要设置为描述文件中的APPID
    Mou icon
  5. 环境基本上配置好了,开始运行了,选择设备为手机运行(个人建议,最好用真机)
    Mou icon
  6. 编译成功后,在工程的Products目录下会有个.app文件
    Mou icon
  7. 接下来开始打包了,首先打开iTunes,然后把之前编译好的.app直接拖到iTunes上,会自动生成App,然后再把生成的App拖出来即可。

    • iTunes上
      Mou icon

    • 从iTunes上拖出来

      Mou icon

这样一个企业证书的app就打好了,赶紧试试吧!

Xcode7:让你只需4步就可以免证书进行真机调试了!

Mou icon
这里可以看到官方说了xcode7可以让所有人都更轻松的将app运行在自己的设备上,而无需开发者帐号。好了,既然官方都说了可以不用证书进行真机调试了,那我们就直接开始吧!

只需4步,你就可以免证书进行真机调试了!

  1. 进入xcode,菜单栏选择xcode –> preferences (快捷键 command + ,)在Accounts选项卡添加自己的Apple ID,下方蓝色选中部分会出现 free free的字样则代表成功;
    Mou icon
  2. 打开需要真机调试的项目,在TARGETS下选择General选项卡,展开Identity项,修改下面的team选项为你刚才添加的Apple ID,修改Bundle Identifier 为没有使用过的BundleID,注意:使用过的BundleID不行
    Mou icon
  3. 把你需要真机调试的设备连上电脑,在刚才team选项的下面此时多了一个警告,点击Fix Issue,等待xcode处理完,这个警告就消失了。
  4. 现在你可以进行真机调试了,运行项目会显示 Build Successed,但之后会出现如下提示(这里针对iOS9),手机安装了APP却打不开,这里需要在手机上设置一下:点击设置 -> 通用 -> 描述文件 -> 里面有你自己的AppleID的描述文件,点击信任就可以了
    Mou icon

iOS中webView加载URL需要处理特殊字符

今天在项目中遇到webView加载URL时,因为URL中有特殊字符,导致页面无法加载,而且在- (BOOL)webView:(UIWebView )webView shouldStartLoadWithRequest:(NSURLRequest )request navigationType:(UIWebViewNavigationType)navigationType代理方法中获取的request.URL是Null。一般来说我们调用webVIew的时候,只要给webVIew传一个url,在网页里面就可以显示网页信息。但是当我们传的url比较麻烦或者带文字符,带参数的时候我们需要对特殊字符进行转义。我们还可以用遍历、正则等来把特殊字符给替换掉!!

有两种方法,希望可以有所帮助:

一、使用NSString的方法:

1.字符串加百分号转义使用编码 (这个方法会把参数里面的东西转义)
    NSString *str1 = [string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];    

2.字符串替换百分号转义使用编码
    NSString *str1 = [string stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

二、使用CFStringRef的方法:

url = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)url, nil, nil, kCFStringEncodingUTF8));

Mou icon

iOS开发之各种动画各种页面切面效果

今天项目有个需求需要用到动画,就在网上搜了一下,搜到一篇博客,把系统的一些动画封装、分类了,而且还有Demo,用起来比较方便,在此为博主点个赞。
Mou icon

Mou icon

  1. 用CATransition实现动画的封装方法如下:

    #pragma CATransition动画实现
    #define  DURATION 0.25
     - (void) transitionWithType:(NSString *) type WithSubtype:(NSString *) subtype     ForView : (UIView *) view
     {    
         //创建CATransition对象
          CATransition *animation = [CATransition animation];
    
          //设置运动时间
          animation.duration = DURATION;
    
         //设置运动type
         animation.type = type;
         if (subtype != nil) { 
            //设置子类
             animation.subtype = subtype;
         }     
           //设置运动速度    
           animation.timingFunction = UIViewAnimationOptionCurveEaseInOut;
        [view.layer addAnimation:animation forKey:@"animation"];
      }
    
  2. 代码说明:

    CATransition常用的属性如下:
    
    duration:设置动画时间
    
    type:稍后下面会详细的介绍运动类型
    
    subtype:和type匹配使用,指定运动的方向,下面也会详细介绍
    
    timingFunction :动画的运动轨迹,用于变化起点和终点之间的插值计算,形象点说它决定了动画运行的节奏,比如是
    
    均匀变化(相同时间变化量相同)还是先快后慢,先慢后快还是先慢再快再慢.
    
    *  动画的开始与结束的快慢,有五个预置分别为(下同):
    
    *  kCAMediaTimingFunctionLinear            线性,即匀速
    
    *  kCAMediaTimingFunctionEaseIn            先慢后快
    
    *  kCAMediaTimingFunctionEaseOut           先快后慢
    
    *  kCAMediaTimingFunctionEaseInEaseOut     先慢后快再慢
    
    *  kCAMediaTimingFunctionDefault           实际效果是动画中间比较快.
    

原博主写的很详细,这里我就不写了,原文请看http://www.tuicool.com/articles/Znq2i2 Demo下载地址:https://github.com/lizelu/CATransitionDemo.git

UITextView/UITextField检测并过滤Emoji表情符号

UITextView/UITextField检测并过滤Emoji表情符号

本人在开发过程中遇到过这种情况,服务器端不支持Emoji表情,因此要求客户端在上传用户输入时,不能包含Emoji表情。在客户端发送请求前,判断用户输入中是否含有表情,如果含有表情,则提示用户重新输入。这个过程关键是如何判断字符串中是否含有Emoji表情。要判断是否含有Emoji表情,必须先了解什么是Emoji。

百度百科中告诉我们“自苹果公司发布的iOS 5输入法中加入了emoji后,这种表情符号开始席卷全球,目前emoji已被大多数现代计算机系统所兼容的Unicode编码采纳,普遍应用于各种手机短信和社交网络中。[1] ”,Emoji表情最终会被编码成Unicode,因此,只要知道Emoji表情的Unicode编码的范围,就可以判断用户是否输入了Emoji表情。

经过多番查找资料和测试Demo,目前有以下两种方式比较合理:

  1. 当用户切换键盘为Emoji表情时,输入的表情不响应(即表情符号不显示到UITextView或UITextField)。这里可以通过UITextView或UITextField的回调和是否为emoji键盘:

    /*
    *第一种方法,简单粗暴
    */
    - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    {
        // 不让输入表情
        if ([textView isFirstResponder]) {
            if ([[[textView textInputMode] primaryLanguage] isEqualToString:@"emoji"] || ![[textView textInputMode] primaryLanguage]) {
                NSLog(@"输入的是表情,返回NO");
                UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告!" message:@"不能输入表情" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
                [alertView show];
                return NO;
            }
        }
        return YES;
    }
    
  2. 为避免当用户通过中文键盘输入中文“哈哈”后出现可选文字中选中的Emoji笑脸,最后在- (void)textFieldDidEndEditing:(UITextField *)textField方法中统一通过检查最终字符串textField/textView.text的内容,通过Emoji筛unicode编码来判断是否存在Emoji表情,如果存在则提醒用户做修改。

    //在输入完成时,调用下面那个方法来判断输入的字符串是否含有表情
    - (void)textFieldDidEndEditing:(UITextField *)textField
    {
        if ([self stringContainsEmoji:textField.text]) {
            NSLog(@"含有表情");
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"警告!" message:@"输入内容含有表情,请重新输入" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定",nil];
            [alertView show];
            textField.text = @"";
            [textField becomeFirstResponder];
        }else {
            NSLog(@"不含有表情");
        }
    
    }
    
    /*
     *第二种方法,利用Emoji表情最终会被编码成Unicode,因此,
     *只要知道Emoji表情的Unicode编码的范围,
     *就可以判断用户是否输入了Emoji表情。
     */
    - (BOOL)stringContainsEmoji:(NSString *)string
    {
        // 过滤所有表情。returnValue为NO表示不含有表情,YES表示含有表情
        __block BOOL returnValue = NO;
        [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
    
            const unichar hs = [substring characterAtIndex:0];
            // surrogate pair
            if (0xd800 <= hs && hs <= 0xdbff) {
                if (substring.length > 1) {
                    const unichar ls = [substring characterAtIndex:1];
                    const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                    if (0x1d000 <= uc && uc <= 0x1f77f) {
                        returnValue = YES;
                    }
                }
            } else if (substring.length > 1) {
                const unichar ls = [substring characterAtIndex:1];
                if (ls == 0x20e3) {
                    returnValue = YES;
                }
            } else {
                // non surrogate
                if (0x2100 <= hs && hs <= 0x27ff) {
                    returnValue = YES;
                } else if (0x2B05 <= hs && hs <= 0x2b07) {
                    returnValue = YES;
                } else if (0x2934 <= hs && hs <= 0x2935) {
                    returnValue = YES;
                } else if (0x3297 <= hs && hs <= 0x3299) {
                    returnValue = YES;
                } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
                    returnValue = YES;
                }
            }
        }];
        return returnValue;
    }
    

ps:Demo已放在云盘里,链接: http://pan.baidu.com/s/1boguLgN 密码: keet

iOS6以后的单个控制器横竖屏显示以及旋转屏控制技巧

一、在应用中从竖屏模式强制转换为横屏模式

  1. 第一种方法:通过模态弹出视图的方式,使得特定ViewController坚持特定的interfaceOrientation
    (1)iOS6之后提供了这样一个方法,可以让你的Controller倔强的坚持某个特定的interfaceOrientation:

    - (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation     NS_AVAILABLE_IOS(6_0)
    {
        return UIInterfaceOrientationLandscapeRight;//左下右上显示
    
        这里有5种供选择,具体什么方向显示,自己可以试一下
        //UIInterfaceOrientationUnknown           
        //UIInterfaceOrientationPortrait          
        //UIInterfaceOrientationPortraitUpsideDown
        //UIInterfaceOrientationLandscapeLeft     
        //UIInterfaceOrientationLandscapeRight    
    }
    

    (2)当然,使用这个方法是有前提的,就是当前ViewController是通过全屏的Presentation(模态视图)方式展现出来的。而且需要设置下面方法返回值为NO,这样控制器就不会再进行旋转,而是以你设定方向显示。

    - (BOOL)shouldAutorotate NS_AVAILABLE_IOS(6_0)
    {
        return NO;
    }
    
  2. 第二种方法:通过人为的办法改变view.transform的属性。
    具体办法:

    view.transform一般是View的旋转,拉伸移动等属性,类似view.layer.transform,区别在于View.transform是二维的,也就是使用仿射的办法通常就是带有前缀CGAffineTransform的类(可以到API文档里面搜索这个前缀的所有类),而view.layer.transform可以在3D模式下面的变化,通常使用的都是前缀为CATransform3D的类。

    这里要记住一点,当你改变过一个view.transform属性或者view.layer.transform的时候需要恢复默认状态的话,记得先把他们重置可以使用view.transform = CGAffineTransformIdentity,或者view.layer.transform = CATransform3DIdentity,假设你一直不断的改变一个view.transform的属性,而每次改变之前没有重置的话,你会发现后来的改变和你想要的发生变化了,不是你真正想要的结果。

    好了,上面介绍了旋转的属性,接下来就是关键了。官方提供了一个办法就是查看当前电池条的状态UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;通过这个办法,你可以知道当前屏幕的电池条的显示方向,而且你还可以强制设置他的显示方向,通过设置这个属性就OK了,可以选择是否动画改变电池条方向。有了这两个那我们就可以任意的改变我们想要的显示方式了。

    (1)获取当前电池条的方向UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation
    
    (2)获取当前屏幕的大小CGRect frame = [UIScreen mainScreen].applicationFrame;
    
    (3)设置我们的View的中心点
    
        CGPoint center = CGPointMake(frame.origin.x + ceil(frame.size.width/2), frame.origin.y + ceil(frame.size.height/2));
    
    (4)根据当前电池条的方向,获取需要旋转的角度的大小。通常
    
    - (CGAffineTransform)getARotation {
        if (orientation == UIInterfaceOrientationLandscapeLeft) {
                return CGAffineTransformMakeRotation(M_PI*1.5);
            } else if (orientation == UIInterfaceOrientationLandscapeRight) {
                return CGAffineTransformMakeRotation(M_PI/2);
            } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
                return CGAffineTransformMakeRotation(-M_PI);
            } else {
                return CGAffineTransformIdentity;
            }
    }
    
    (5)可以动画的改变我们view的显示方式了
    [[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeRight animated:YES];
    
    CGFloat duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration;(获取当前电池条动画改变的时间)
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:duration];
    
    //在这里设置view.transform需要匹配的旋转角度的大小就可以了。
    //把(4)中返回的rotation赋给self.view.transform
    self.view.transform = [self getARotation];
    
    [UIView commitAnimations];
    
  1. 第三种方法:通过setOrientation:的办法强制性的旋转到一个特定的方向。

    注意:Apple在3.0以后都不支持这个办法了,这个办法已经成为了私有的了,但是要跳过App Stroe的审核,需要一点巧妙的办法。

        不要直接调用[[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]这样的办法来强制性的横屏,这样导致你的程序是很难通过App Store审核的。但是你可以选择使用performSelector的办法来调用它。具体就几行代码如下:
    
    //强制横屏
        if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {
            [[UIDevice currentDevice] performSelector:@selector(setOrientation:)
                                           withObject:(id)UIInterfaceOrientationLandscapeRight];
        }
    
  2. 总结:如果第一种办法可以满足你需要的话,最好使用第一种办法,因为第一种方法在App Store肯定没有问题,而且也比较简单;第二种方法在App Store也是没问题的,但是稍微复杂一些;第三种的话是需要冒风险的,但是如果你的结构太复杂了,导致使用前两种办法人为很难控制的话,可以尝试简单的使用第三种办法。

二、屏幕自适应重力感应进行旋转,实现对每个viewController的单独控制:

  1. 子类化UINavigationController,增加方法

    - (BOOL)shouldAutorotate  
    {  
        return self.topViewController.shouldAutorotate;  
    }  
    
    - (NSUInteger)supportedInterfaceOrientations  
    {  
        return self.topViewController.supportedInterfaceOrientations;  
    }  
    
  2. 并且设定其为程序入口,或指定为 self.window.rootViewController
    随后添加自己的view controller,如果想禁止某个view controller的旋屏:(支持全部版本的控制)

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
    {  
        return (interfaceOrientation == UIInterfaceOrientationPortrait);  
    }  
    
    -(BOOL)shouldAutorotate  
    {  
        return NO;  
    }  
    
    -(NSUInteger)supportedInterfaceOrientations  
    {  
        return UIInterfaceOrientationMaskPortrait;  
    }  
    
  1. 如果想又开启某个view controller的全部方向旋屏支持:

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation  
    {  
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);  
    }  
    
    -(NSUInteger)supportedInterfaceOrientations  
    {  
        return UIInterfaceOrientationMaskAllButUpsideDown;  
    }  
    
    -(BOOL)shouldAutorotate  
    {  
        return YES;  
    }  
    

    从而实现了对每个view controller的单独控制。

  2. 顺便提一下,如果整个应用所有view controller都不支持旋屏,那么干脆:

    - (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window  
    {  
         return UIInterfaceOrientationMaskPortrait;  
    }  
    

横屏时,ios7上有电池状态栏,在iOS8就没有电池状态栏了

上次开发过程遇到有个页面横屏显示,当设置横屏展示时,就没有电池状态栏了。查了一些资料才发现,原来
横屏时,ios7上有电池状态栏,在iOS8就没有电池状态栏了,是因为iOS8默认横屏时将电池状态栏隐藏了,这是iOS8的新特性。

下面说说怎么让状态栏在横屏时显示出来:

  1. 在plist文件中将 View controller-based status bar appearance 设置为 NO
    Mou icon

  2. 在appdelegate.m中的- (BOOL)application:(UIApplication )application didFinishLaunchingWithOptions:(NSDictionary )launchOptions 方法中添加下面代码即可。

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    
        [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationNone];
        [[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
        return YES;
    }
    

UICollectionview的使用详解

  1. 三个代理
    前两个的用法和tableView的很像,第三个是布局的协议。(注意:头视图尾视图都是由代理方法获得,而且需要写注册,缺少了也不行。) 注册以后,就不需要再去管理复用的问题了。这点就很简单。这个如果用好的话,会非常的简单。
  2. item(即cell)的布局原理(类似tableView)
  3. header/footer View的布局原理
    都是继承于UICollectionReusableView,并且必须要从dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:这个代理方法中获取,而且根据不同的kind作为headerView或者footerView,切记:collectionView中头部视图和尾部视图也需要注册

下面直接上代码,看注释即可:

ViewController.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController<UICollectionViewDataSource,UICollectionViewDelegateFlowLayout>{

}
@property (strong, nonatomic)UICollectionView *collectionView;

@end

ViewController.m

#import "ViewController.h"
#import "NewSceneCollectionHeaderView.h"
#import "NewSceneCollectionFooterView.h"
#import "NewSceneCollectionViewCell.h"

@interface ViewController ()

@end

//cell、header、footerView 标识
static NSString *cellIdentifier = @"NewSceneCollectionViewCell";
static NSString *headerIdentifier = @"NewSceneCollectionHeaderView";
static NSString *footerIdentifier = @"NewSceneCollectionFooterView";

@implementation ViewController

- (void)viewDidLoad
{
      [super viewDidLoad];
     //创建布局对象
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    //flowlaout的属性,确定是水平滚动,还是垂直滚动
    flowLayout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

    //接下来就在创建collectionView的时候初始化,就很方便了(能直接带上layout)
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, 200, 320, 280) collectionViewLayout:flowLayout];
    self.collectionView.backgroundColor = [UIColor grayColor]; 

    //指定数据源和代理
    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;

    //添加到主页面上去 
    [self.view addSubview:self.collectionView];

    //collectionCell的注册
    [self.collectionView registerClass:[NewSceneCollectionViewCell class] forCellWithReuseIdentifier:cellIdentifier];

    //collection头视图的注册。  注意:奇葩的地方来了,头视图和尾部视图也得注册
    [self.collectionView registerClass:[NewSceneCollectionHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier];
    [self.collectionView registerClass:[NewSceneCollectionFooterView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:footerIdentifier];

      /*另一种方式
      //从Xib上注册
    UINib *nib = nil;
    nib = [UINib nibWithNibName:cellIdentifier bundle:nil];
    [self.collectionView registerNib:nib
                 forCellWithReuseIdentifier:cellIdentifier];
    //注册headerview和footerview
    nib = [UINib nibWithNibName:headerIdentifier bundle:nil];
    [self.collectionView registerNib:nib forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:headerIdentifier];
    nib = [UINib nibWithNibName:footerIdentifier bundle:nil];
    [self.collectionView registerNib:nib forSupplementaryViewOfKind:UICollectionElementKindSectionFooter withReuseIdentifier:footerIdentifier];
    */
      [self.view addSubview:self.collectionView];
}

/********************************************************
 *UICollectionViewDataSource/Delegate/DelegateFlowLayout
 ********************************************************/
#pragma mark  UICollectionViewDataSource/Delegate

//返回多少组(section),此方法不写默认是1组(跟tableview类似)
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 2;
}

#pragma mark required
//每组返回多少个Item,这个Item类似tableview中的cell
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 10;
}

//返回cell,这里构建Item(即cell)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    //这里是自定义的cell
    NewSceneCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    cell.backgroundColor = [UIColor redColor];
    return cell;
}

#pragma mark  optional
//自定义header/footerView
// The view that is returned must be retrieved from a call to -dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:
//这里返回的view必须要从dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:这个方法中获取,而且根据不同的kind作为headerView或者footerView,切记:collectionView中头部视图和尾部视图也需要注册
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    UICollectionReusableView *reusableView = nil;
    if (UICollectionElementKindSectionHeader == kind) {
        //这里是自定义的头视图
        NewSceneCollectionHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:headerIdentifier forIndexPath:indexPath];
        headerView.backgroundColor = [UIColor whiteColor]; 
        return headerView;
    }
    if (UICollectionElementKindSectionFooter == kind {
        //这里是自定义的尾视图               
        NewSceneCollectionFooterView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:footerIdentifier forIndexPath:indexPath];
        footerView.backgroundColor = [UIColor whiteColor]; 
        return footerView;
    }
    return reusableView;
}

#pragma mark --UICollectionViewDelegateFlowLayout

//布局确定每个Item 的大小
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{    
    return CGSizeMake(100, 100);
}

//布局确定每个section内的Item距离section四周的间距 UIEdgeInsets
-(UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section
{
    return UIEdgeInsetsMake(10, 10, 10, 10);
}

//返回每个section内上下两个Item之间的间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section
{
    return 10; 
}
//返回每个section内左右两个Item之间的间距
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section
{
    return 10;
}

//返回headerView的尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section
{
    CGFloat width = CGRectGetWidth(collectionView.bounds);
    CGFloat height = width + 86;
    return CGSizeMake(width, height);
}

//返回footerView的尺寸
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout referenceSizeForFooterInSection:(NSInteger)section
{
    CGFloat width = CGRectGetWidth(collectionView.bounds);
    CGFloat height = 144;
    return CGSizeMake(width, height);
}

#pragma mark --UICollectionViewDelegate

//UICollectionView被选中时调用的方法
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    NewSceneCollectionViewCell * cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
    cell.backgroundColor = [UIColor greenColor];
    NSLog(@"item======%ld",(long)indexPath.item);
    NSLog(@"row=======%ld",(long)indexPath.row);
    NSLog(@"section===%ld",(long)indexPath.section);
}

//返回这个UICollectionView是否可以被选择
-(BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

Undefined symbols for architectur referenced from问题解决

多个人共同操作同一个项目或拷贝项目时,经常会出现类似这样的问题:
Undefined symbols for architecture x86_64:
“_OBJCCLASS$_xxx文件名”, referenced from:
Mou icon
今天我就遇到了这个问题,当我从svn上update服务器上的改动后再commit本地的修改,出现了冲突,打不开工程,当我删除冲突后打开工程,就出现上述错误(是误删出了错)。删除冲突操作如下图:
Mou icon

下面给我的解决办法,在报错这里我们可以看到,是因为缺少了两个XXX.o文件

  1. 先打开svn,找到工程的配置文件,选中project.pbxproj,然后revert,这里是把你之前解决冲突时删除的操作恢复了。如图
    Mou icon

  2. 这里你之前添加到工程里的文件会被恢复,文件还在(因为之前你已经commit了),只是没有添加到工程中,这时打开之前文件添加的位置,点击add files,如图
    Mou icon

  3. 会出现一个窗口,在这个窗口中,灰色不能点击的文件均为已经添加到工程里的文件,这时你会看到你之前添加的文件,它们是正常文件颜色,可以点击,选中它们添加到工程即可,如图
    Mou icon

  4. 最后,运行项目即可

iOS中nil 、NULL、 Nil 、NSNull,你真的了解吗?

今天突然间对nil和NULL产生了疑问,就在网上查了一下相关的问题,看完之后终于有了清晰的认识,跟我一样有疑问的童鞋们可以看看。

  1. nil,定义一个空的实例,指向OC中对象的空指针。

    示例代码:
    NSString *someString = nil;
    NSURL *someURL = nil;
    id someObject = nil;
    if (anotherObject == nil) // do something
    
    用法讲解:
     当对某个对象release 的同时最好把他们赋值为nil,这样可以确保安全性,如果不赋值nil,可能导致程序
     崩溃.
          NSArray * array = [NSArray arrayWithObjects:@"test",@"test1" ,nil];
          [array release];
          
          if (array)
          {
          //仅仅对数组release,并没有赋值为nil,在程序某个地方如果继续对数组操作,程序直接崩溃
              NSString * string = [array objectAtIndex:0];
              NSLog(@"%@",string);
          }
    
  2. NULL,NULL可以用在C语言的各种指针上。

    #define __DARWIN_NULL 
    #define__DARWIN_NULLConstants
    示例代码:
    int *pointerToInt = NULL;    
    char *pointerToChar = NULL;  
    struct TreeNode *rootNode = NULL;
    
    用法讲解:
      在Objective-C里,nil对象被设计来跟NULL空指针关联的。他们的区别就是nil是一个对象,而NULL只是一个
      值。而且我们对于nil调用方法,不会产生crash或者抛出异常。
    
  3. Nil,定义一个空的类

    示例代码:  
    Class someClass = Nil; 
    Class anotherClass = [NSString class];
    
  4. NSNull,NSNull是一个类,它定义了一个单例对象用于表示集合对象的空值

    集合对象无法包含nil作为其具体值,如NSArrayNSSetNSDictionary。相应地,nil值用一个特定的对象
    NSNull来表示。NSNull提供了一个单一实例用于表示对象属性中的的nil值。默认的实现方法中,
    dictionaryWithValuesForKeys:和setValuesForKeysWithDictionary:自动地将        NSNullnil相互转换,因此您的对象不需要进行NSNull的测试操作。