常见问题汇总

AFNetworking Get请求失败

  • 今天第一次使用AFNetworking,发现NSURLSessionDataTask一直报错,错误信息:
  • Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text\/html"
  • 经过一番网上排查,网上有人说是AF2.0本身的问题,解析格式不全,所以需要在AF的源文件AFURLResponseSerialization.m中修改代码就能解决,修改文件228行处
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil nil];

改为

self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil nil];
  • 即可,试过确实可以,但AF还在持续更新的类库,不宜随意修改,特别是在用了CocoaPods之后,如果之后更新库,此类错误又会重复出现,随后在另外一篇文章中发现acceptableContentTypes是一个开放的属性,既然这样,就证明acceptableContentTypes可以在外部被修改,所以可以在

初始化HttpClient单利的时候改变这一值:

- (instancetype)initWithBaseURL:(NSURL *)url {  
    if (self = [super initWithBaseURL:url]) {  

        self.responseSerializer = [AFJSONResponseSerializer serializer];  
        self.requestSerializer.timeoutInterval = TimeoutInterval;  
        self.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html", nil nil];  
        [self setHTTPHeader];  // 可在此处设置Http头信息  
    }  
    return self;  
}

项目中集成Alipay支付宝接口

  • 首先下载支付钱包接口Demo源代码,导入如下内容:

    • openssl 文件夹下的所有文件
    • Util 文件夹的所有文件
    • libcrypto.a
    • libssl.a
    • AlipaySDK.bundle
    • AlipaySDK.framework
  • 将上面所有文件加入项目后,在项目的Build Settings→Search Paths中指定Framework Search Path、Header Search Paths和Library Search Paths为导入的文件位置,如:$(PROJECT_DIR)\/JZ-KongGe\/AliPay

Xcode7 真机运行时报错

  • 出现场景

    • 正常调试是没有问题的,但是在Archive的时候,报出了这个错误。
  • 错误信息

    ld: 'XXX' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), 
    obtain an updated library from the vendor, or disable bitcode for this target. for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    
  • 问题分析

    • 从上述的错误中应该可以看出,这是因为一个第三方的库不兼容,我的工程中开启了 ENABLE_BITCODE (Xcode7.0默认是开启Enable Bitcode的),而这个第三方的库在编译的时候没有 enable bitcode,如果你导入的一些第三方库在编译的时候没有Enable Bitcode 的话,就会导致上诉问题。
  • 解决方法

    • 方法一:使用Enable Bitcode的第三方库
    • 方法二:将工程中的Enable Bitcode设置为NO

IOS 获取定位权限

  • 配置信息

    • 在plist文件中添加NSLocationWhenInUseUsageDescription 和 NSLocationAlwaysUsageDescription 这两项;
    • Type选择Boolean,Value均为YES。
  • 代码部分

    • 首先,我们需要在工程中导入CoreLocation系统框架。然后在我们的控制器中引入头文件。
    #import <CoreLoction/CoreLocation.h>
    
    • 然后,声明一个CLLocationManager对象作为成员变量,用于定位获取经纬度坐标,并遵守协议CLLocationManager的协议。
    @interface TYViewController () <CLLocationManagerDelegate> {
      CLLocationManager *_locationManager;
    }
    
    • 实现其中的代理方法
    - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
    {
      //将经度显示到label上
      self.longitude.text = [NSString stringWithFormat:@"%lf", newLocation.coordinate.longitude];
      //将纬度现实到label上
      self.latitude.text = [NSString stringWithFormat:@"%lf", newLocation.coordinate.latitude];
      // 获取当前所在的城市名
      CLGeocoder *geocoder = [[CLGeocoder alloc] init];
      //根据经纬度反向地理编译出地址信息
      [geocoder reverseGeocodeLocation:newLocation completionHandler:^(NSArray *array, NSError *error){
         if (array.count > 0){
           CLPlacemark *placemark = [array objectAtIndex:0];
           //将获得的所有信息显示到label上
           self.location.text = placemark.name;
           //获取城市
           NSString *city = placemark.locality;
           if (!city) {
             //四大直辖市的城市信息无法通过locality获得,只能通过获取省份的方法来获得(如果city为空,则可知为直辖市)
             city = placemark.administrativeArea;
           }
           NSLog(@"city = %@", city);
           _cityLable.text = city;
           [_cityButton setTitle:city forState:UIControlStateNormal];
         }
         else if (error == nil && [array count] == 0){
           NSLog(@"No results were returned.");
         }
         else if (error != nil){
           NSLog(@"An error occurred = %@", error);
         }
       }];
      //系统会一直更新数据,直到选择停止更新,因为我们只需要获得一次经纬度即可,所以获取之后就停止更新
      [manager stopUpdatingLocation];
    }
    
    • 最后在viewDidLoad中初始化定位管理器。
    - (void)viewDidLoad
    {
      [super viewDidLoad];
      [self initializeLocationService];
      // Do any additional setup after loading the view.
    }
    - (void)initializeLocationService {
      // 初始化定位管理器
      _locationManager = [[CLLocationManager alloc] init];
      // 设置代理
      _locationManager.delegate = self;
      // 设置定位精确度到米
      _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
      // 设置过滤器为无
      _locationManager.distanceFilter = kCLDistanceFilterNone;
      // 开始定位
      [_locationManager startUpdatingLocation];
    }
    

