zoukankan      html  css  js  c++  java
  • iOS开发——OC篇&常用问题解答(二)

    101、编译错误:ld: library notfound for -lPods

    当项目中使用了 cocoaPods 时,经常出现此错误(通常是 release 的时候)。

    这是由于 pod install 后,cocoaPods 会创建一个新的 workspace。你必须关闭项目并重新打开。问题即可解决。

    102、为什么 iOS 的时间总是比真实时间慢8小时       

    例 如,一个北京时间"2014-4-4 22:00"(字符串),需要转换成 NSDate。字符串转换成 NSDate 一般是通过 NSDateFormatter 进行的。而在 iOS 上 NSDate 以 GMT 时间存储,因此NSDateFormatter会自动将字符串当前时区的本地时间处理,即将被转换的北京时间(字符串"2014-4-4 22:00")换成 GMT 时间("2014-4-4 14:00")。如果直接把这个 NSDate(longlong,1970以来的秒数或毫秒数)传给服务器,服务器会把这个时间当成北京时间使用(实际上它却是GMT时间),这就导致时 间差了8小时。

    正确的做法是在这个 NSDate 的基础上加上时差。而时差的计算需要知道当前时区。[NSTimeZonesystemTimeZone]可以得到当前时区(东8区),然后用 secondsFromGMTForDate: 方法可获得这个时区(东8区)的时差(以秒计)。代码如下:

    NSDateFormatter* df=[NSDateFormatter new];

    //        [dfsetLocale:[NSLocale  currentLocale]];

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

            NSDate* date=[dfdateFromString:@"2014-4-4 22:00"];

            NSTimeZone *zone =[NSTimeZone systemTimeZone];

            NSInteger interval = [zonesecondsFromGMTForDate: date];

            NSDate *localeDate =[date  dateByAddingTimeInterval:interval];

           NSLog(@"%@",localeDate);

    103、禁止 UITableViewController 中键盘弹出动画

    TableViewController 中内置了键盘弹出动画的代码,当单元格中的输入控件弹出软键盘时,tableView 会自动向上滚动。但这个功能有时候会带来大麻烦,因为有时候输入控件会被滚动到不可视的地方。由于我们无法修改框架的代码,所以这种情况下我们必须放弃使 用 TableViewController(子类化),而改用一般的UIViewController+UITableView 代替。但有时候我们必须使用TableViewContrller——例如想使用它的静态单元格,则可以通过下列方法解决。在 UITableViewController 子类中覆盖 viewWillAppear 方法,禁用父类的 viewWillAppear 行为。即不要调用[superviewWillAppear:animated]一句:

    -(void)viewWillAppear:(BOOL)animated{

        // Override super method with don'tcall [super viewWillApper]

    }

    104、应该在什么时候使用 NSCache

    NSCache 会自动根据内存压力释放其中的某个缓存对象(例如视图被销毁,或者缓存的对象实在太多)。因此 NSCache 缓存的对象必须是可以重建的,例如这些对象——可以在需要时从网络上下载到的数据。否则,你不应当使用 NSCache——因为对象不知道什么时候就会被销毁了。

    因此,使用 NSCache 时必须注意,如果检索的对象在 cache 中不存在,我们必须重建一个:

    -(CachedObject)getCachedObject:(id)key{

        id* obj=[NSCacheObjectobjectForKey:key];

        if (cb==nil) {

           obj=[[CachedObjectalloc]init];  // Recreate cached object

           ……

        }

        return obj;

    }

    105、Pods 在 Xcode5 上Archive 的问题

    问题描述:

    Archive 时出现如下错误(debug 时可能是正常的):

    ld: library not found for -lPods

    问题是由于 Xcode5.x 现在会检测依赖项目的 architecture ,其设置必须和主项目一致,否则该依赖项目会被拒绝(即不会编译)。

    解决办法:

    在 Pods 项目的所有 target 下,将他们的 architecture 设置为和主项目一致。

    106、如何查看一个静态库支持的 Architecture

    使用“lipo -info 静态库文件”命令,例如:

    lipo -info Unrar4iOS

    然后终端会作如下显示:

    Architectures in the fat file: Unrar4iOS are: armv7 armv6 i386

    107、项目中引入某些静态库会导致在 Archive 时报“Undefined symbols forarchitecture armv7s/arm64”错误

    正如问题 105 所述。除了用问题 105 中的解决方法,还有一种解决办法。

    首 先查看该静态库的 Architecture(参考问题106)。然后修改 Scheme 为该静态库支持的 Architecture。然后修改 Buid Settings 中的 Build Active ArchitectureOnly(仅编译为所选的架构),将值改为 Yes。然后编译即可。

    108、Autolayout 下,UITableView 的高度不正确

    Autolayout 下,如果有导航栏,视图上的 UITableView 受 constraints 的限制,运行时高度被 constraints 重新设置为没有导航栏的高度。此时应该实现viewDidLayoutSubviews 方法,将 constraints 的影响排除:

    - (void)viewDidLayoutSubviews {

    _table.frame=CGRectMake(0,0,self.view.frame.size.width,self.view.frame.size.height);

    }

    109、如何修改默认返回按钮的title?

    假设导航为:A视图-->B视图

    如果要改变B视图返回到A视图的返回按钮的title,只需在A视图中使用如下代码:

    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:nil];

    B视图不用做任何操作。

    110、有一个空对象,但它既不是 nil,也不是 null?

    它是 NSNull。你可以打印这个对象(用 po 命令或者 NSLog),则打印结果是“<null>”,而不是“(null)”(nil 对象)。

    由于O-C 的集合对象中不允许插入空值(nil),而 NSNull 并不是 nil,所以就用NSNull 对象来表示这个集合为空(表示列表结束)。而且,与 nil 不同,发送消息给一个 NSNull 将导致异常。

    NSNull具有唯一的方法:[NSNull null]你可以用它来测试一个对象是不是 NSNull:

    BOOL isNSNull(id any){

        return [any isEqual:[NSNullnull]];

    }

        #import "a.h"

    #endif

    111、为什么在 IB 中设置 layer.borderColor 无用?

    我在 IB 中通过设置 UIView 的Runtime 属性,以获得一个圆角带红色边框的矩形效果,如下图所示:

    但是,borderColor 属性似乎是无效的,边框无法显示。

    layer.borderColor 是一个 CGColorRef 属性,而 Runtime 属性的颜色面板中得到的只能是 UIColor 属性,因此你无法在 IB 中设置 borderColor,而只能通过代码设置。

    112、在 Swift 中还可以使用 DLog 宏和 ALog 宏吗?

    在C和Objective-C中使用的复杂宏无法在Swift中使用。复杂宏是除了常量定义之外的宏,包含带括号的函数宏。我们可以定义全局函数来代替:
    func dLog(message: String, filename: String = __FILE__, function: String =__FUNCTION__, line: Int = __LINE__) {

        if DEBUG==1 {    

       println("[(filename.lastPathComponent):(line)] (function) -(message)")

        }

    }

    113、O-C 中的枚举在 Swift 中无法使用?

    出错:Enum case pattern cannot match values of the non-enum type '枚举名'

    截止到 Beta 5,Swift 只能映射O-C 中使用 NS_ENUM 宏定义的枚举类。因此对于所有typedef enum 方式定义的 O-C 枚举,都需要重新用 NS_NUM 定义:

    typedef enum {

        ChinaMobile = 0,    // MNC 00 02 07

        ChinaUnicom,        // MNC 01 06

        ChinaTelecom,       // MNC 03 04

        ChinaTietong,       // MNC 20

        Unknown

    } CarrierName;

    114、Swift 中不能使用 #ifdef 宏吗?

    Swift 中可以使用 #if/#else/#endif:

    #if DEBUG

        let a = 2

    #else

        let a = 3

    #endif

    但是 DEBUG 符号必须在 Other Swift Flags 中进行定义:

    115、textFieldShouldReturn 方法返回 YES 或者 NO 有什么不同?

    返回 YES, 将触发自动文本纠正和自动首字母大写(即苹果文档中所谓的默认行为),返回 NO则不会。

    116、如何改变 UITextView 的行高?

    首先设置 UITextView 的 layouManager.delegate:

    textView.layoutManager.delegate = self; // you'll need to declare you 

    然后在实现 delegate 方法:

    - (CGFloat)layoutManager:(NSLayoutManager *)layoutManagerlineSpacingAfterGlyphAtIndex:(NSUInteger)glyphIndexwithProposedLineFragmentRect:(CGRect)rect

    {

        return 4; // 这是行间距

    }

    117、修改 UITextView 的最小高度

    无 论你如何在 IB 中修改 UITextView 的frame 高度都是无用的。UITextView的最小高度是通过它的内容来计算的,它的最小高度等于单行高度。因此在 iOS 7 上可以通过设置其 textContainerInset(iOS 6 则是 contentInset)来修改最小高度:

     if (NSFoundationVersionNumber >NSFoundationVersionNumber_iOS_6_1) {

         self.textContainerInset =UIEdgeInsetsMake(4, 10, 4, 10);

    } else {

        self.contentInset =UIEdgeInsetsMake(4, 10, 4, 10);

    }

    117、 在插入图片(NSTextAttachment)后NSAttribtuedString 字体莫名被变小

    插入图片前字体:

    插入图片后:

    这是因为 NSTextAttachment 插入时是以上标形式插入的,这导致三个属性被修改:字体、baseline、 NSSuperscriptAttributeName。

    因此在插入图片后,需要将这3个值改为默认(光修改字体不行):

    [mutableAttrString addAttributes:

    @{NSFontAttributeName:[UIFontsystemFontOfSize:16],(id)kCTSuperscriptAttributeName:@0,NSBaselineOffsetAttributeName:@0}           range:NSMakeRange(0,mutableAttrString.length)];

    注意 NSSuperscriptAttributeName 在 iOS 中无效。因此需要用 CoreText 的 kCTSuperscriptAttributeName 代替。

    118、如何一次性向导航控制器中压入两个 ViewController?

    只需这样:

    [viewController1.navigationController pushViewController:viewController2animated:NO];

    [viewController2.navigationController pushViewController:viewController3animated:YES];

    第一次 PUSH 时不带动画,第二次 PUSH 时带动画,这样用户会觉得只 PUSH 了一个ViewController,而实际上你 PUSH 了两个。

    119、统计整个工程代码行数

    打开终端,用cd命令 定位到工程所在的目录,然后调用以下命名即可把每个源代码文件行数及总数统计出来:

    find . "(" -name "*.m" -or -name "*.mm" -or-name "*.cpp" -or -name "*.h" -or -name "*.rss"")" -print | xargs wc -l

    其中,-name  "*.m" 就表示扩展名为.m的文件。同时要统计java文件和xml文件的命令分别是:

    find . "(" -name "*.java"  ")" -print | xargs wc -l

    find . "(" -name "*.xml"  ")" -print | xargs wc -l

    120、如何减少 requireGestureRecognizerToFail 方法的延时?

    requireGestureRecognizerToFail一般用于区别单击和双击的识别。假设你有两个手势,一个单击一个双击,你不想在用户双击时同时被识别为单击双击,可以使用下列代码:

    UITapGestureRecognizer *doubleTapGestureRecognizer =[[UITapGestureRecognizer alloc]

                           initWithTarget:self action:@selector(handleDoubleTap:)];

    doubleTapGestureRecognizer.numberOfTapsRequired = 2;

    [self addGestureRecognizer:doubleTapGestureRecognizer];

    UITapGestureRecognizer *singleTapGestureRecognizer =[[UITapGestureRecognizer alloc] initWithTarget:selfaction:@selector(handleSingleTap:)];

    singleTapGestureRecognizer.numberOfTapsRequired = 1;

    [singleTapGestureRecognizer requireGestureRecognizerToFail: doubleTapGestureRecognizer];

     [selfaddGestureRecognizer:singleTapGestureRecognizer];

    但 是这个方法有个致命的缺点,由于每次单击都要先进行双击的识别,而且要等双击识别失败才进行单击的处理,导致每次单击都会有一个延迟,一般这个时间会是 0.35 秒。尽管 0.35 秒很短,但用户能感到明显的延迟。因此我们需要重载 TapGestureRecognizer,减少这个延时:

    #import <UIKit/UIGestureRecognizerSubclass.h>

    #define UISHORT_TAP_MAX_DELAY 0.25

    @interface UIShortTapGestureRecognizer : UITapGestureRecognizer

    @property(nonatomic,assign)float maxDelay;

    @end

     #import"UIShortTapGestureRecognizer.h"

    @implementation UIShortTapGestureRecognizer

    - (instancetype)initWithTarget:(NSObject*)target action:(SEL)selector{

        self=[super initWithTarget:targetaction:selector];

        if (self) {

           self.maxDelay=UISHORT_TAP_MAX_DELAY;

        }

        return self;

    }

    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

    {

        [super touchesBegan:toucheswithEvent:event];

        dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(self.maxDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^

                       {

                           // 0.1 秒后,宣告手势识别失败

                           if  (self.state !=UIGestureRecognizerStateRecognized)

                           {

                               self.state= UIGestureRecognizerStateFailed;

                           }

                       });

    }

    @end

    现在可以在实例化 UIShortTapGestureRecognizer 之后设置它的 maxDelay属性了。注意,这个值不要小于 0.2秒(用户必须非常快,否则无法完成双击动作),最佳为 0.25。

    121、如何将字典/数组转换为字符串?

    NSString* id2json(id dicOrArr){

        NSError *error;

        NSData *jsonData =

        [NSJSONSerialization

         dataWithJSONObject:dicOrArr

        options:NSJSONWritingPrettyPrinted // Pass 0 if you don't care about thereadability of the generated string

         error:&error];

       

        if (! jsonData) {

            DLog(@"Got an error:%@", error);

            return nil;

        } else {

            NSString *jsonString =[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];

            return jsonString;

        }

    }

    122、Xcode 6.1 GM,AudioToolbox 无法使用

    通常,我们在程序中习惯用 AudioToolbox 来播放较短的声音效果,例如这段代码,在 Xcode 6.0 中是可用的,但在 Xcode 6.1 GM 上会导致一个编译错误:

    func playSystemSound(soundName:String){// Tink.caf

        letsoundPath:String="/System/Library/Audio/UISounds/"+soundName

        var soundID:SystemSoundID = 0

        ifNSFileManager.defaultManager().fileExistsAtPath(soundPath) {

            let soundURL =NSURL(fileURLWithPath: soundPath)

           AudioServicesCreateSystemSoundID(soundURL as CFURL, &soundID)

           AudioServicesPlaySystemSound(soundID)

        }

    }

    只需将 AudioServicesCreateSystemSoundID(soundURL as CFURL, &soundID) 替换为:

    AudioServicesCreateSystemSoundID(soundURL, &soundID)

    123、升级为 Yosemite 后,Xcode6 无法运行模拟器

    升级为 Yosemite 后,Schema 中的所有模拟器消失,如下图所示,模拟器一栏仅剩下 iOS Device :

    此时,App 无法在模拟器上运行。

    解 决方法为,打开模拟器(方法:Xcode -> Open Developer Tool -> iOS ),此时会弹出一个 Unable to determine device 的错误,不用管,点击 OK。在模拟器菜单,Hardware -> Device ->Manage Devices…,弹出设备列表。点击左下角的 + 按钮,添加所需要的模拟器,然后点击 Create即可,如下图所示:

    124、集成Alamofire时出现错误:only supported on iOS 8.0 andlater

    将Alamofire的deployment target设置为和主项目的一样。

    125、错误:must register a nib or a class for the identifier

    当使用编程方法构建UITableViewCell时,需要注册该UITableViewCell的xib。在 viewDidLoad 方法中加入下句:

    [self.yourTableViewName registerNib:[UINibnibWithNibName:@"YourNibName" bundle:nil]

            forCellWithReuseIdentifier:@"YourIdentifierForCell"];

    如果UITableViewCell未使用xib,但该UITableViewCell有自定义的.m/.h文件,则使用下句替代:

    [self.tableView registerClass:[UITableViewCell class]forCellReuseIdentifier::@"Cell"];

    126、错误Undefined symbols for architecture armv7

    如果你在真机调试出现这个错误,在模拟器下没有这个错误。说明有某个lib库只有x86版本,而缺少armv7/armv6版本。查看错误所指向的库,用lipo –info 命令检查该.a文件的二进制信息。

    如果缺少armv6/armv7版本的.a文件,请重新编译一个armv7/armv6的.a文件添加到工程中。

    还可以用lipo –create –output命令将两个版本的.a文件融合成一个通用版.a文件放到工程中。

    此外,可能还需要检查Library Search Path设置,看.a文件的路径指向是否正确。

    127、错误Type 'String' does not conform to protocol 'IntervalType'

    当switch语句中对String? 进行匹配时出现此错误。例如:

    switch item.name {

                    case "到达现场时间":

    cellItems.append(item)default:

        break

    }

    修改为如下语句可解决此错误:

    if let name = item.name{

                    switch name {

                    case "到达现场时间":

    cellItems.append(item)default:

        break

                    }

     }

    128、pod update时经常出现错误:Attempt to read nonexistent folder

    cocoapod服务器被墙了,请使用代理或者VPN(推荐VPN)。

    129、ViewController类声明出现错误:initializer 'init(coder:)'must be provided by a subclass of UIViewController

    在你的ViewController中有某个属性声明时未赋予初值,而且也没有标记为可空。例如 varkPickerViewSize:CGSize,可修改为var kPickerViewSize:CGSize?即可消除此错误

    130、Swift中如何取得Dictionary的所有key?

    在NSDicationary中可以使用allKeys属性,在Dictionary中则使用keys属性:

    let array:[String] = [String](dictionary.keys)

    131、如何限制ScrollView在某个方向上不可滚动?

    例如,要限制x方向上不可滚动,可以实现UIScrollViewDelegate协议方法:

    func scrollViewDidScroll(scrollView: UIScrollView) {

            ifabs(scrollView.contentOffset.x) > 0 {

                scrollView.contentOffset= CGPointMake(0, scrollView.contentOffset.y)

            }

    }

    132、如何在Swift Framework目标中导入O-C框架

    以BmobSDK 为例(CommonCrypto等C/O-C框架也是一样的),当你将BmobSDK添加到Link Binary With Libraries中时,当你使用“importBmobSDK”语句时,出现错误:no such module

    如果你试图使用bridging headers导入BmobSDK,则会导致另一个错误。

    这是由于Swift Framework不支持bridging headers文件。

    解决这个问题,需要经过以下步骤:
    1) 在项目目录中创建BmobSDK目录,将BmobSDK.framework放到这个目录。同时在这个目录下创建一个module.map文件,内容如下:

    module BmobSDK [system] {

        header"/Users/kmyhy/Documents/Swift/code/第12章/kNote/BmobSDK/BmobSDK.framework/Headers/Bmob.h"

        link "BmobSDK"

        export *

    }

    这将允许我们将BmobSDK当做Swift module来使用。

    2) 在Build Settings中,找到Import Paths(SWIFT_INCLUDE_PATHS),增加BmobSDK目录。如下图所示:

    3)在swift文件中导入BmobSDK框架:

    import BmobSDK

    133、如何在App Extension中使用CocoaPods

    在 Podfile中加入此句:

    link_with '扩展的名字'

    添加bridging header文件,并设置Objective-C BridgingHeader。

    134、错误'xxx.pch' has been modified since the precompiled header was builterror in Xcode

    执行深度Clean(快捷键Option+Command+Shift+K)

    135、Document Provider扩展中,DocumentPickerViewController的documentStorageURL属性返回为nil。

    确认容器App,Document Provider扩展和File Provider扩展的App Groups设置正确,如果有任何惊叹号,请Fixed。

    136、插入和删除CollectionView中的Cell

    跟 TableView一样,我们可以用insertItemsAtIndexPaths()/deleteItemsAtIndexPaths()插入/删 除单元格。不同的是CollecionView不再支持beginUpdates()/endUpdates()操作。默认已支持插入/删除动画,如果不 想要默认动画效果,可以设置UIView的animationsEnabled属性:

    BOOL animationsEnabled = [UIView areAnimationsEnabled];

    [UIView setAnimationsEnabled:NO];

    [myCollectionView reloadItemsAtIndexPaths:myIndexPaths];

    [UIView setAnimationsEnabled:animationsEnabled];

    137、UIScrollView中的UICollectionView不会滚动

    检查UIScrollView是否被设置了delegate属性,同时检查在delegate中是否实现了scrollViewDidScroll方法。如果是,请删除该方法(仅仅取消delegate属性是不行的)。

    同时检查UICollectionView的宽度(或宽度约束)、高度(或高度约束),以及列表内容大小,因为当列表内容小于UICollectionView的宽(或高)时,该方向的滚动条不会出现。

    138、单元格使用UITableViewCellStyleValue1,为什么显示不正确?

    UITableViewCell 有几个内置的类型,如UITableViewCellStyleDefault、UITableViewCellStyleValue1、UITableViewCellStyleValue2。

    这 些Cell都是SDK预先配置的,它们呈现固定的内置样式,比如字体大小、颜色、对齐方式等。如果你在想修改这些配置,很可能显示不正常,比如有的文本一 下子能显示,一下子又不显示,或者一下子显示固有字体(及颜色),一下子(比如说点击单元格)又显示修改后的字体(及颜色)。

    在这种情况下,你最好定制自己的单元格(子类化)。

    139、boundingRectWithSize 计算出的尺寸不正确?

    注意提供正确的options参数。对于UILabel,至少需要使用UsesLineFragmentOrigin和UsesFontLeading两个选项:

    CGRect paragraphRect =

      [attributedTextboundingRectWithSize:CGSizeMake(300.f, CGFLOAT_MAX)

    options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)

      context:nil];

    140、Swift中无法对多个枚举值进行按位或(|)运算

    注意,这个问题在 iOS 8.3 SDK Beta 1 (12F5027d)中已解决。对于低于此版本的SDK,我们可以用以下代码代替:

    let options =unsafeBitCast(NSStringDrawingOptions.UsesLineFragmentOrigin.rawValue |

                       NSStringDrawingOptions.UsesFontLeading.rawValue,

                       NSStringDrawingOptions.self)

                    

    let frame = text.boundingRectWithSize(size, options:options, attributes:D,context:nil)

    本博客,专属!本博文由博主独立编写或者借鉴别人的好文章进行修改而成,如果不对的地方望指正,谢谢!
  • 相关阅读:
    201504051930_《移动APP框架——MUI——HTML5》
    201503121644_《ios直播协议相关》
    2010502260926_《avolon》
    201502251333_《avolon作用域》
    201502251308_《fekit》
    使用Eclipse下载CRaSH源代码
    网络流量监控工具
    Map的putAll方法验证
    bat脚本中%~dp0含义解释
    CD管理和检索软件比较
  • 原文地址:https://www.cnblogs.com/stronger-ios-lcx/p/5629051.html
Copyright © 2011-2022 走看看