ios中常用的小技巧大全(总有你不知道的和你会用到的)

ios中常用的小技巧(总有你不知道的和你会用到的)

一、父视图设置的透明度影响到子视图的透明度问题

    UIView *darkView = [[UIView alloc] init];
    //[darkView setAlpha:0];//会影响到子时图
    [darkView setUserInteractionEnabled:NO];
    [darkView setFrame:(CGRect){0, 0, SCREEN_SIZE}];
    //[darkView setBackgroundColor:LCColor(46, 49, 50)];
    darkView.backgroundColor = [[UIColor colorWithRed:46/255.0f green:49/255.0f blue:50/255.0f alpha:1.0f] colorWithAlphaComponent:LC_DEFAULT_BACKGROUND_OPACITY];//这样父视图透明不影响子时图


二、控件的局部圆角问题

你是不是也遇到过这样的问题,一个button或者label,只要右边的两个角圆角,或者只要一个圆角。该怎么办呢。这就需要图层蒙版来帮助我们了。

    CGRectrect=CGRectMake(0,0,100,50);
    CGSizeradio=CGSizeMake(5,5);//圆角尺寸
    UIRectCornercorner=UIRectCornerTopLeft|UIRectCornerTopRight;//这只圆角位置
    UIBezierPath*path=[UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:corner cornerRadii:radio];
    CAShapeLayer*masklayer=[[CAShapeLayeralloc]init];//创建shapelayer
    masklayer.frame=button.bounds;
    masklayer.path=path.CGPath;//设置路径
    button.layer.mask=masklayer;

举例为button,其它继承自UIView的控件都可以


三、navigationBar的透明问题

如果仅仅把navigationBar的alpha设为0的话,那就相当于把navigationBar给隐藏了, 大家都知道,父视图的alpha设置为0的话,
那么子视图全都会透明的。那么相应的navigationBar的标题和左右两个按钮都会消失。这样显然达不到我们要求的效果。
(1)如果仅仅是想要navigationBar透明,按钮和标题都在可以使用以下方法:
<pre name="code" class="objc" style="color: rgb(46, 46, 46); font-size: 15px; line-height: 24px;">//给navigationBar设置一个空的背景图片即可实现透明,而且标题按钮都在
[self.navigationController.navigationBar setBackgroundImage:[UIImage new]forBarMetrics:UIBarMetricsDefault];
 
   细心的你会发现上面有一条线? 
  

首先我们看一下苹果官方给出的解释:

2E04731A-B0C8-4341-9B1D-D8FBB09B6484.png

现在让我这个英语半吊子来翻译一下,他的意思就是说如果你不调用这个方法设置一张背景图片的话,那我就给你默认一张,然后同时还有一张阴影图片被默认设置上去,好吧,这就是导航栏上1px黑线的由来,没错,就是这个苹果赠送的shadowImage。

相信看到这个解释即使不继续说下去有些同学也知道解决办法了吧,没错嘛,你就用上面说的那个方法,给设置一张背景图片,然后在设置一张shadowImage就可以了,就像这样:

