ios 开发中遇见的问题及处理方法

记录一点点小问题处理

xcode调试在release模式下,控制台不打印信息问题:

debug模式不要调整,自动可以po出属性。release模式将building setting -> Optimization Level ->release 条件由Fastest, Smallest[-Os] 改成 None[-Oo].
发布版本的时候,记得改回来,倒数第二个哦。

1.一般我们进行刷新的下拉时候,都会先清掉数据源,在重新请求数据,加载数据源; 这时候你要直接就将数据清掉,可能会引起crash。因为你在清掉数据源,视图还在,内部调用方法就crash了。这时候要先请求数据,确认数据请求到了,在清掉原来的数据,在加载新的数据源。
But t t t ——有的场景就不能这么处理,还没有load到新数据之前,就必须要把旧的数据源清掉。这样很容易导致crash;

我的处理方法是:在清掉数据源之后,紧接着刷新一下视图;[self.tableView reloadData]。这样就不会引起crash,具体为什么是这样,我也不是很清楚,可能relaodData 方法内部进行什么处理了吧。。谁知道或是有更好的办法求告知,感激不尽!!

2.当cell上有动画时,一定要注意动画完成的block与刷新数据方法的调用顺序。
当你刷新数据方法在动画完成block之前调用了,就可能会出现异常。

解决办法:用GCD,确保方法的执行顺序,block完成之后在调用数据刷新;添加到队列里的方法,会按着添加的顺序执行(FIFO),这样就能保证了调用顺序。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ //Do Something });

这么写可能不太理解,反正就是要注意动画完成的block之后在刷新数据。如果不能保证这样的执行顺序,就不要在动画完成那里在处理一些你想做的视图更新操作。

3.关于tableView的使用和代理方法

tableView的plain类型,sectionHead 会有悬停效果;grouped类型,不会悬停。

直接用这个方法设置头视图
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return @"Title"; }
当是plain类型时,显示正确;当是grouped类型时,会强制转成大写“TITLE”。中文没有影响。

//响应点击索引时的委托方法
-(NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
设置索引的时候,这个代理方法设置点击索引跳转的位置。默认不写或是直接return index,系统会自动关联索引,自己实现这个代理方法可能还出错呢,建议不要实现这个方法。

//修改索引字体

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
    //修改索引颜色
//    tableView.sectionIndexBackgroundColor = [UIColor greenColor];//修改右边索引的背景色
    tableView.sectionIndexColor = kMainColor;//修改右边索引字体的颜色
//    tableView.sectionIndexTrackingBackgroundColor = [UIColor orangeColor];//修改右边索引点击时候的背景色
    return self.headerTitles;
}

设置sectionHeadView

在设置header和footer信息的时候,View的优先级高于titile。即使你写了title代理方法,但是你实现了headView代理方法,这是title代理方法- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section无效。

sectionHead或footView 都要注意复用,提高效率,而且还可以在相应的代理方法中改变其属性
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { UITableViewHeaderFooterView *vi = (UITableViewHeaderFooterView *)view; vi.textLabel.textColor = [UIColor redColor];//这时候已经拿到了headView 随意更改它的属性 }

4.UITableViewDelegate(tableView代理方法)

cell将要显示时调用的方法

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;

头视图将要显示时调用的方法

- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section;

尾视图将要显示时调用的方法

- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section;

和上面的方法对应,这三个方法分别是cell,头视图,尾视图已经显示时调用的方法

- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath;
- (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section;
- (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section;

设置自定义头视图和尾视图

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

5.寻找第一响应者
实际开发中,经常用到第一响应者,做一些特别的操作。有时候还不太好找,用Apple 这个public API,当target是nil的时候,就会直接拿到第一响应者。
- (BOOL)sendAction:(SEL)action to:(id)target from:(id)sender forEvent:(UIEvent *)event
什么意思呢?

The object to receive the action message. If target is nil, the app sends the message to the first responder, from whence it progresses up the responder chain until it is handled.
第一响应者也参考这个文章

6.iOS定时器——GCD定时器

//系统自带里这个快捷创建方式(dispatch_source),只需要设置一个queue即可。 
- (dispatch_source_t)createGCDTimer {
    dispatch_queue_t queue = dispatch_get_main_queue();
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        //定时器开始回调
    });
    dispatch_resume(timer);
    return timer;
}

***********分步创建*****************
 //0.创建一个队列
  dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
 
 //1.创建一个GCD的定时器
  /*
   第一个参数:说明这是一个定时器
   第四个参数:GCD的回调任务添加到那个队列中执行,如果是主队列则在主线程执行
   */
  dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
  
//2.设置定时器的开始时间,间隔时间以及精准度
  //设置开始时间,三秒钟之后调用
  dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW,3.0 *NSEC_PER_SEC);
  //设置定时器工作的间隔时间
  uint64_t intevel = 1.0 * NSEC_PER_SEC;
  /*
   第一个参数:要给哪个定时器设置
   第二个参数:定时器的开始时间DISPATCH_TIME_NOW表示从当前开始
   第三个参数:定时器调用方法的间隔时间
   第四个参数:定时器的精准度,如果传0则表示采用最精准的方式计算,如果传大于0的数值,则表示该定时切换i可以接收该值范围内的误差,通常传0
   该参数的意义:可以适当的提高程序的性能
   注意点:GCD定时器中的时间以纳秒为单位(面试)
   */
  dispatch_source_set_timer(timer, start, intevel, 0 * NSEC_PER_SEC);
  