接下来编译并运行程序,手动在iOS模拟器上配置定位坐标,即可打印出该经纬度坐标对应的城市名(真机可直接打印出当前城市名)。

CLPlacemark类中封装了很多的地理信息属性,包括完整的地址(大到国家,小到街道)和地理名称等等,可以酌情使用。

PS:如果定位出的街道信息为英文,那请先处理本地化,同时模拟器调整语言为中文。

iOS中添加UITapGestureRecognizer手势识别后,UITableView的didSelectRowAtIndexPath失效

用TableView写了一个登陆界面,帐号和密码两个Cell中加入了TextField。由于想在TableView的空白处点击时收起键盘,所以他注册了一个UITapGestureRecognizer来识别手势。

ViewDidLoad中注册手势的部分代码如下:

UITapGestureRecognizer *oneTap = [[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyBoard)] autorelease];  
oneTap.delegate = self;  
oneTap.numberOfTouchesRequired = 1;  
[self.view addGestureRecognizer:oneTap];

其中hideKeyBoard方法就省略了,基本就是几个resignFirstResponder。 然后发生了一个奇怪的现象,点击“找回密码”那一栏时没有反应了!!!

调试后我发现委托方法

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath不执行了。

目测原因是UITapGestureRecognizer截获了touch事件,导致didSelectRowAtIndexPath方法无法响应。

查阅了相关文档后找到了一种可行的解决方法:重写UIGestureRecognizerDelegate中的

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch方法。
#pragma mark - UIGestureRecognizerDelegate  
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch  
{  
    // 输出点击的view的类名  
    NSLog(@"%@", NSStringFromClass([touch.view class]));  

    // 若为UITableViewCellContentView(即点击了tableViewCell),则不截获Touch事件  
    if ([NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]) {  
        return NO;  
    }  
    return  YES;  
}

再次调试,这回didSelectRowAtIndexPath响应了,解决UITapGestureRecognizer手势截获Touch事件的问题!

PS:笔者对Tap手势外其他手势进行了测试,Pinch、Pan、Swipe、Rotation没有产生类似的问题,而Tap和LongPress产生了这样的问题。多谢Doralink提醒,写技术博客还是要写的全面一些。

Code=3000 "未找到应用程序的“aps-environment”的授权字符串" 解决办法

这个问题可能比较多出现,网上呢一股脑的方案是:描述文件,推送证书与项目中的bundle identifer 不一致,或者什么appid不一致呀,什么证书生成顺序不一致呀,什么xcode的code signing没有配置呀,就不写了,网上搜很多,我现在就把自己的问题说一下:

出现的背景是:原先的项目兼容iOS10,远程推送也用了最新的iOS10的推送框架,创建证书、描述文件的时候的appid,顺序啊,bundle identifer呀都正常

如果大家谁也出现这个问题了,不要忘记去看看xcode中的一个设置: 就是上图,记得看看打开没打开这个‘Push Notification’开关,打开之后,steps这两步骤会自动检查APP ID等推送文件的合法性。我的项目打开这个开关之后,验证也通过了,再运行,不会出现一开始‘Code=3000 “未找到应用程序的“aps-environment”的授权字符串”’的错误。 如果这两个step报错,就要去按照网上其他的重新设置provisioning profile,bundle identifer等,让其保持一致性。

results matching ""

    No results matching ""