这就需要我们做进一步处理,把线去掉,如下方法即可:
self.navigationController.navigationBar.shadowImage = [UIImage new];
//其实这个线也是image控制的。设为空即可
根据UI的设计,navigationbar需要跟界面一体化,但是下面这根黑线是比较烦的问题,可能界面一需要隐藏,界面二就要出现,也可能需要改变粗细之类的,又因为navigationbar会影响接下来的推栈,所以需要做一点小改动.
方法2:直接隐藏:
//在页面出现的时候就将黑线隐藏起来
 -(void)viewWillAppear:(BOOL)animated
{
    [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    [self.navigationController.navigationBar setShadowImage:[UIImage new]];
}
//在页面消失的时候就让navigationbar还原样式
-(void)viewWillDisappear:(BOOL)animated{

    [self.navigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault];
    [self.navigationController.navigationBar setShadowImage:nil];
}
这个方法唯一的不好就是会影响导航栏的translucent(透明)属性

方法3:找出黑线,再做处理:
//通过一个方法来找到这个黑线(findHairlineImageViewUnder):
 - (UIImageView *)findHairlineImageViewUnder:(UIView *)view {
    if ([view isKindOfClass:UIImageView.class] && view.bounds.size.height <= 1.0) {
        return (UIImageView *)view;
    }
    for (UIView *subview in view.subviews) {
        UIImageView *imageView = [self findHairlineImageViewUnder:subview];
        if (imageView) {
            return imageView;
        }
    }
    return nil;
}
//再定义一个imageview来等同于这个黑线 
 UIImageView *navBarHairlineImageView;
 navBarHairlineImageView = [self findHairlineImageViewUnder:self.navigationController.navigationBar];

同样的在界面出现时候开启隐藏
 -(void)viewWillAppear:(BOOL)animated
{
 navBarHairlineImageView.hidden = YES;
}
//在页面消失的时候就让出现
 -(void)viewWillAppear:(BOOL)animated
{
 navBarHairlineImageView.hidden = NO;
}
如果想要做一些更好的处理,比如说改变粗细,颜色之类的也在界面出现的时候写就行了.
推荐使用第二种方法,因为整个项目都在使用导航栏推栈,出栈,很可能因为改变了样式,导致后面的属性混乱起来.

方法4.下一个解决办法,将UINavigationBar的clipsToBounds属性设成YES就好啦,从此黑线去无踪。

方法5.最后一个办法,就是循环遍历一下UINavigationBar的所有子视图,发现有UIImageView类型的视图就remove掉,或者设成隐藏状态(hidden)。虽然也能达到想要的效果,但是感觉这个方法太暴力了,不是很推荐。


(2)如果你想在透明的基础上实现根据下拉距离,由透明变得不透明的效果,那么上面那个就显得力不从心了,这就需要我们采用另外一种方法了
//navigationBar是一个复合视图,它是有许多个控件组成的,那么我们就可以从他的内部入手
[[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = 0;//这里可以根据scrollView的偏移量来设置alpha就实现了渐变透明的效果

四、全局设置navigationBar标题样式和barItem的标题样式

//UIColorWithHexRGB( )这个方法是自己定义的,这里只需要给个颜色就好了
 [[UINavigationBar appearance] setBarTintColor:UIColorWithHexRGB(0xfefefe)];
 
 [[UINavigationBar appearance] setTitleTextAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:18],NSForegroundColorAttributeName:UIColorWithHexRGB(0xfe6d27)}];
 
 [[UITabBarItem appearance] setTitleTextAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:10],NSForegroundColorAttributeName : UIColorWithHexRGB(0x666666)} forState:UIControlStateNormal];



五、navigationBar隐藏和显示的过度

相信在使用中肯定遇到过,一个页面隐藏navigationBar,另一个不隐藏。两个页面进行push和pop的时候,尤其是有侧滑手势返回的时候,不做处理就会造成滑动返回时,navigationBar位置是空的,直接显示一个黑色或者显示下面一层视图,很难看。这就需要我们加入过度动画来隐藏或显示navigationBar:
在返回后将要出现的页面实现viewWillAppear方法,需要隐藏就设为YES,需要显示就设为NO
- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:NO animated:YES];
}


六、给webView添加头视图

webView是一个复合视图,里面包含有一个scrollView,scrollView里面是一个UIWebBrowserView(负责显示WebView的内容)
    UIView *webBrowserView = self.webView.scrollView.subviews[0];//拿到webView的webBrowserView
    self.backHeadImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenWidth*2/3.0)];
    [_backHeadImageView sd_setImageWithURL:[NSURL URLWithString:self.imageUrl] placeholderImage:[UIImage imageNamed:@"placeholderImage"]];
    [self.webView insertSubview:_backHeadImageView belowSubview:self.webView.scrollView];
    //把backHeadImageView插入到webView的scrollView下面
    CGRect frame = self.webBrowserView.frame;
    frame.origin.y = CGRectGetMaxY(_backHeadImageView.frame);
    self.webBrowserView.frame = frame;
    //更改webBrowserView的frame向下移backHeadImageView的高度,使其可见


七、模态跳转的动画设置

设置模态跳转的动画,系统提供了四种可供选择
    DetailViewController *detailVC = [[DetailViewController alloc]init];
    //UIModalTransitionStyleFlipHorizontal 翻转
    //UIModalTransitionStyleCoverVertical 底部滑出
    //UIModalTransitionStyleCrossDissolve 渐显
    //UIModalTransitionStylePartialCurl 翻页
    detailVC.modalTransitionStyle = UIModalTransitionStylePartialCurl;
    [self presentViewController:detailVC animated:YES completion:nil];



