Warning统计

Warning的一些案例统计

Posted by Ted on November 21, 2018

1、Block导致的循环引用

去除一方强引用即可

2、Block引起的循环引用误报

img

查看Marsony源码

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block {
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];
}

self并没有持有block,不会构成引用循环,这是Xcode9.3之后的误报。同样还有这种情况的有遍历的block;GCG的block、UIView animationBlock;

解决方案

2.1、将下划线形式_的实例变量变成点语法

// make.left.mas_greaterThanOrEqualTo(_circleNameLabel.mas_right);
   make.left.mas_greaterThanOrEqualTo(self.circleNameLabel.mas_right);

2.2、将这种类型的报警去除

img

3、不带参数的Block

Xcode 9之后如果定义一个不带参数的block,会有Warning

Warning:This block declaration is not a prototype

img

解决方案

3.1、加一个void参数

3.2、全部忽略

img

4、未被使用的变量

Unused variable ‘xxxx’

减少此类Warning有利于节省内存

5、指针未添加nullable标识

Warning:Pointer is missing a nullability type specifier (_Nonnull, _Nullable, or _Null_unspecified)

其实这是由于Swift的加入引起的问题:

我们都知道在swift中,可以使用!和?来表示一个对象是optional的还是non-optional,如view?和view!。而在Objective-C中则没有这一区分,view即可表示这个对象是optional,也可表示是non-optioanl。这样就会造成一个问题:在Swift与Objective-C混编时,Swift编译器并不知道一个Objective-C对象到底是optional还是non-optional,因此这种情况下编译器会隐式地将Objective-C的对象当成是non-optional。

解决方案

NS_ASSUME_NONNULL_BEGIN 

//代码

NS_ASSUME_NONNULL_END

6、通过Category来重写原类方法

Warning:Category is implementing a method which will also be implemented by its primary class

苹果的官方文档有写明

If the name of a method declared in a category is the same as a method in the original class, or a method in another category on the same class (or even a superclass), the behavior is undefined as to which method implementation is used at runtime。

如果通过Category来重写原类方法可能造成调用方法的不可预知性。

解决方案

6.1、如果是自定义类,用继承的方式父类方法;

6.2、非自定义类,用runtime的method swizzling来进行方法交换处理。

7、未定义方法

Warning:Method definition for ‘showEmptyRolesView:’ not found

如果在父类.h里声明某个方法,只在子类里重写实现,就会有这个Warning。应该在父类里也有一份实现,防止在使用父类时误用这个方法

8、精度缺失

implicit conversion loses integer precision ‘nsinteger’ (aka ‘long’) to ‘int’

#if __LP64__ || TARGET_OS_EMBEDDED || TARGET_OS_IPHONE || TARGET_OS_WIN32 || NS_BUILD_32_LIKE_64
typedef long NSInteger;
typedef unsigned long NSUInteger;
#else
typedef int NSInteger;
typedef unsigned int NSUInteger;
#endif

在不同机器上,定义不一样,官方API是推荐使用NSInteger而不是int/long

9、新的API

Warning:’UIScrollViewContentInsetAdjustmentNever’ is only available on iOS 11.0 or newer

加一个判断

if (@available(iOS 11.0, *)){}
else{}

10、库支持的版本过高

warning: object file …Classes/ProtocolBuffer/Libs/libprotobuff.a(java_message_field.o)) was built for newer iOS version (9.1) than being linked (8.0)

引用文件支持的最低版本比项目编译版本高

解决方案

10.1、重新编译库与项目编译版本匹配

10.2、Build Settions Other links Flags 中添加-w忽略掉

二、通过Clang来忽略警告

img

img

1、忽略一段代码的警告

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wimplicit-retain-self"

// 要忽略警告的代码

#pragma clang diagnostic pop

常用的忽略警告类型

字段 警告类型
-Wimplicit-retain-self 循环引用
-Wstrict-prototypes 不带参数的block
-Wshorten-64-to-32 精度缺失
-Wnullability-completeness 未添加nullable标识
-Wobjc-protocol-method-implementation Category重写原类方法
-Wdeprecated-implementations 方法被弃用
-Wdeprecated-declarations 字段被弃用
-W-documentation 注释有问题
-Wundeclared-selector 未定义方法
-Wincompatible-pointer-types 对象的指针类型不正确

2、忽略整个工程的警告类型

img

要修改一下“-Wimplicit-retain-self”换成“-Wno-implicit-retain-self”

3、忽略几个文件的警告:

可以在pch等具有大范围作用域的头文件中包含: #pragma clang diagnostic ignored “警告名称” 如果剔除了push与pop则后面所有的代码都具有强制消除警告作用