//3.设置定时器开启后回调的方法
  /*
   第一个参数:要给哪个定时器设置
   第二个参数:回调block
   */
  dispatch_source_set_event_handler(timer, ^{
      NSLog(@"------%@",[NSThread currentThread]);
  });

  //4.执行定时器
  dispatch_resume(timer);
  //注意:dispatch_source_t本质上是OC类,在这里是个局部变量,需要强引用
  self.timer = timer;

7.给字符串里的某些指定字符串设置富文本

 NSString *marketPriceStr = [NSString stringWithFormat:@"¥%.2f", product.marketPrice];
 NSString *showStr = [NSString stringWithFormat:@"¥%.2f %@", product.goodsPrice, marketPriceStr];
//先拿到要设置富文本字符串的位置  这里就是给showStr字符串里的marketPriceStr这些字设置富文本
NSRange range = [showStr rangeOfString:marketPriceStr options:NSBackwardsSearch];
//设置你想要的富文本
 NSDictionary *attr = @{
                           NSFontAttributeName : [UIFont systemFontOfSize:12],
                           NSStrikethroughStyleAttributeName : @(NSUnderlineStyleSingle | NSUnderlinePatternSolid),
                           NSStrikethroughColorAttributeName : [UIColor colorWithRed:230 / 255.0f green:23 / 255.0f blue:115 / 255.0f alpha:1]
                           };
//然后添加富文本 在这个找到的特殊位置
[showAttrStr addAttributes:attr range:range];

8.关于iOS通知机制NSNotificationCenter
通知在iOS开发中很常用,用于多个界面的传值响应等,可以一对多传递。使用唯一注意一点的是:要先addObserver,在postNotificationName通知。 这个就要注意一下顺序了。 只有addObserver这个界面先出现,在出现postNotification这个界面,当你切换到发通知这个界面时,前面添加接收通知的界面才会响应通知内容。。。这里要注意的就是这个顺序问题

9.KVO 使用
使用不多说,就说一个地方要注意:Keypath的命名不是随便的,要用你要监听的那个属性命名,不能错。 而且,属性值发生变化自动调用KVO的前提是:属性必须调用了setter、getter方法或是KVC方法。 直接_name = "newName"是不可以的。

10.webView获取js的meta内容

//js的标签内容


//UIWebView获取方法
    NSString *js = @"document.getElementsByName(\"attach_title\")[0].content";
    NSString *attach_title = [self.webView stringByEvaluatingJavaScriptFromString:js];
    
    js = @"document.getElementsByName(\"attach_url\")[0].content";
    NSString *attach_url = [self.webView stringByEvaluatingJavaScriptFromString:js];
//WKWebView的获取方法
- (void)getWKwebViewCenterDic {
    WEAKSELF;
    [self.wkWebView evaluateJavaScript:@"document.getElementsByName(\"attach_title\")[0].content" completionHandler:^(id result, NSError * _Nullable error) {
        NSString *attach_title = @"";
        if ([result isKindOfClass:[NSString class]]) {
            attach_title = result;
        }
        
        [weakSelf getWebViewJSResult:@{@"title" : attach_title}];
    }];
    
    [self.wkWebView evaluateJavaScript:@"document.getElementsByName(\"attach_url\")[0].content" completionHandler:^(id result, NSError * _Nullable error) {
        NSString *attach_url = @"";
        if ([result isKindOfClass:[NSString class]]) {
            attach_url = result;
        }
        
        [weakSelf getWebViewJSResult:@{@"url" : attach_url}];
    }];
}

iOS 保持界面流畅的技巧
暂时就这么多,随时发现随时记录更新。

你可能感兴趣的:(ios 开发中遇见的问题及处理方法)