八、图片处理:只拿图片的一部分

UIImage *image = [UIImage imageNamed:filename];
CGImageRef imageRef = image.CGImage;
CGRect rect = CGRectMake(origin.x, origin.y ,size.width, size.height);
//这里的宽高是相对于图片的真实大小
//比如你的图片是400x400的那么(0,0,400,400)就是图片的全尺寸,想取哪一部分就设置相应坐标即可
CGImageRef imageRefRect = CGImageCreateWithImageInRect(imageRef, rect);
UIImage *imageRect = [[UIImage alloc] initWithCGImage:imageRefRect];


九、给TableView或者CollectionView的cell添加简单的动画,像这样


只要在willDisplayCell方法中对将要显示的cell做动画即可:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    NSArray *array =  tableView.indexPathsForVisibleRows;
    NSIndexPath *firstIndexPath = array[0];
 
    //设置anchorPoint
    cell.layer.anchorPoint = CGPointMake(0, 0.5);
    //为了防止cell视图移动,重新把cell放回原来的位置
    cell.layer.position = CGPointMake(0, cell.layer.position.y);
 
    //设置cell 按照z轴旋转90度,注意是弧度
    if (firstIndexPath.row < indexPath.row) {
            cell.layer.transform = CATransform3DMakeRotation(M_PI_2, 0, 0, 1.0);
    }else{
        cell.layer.transform = CATransform3DMakeRotation(- M_PI_2, 0, 0, 1.0);
    }
 
    cell.alpha = 0.0;
 
    [UIView animateWithDuration:1 animations:^{
        cell.layer.transform = CATransform3DIdentity;
        cell.alpha = 1.0;
    }];
}
- (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath{
 
    if (indexPath.row % 2 != 0) {
        cell.transform = CGAffineTransformTranslate(cell.transform, kScreenWidth/2, 0);
    }else{
        cell.transform = CGAffineTransformTranslate(cell.transform, -kScreenWidth/2, 0);
    }
    cell.alpha = 0.0;
    [UIView animateWithDuration:0.7 animations:^{
        cell.transform = CGAffineTransformIdentity;
        cell.alpha = 1.0;
    } completion:^(BOOL finished) {
 
    }];
}

十、点击屏幕隐藏键盘

这个需求应该是非常常见的,一个应用总有那么几个UITextField控件,当输入完成后,可以通过点击屏幕来隐藏键盘。具体实现如下:
(1)在ViewController的viewDidload方法中增加一个点击手势,
UITapGestureRecognizer *tap = 
[[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(dismissKeyboard)];

[self.view addGestureRecognizer:tap];
(2)实现dissmissKeyboard方法 在方法内隐藏键盘
[textField resignFirstResponder];//textField是需要监听的UITextField对象

十一、隐藏UITabbar

这个需求在列表页转场至详细页面中会遇到。例如在tableView的 didSelectRowAtIndexPath方法中可以使用,实现方法如下:
detailViewController *dc = [[detailViewController alloc]init];
dc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:dc animated:YES];

十二、iOS中字符串过滤掉非法字符

这里简单说两种方法,第一种就是替代法:使用stringByReplacingOccurrencesOfString这个方法将字符串里的非法字符逐个替代
/*1*/ tempString = [tempString stringByReplacingOccurrencesOfString:@" " withString:@""];
/*2 */tempString = [tempString stringByReplacingOccurrencesOfString:@"#" withString:@""];
/*3*/ tempString = [tempString stringByReplacingOccurrencesOfString:@"*" withString:@""];
/*4*/ tempString = [tempString stringByReplacingOccurrencesOfString:@"+" withString:@""];
/*5*/ tempString = [tempString stringByReplacingOccurrencesOfString:@"-" withString:@""];

这样做比较烦的一个问题就是,如果要过滤掉的非法字符有很多的话,就得写多行这种替代代码。

另外一种方法比较巧妙,先将字符串按非法字符集进行截断最后再拼接起来。代码看起来很简直,直接了断。

/*1*/ NSCharacterSet *doNotWant = [NSCharacterSet characterSetWithCharactersInString:@"[]{}(#%-*+=_)\\|~(<>$%^&*)_+ "];
/*2*/ tempString = [[tempString componentsSeparatedByCharactersInSet: doNotWant]componentsJoinedByString: @""];

doNotWant这个字符集里想写几个就写几个。

另外不能用stringByTrimmingCharactersInSet这个方法进行过滤,它能做到的仅仅是把字符串两端的非法字符过滤,但是包含在字符串里非法字符则无能为力。


十三、点击系统的返回按钮,返回到指定视图

举个栗子:我们在开发中,有时会遇到这样的情况,有A、B、C三个视图控制器,A中有一个按钮,点击按钮push到B控制器,B中有个按钮,点击push到C控制器,如果点击C左上角系统自带的返回按钮,会默认的执行下面的代码:

- (nullable UIViewController *)popViewControllerAnimated:(BOOL)animated;

返回到上一个页面B,当然我们可以通过自定义左上角的返回按钮,通过系统的方法:

- (nullable NSArray<__kindof UIViewController *> *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated;

返回到我们指定的视图控制器,但是此时会有一个问题,如果自定义了返回按钮,可以返回到指定的页面,但是如果通过右划的手势,此时页面返回的还是上一级页面,当然我们也可以通过给视图重新添加手势,在右划的时候,也返回到指定的页面,但是我觉得这样就有点儿工作量了;我想要表达的意思就是:在不自定义返回按钮的前提下,A->B->C,点击C上面的返回按钮(或者通过右划的手势),返回到A页面怎么实现呢;

网找了很多终于找到一个好的方法:

在B push到C页面之后,在C页面中,把B从视图控制器中删除,此时的控制器中只有A和C了,点击C上面的返回按钮,返回的就是A页面;(哎,哎,别打...)代码如下,这是在C页面中的代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    //得到当前视图控制器中的所有控制器
    NSMutableArray *array = [self.navigationController.viewControllers mutableCopy];
    //把B从里面删除
    [array removeObjectAtIndex:1];
    //把删除后的控制器数组再次赋值
    [self.navigationController setViewControllers:[array copy] animated:YES];
}

当然,如果有4个视图控制器的话A/B/C/D,如果想用从D返回到到A,可以把B和C从里面删除了,具体思路根据具体业务分析;



十四、IOS storyboard解决TableViewCell底线无法到头问题

加上下边这两段代码即可:
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    // 让分割线从头开始
    if ([_TableViewList respondsToSelector:@selector(setSeparatorInset:)]) {
        [_TableViewList setSeparatorInset:UIEdgeInsetsMake(0,0,0,0)];
    }
    
    if ([_TableViewList respondsToSelector:@selector(setLayoutMargins:)]) {
        [_TableViewList setLayoutMargins:UIEdgeInsetsMake(0,0,0,0)];
    }
}
// 让分割线从头开始
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
        [cell setSeparatorInset:UIEdgeInsetsZero];
    }
    
    if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
        [cell setLayoutMargins:UIEdgeInsetsZero];
    }
}

或者在xib中这样:
相信很多ios开发者都有遇到过这个坑,在设置tableview的时候想要将每个cell的底部线条长度和屏幕宽度一样。
但是即使在storyboard的tableview上设置如下图:



即使这样在你运行调试的时候每个cell的左边也还是会有一小段空白。
这问题是不是让你们很头疼呢?


估计有人会说直接使用uiview来当线条就好了
首先,用view当线条我不反对,但是在特殊情况下是不是很繁琐呢?你要在每个地方加这东西。。。


好了,直接进入问题吧。想要解决这个问题,其实很简单。


首先在storyboard上选中你的cell,然后如下图;



十五、iOS 修改导航栏的返回按钮的内容

我大致解释一下,使用pushViewController切换到下一个视图时,navigation controller按照以下3条顺序更改导航栏的左侧按钮。

1、如果B视图有一个自定义的左侧按钮(leftBarButtonItem),则会显示这个自定义按钮;

2、如果B没有自定义按钮,但是A视图的backBarButtonItem属性有自定义项,则显示这个自定义项;

3、如果前2条都没有,则默认显示一个后退按钮,后退按钮的标题是A视图的标题。

按照这个解释,我把UIBarButtonItem *backItem……这段代码放在A视图的pushViewController语句之前。

OK问题解决了,B视图的后退按钮的标题变成back了。

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self)
    {
        UIBarButtonItem *backItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStyleBordered target:nil action:nil];
        [self.navigationItem setBackBarButtonItem:backItem];
    }
    return self;
}



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值