• 首页
  • 关于
    • zerone-z photo

      zerone-z

      记录下自己学习的过程、点滴,也为了分享自己的收获。

    • Learn More
    • Email
    • Github
  • 博客
    • 博客
    • 标签
  • 随笔
  • 项目

iOS Tips

08 Sep 2016

Reading time ~2 minutes

Target预编译宏

  1. OTHER_CFLAGS (Other C Flags) 项目下的Target –> Build Setting –> Apple LLVM x.x - Custom Compiler Flags –> Other C Flags 下添加一个要定义的宏。 使用这个方法需要使用-D格式:-D[需要设置的宏]。没有中括号[]
  2. GCC_PREPROCESSOR_DEFINITIONS(Preprocessor Macros) 项目下的Target –> Build Setting –> Apple LLVM x.x - Preprocessing –> Preprocessor Macros(预编译宏) 下添加一个要定义的宏 在这个定义宏需要转译,如:

    // 定义替换为NSString类型
    MY_MACRO=@\"Hello!!\"
    // 定义替换后的类型是:NSNumber
    MY_NUMBER=@"123"
    // NSInteger类型
    MY_INTEGER=1
    
  3. INFPLIST_PREPROCESSOR_DEFINITIONS (Info.plist Preprocessor Definitions) 项目下的Target –> Build Setting –> Packaging –> Info.plist Preprocessor Definitions 下添加要定义的宏

弱引用

Object *__weak wself = self;
__weak __typeof(self) wself = self;
__weak __typeof__(self) wself = self;
typeof(self) __weak wself = self;

__typeof()与__typeof__()是C语言中的,typeof()是C语言的扩展部分。三个的用法相同。

nil Nil NULL NSNull

  • nil Objective-C对象(Object)为空 nil用来给Objective-C对象赋空值。如:
  NSObject *obj = nil;
  if (nil == objc) {
      NSLog(@"obj is nil");
  } else {
      NSLog(@"obj is not nil");
  }
  • Nil Objective-C类(Class)为空 Nil用来给Objective-C某一类赋空值。如:
  Class someClass = Nil;
  Class anotherClass = [NSString class];
  • NULL 基本的数据对象指针为空 NULL用来给C语言的各种基本数据类型指针赋空值。如:
  int *pointerToInt = NULL;
  char *pointerToChar = NULL;
  struct TreeNode *rootNode = NULL;
  • NSNull 空值对象
    NSNull用作解决集合类(NSArray、NSSet、NSDictionary)不能有nil值的缺陷。 集合对象无法包含 nil 作为其具体值,如NSArray、NSSet和NSDictionary。相应地,nil 值用一个特定的对象 NSNull 来表示。NSNull 提供了一个单一实例用于表示对象属性中的的nil值。NSNull的类:
@interface NSNull : NSObject <NSCopying, NSSecureCoding>

+ (NSNull *)null;

@end

GCD

在iOS 6.0或Mac OS X 10.8以前的版本中需要自己管理GCD对象,使用dispatch_release和dispatch_retain,ARC不会管理它们。 在iOS 6.0或Mac OS X 10.8 及以后的版本中,ARC可以管理GCD对象,不需要使用dispatch_release和dispatch_retain。 为了兼容iOS 6.0 或 Mac OS X 10.8以前及以后版本,我们应该这么写:

#if OS_OBJECT_USE_OBJC
@property (nonatomic, strong) dispatch_queue_t queue;
#else
@property (nonatomic, assign) dispatch_queue_t queue;
#endif

在dealloc中应该加入:

#if !OS_OBJECT_USE_OBJC
    dispatch_release(_queue);
#endif

OS_OBJECT_USE_OBJC这个宏是在sdk6.0及之后才有的,如果是之前的,则OS_OBJECT_USE_OBJC为0

UUID的创建

iOS系统提供的唯一标示符的方法。

CFUUID

从iOS2.0开始,CFUUID就已经出现了。它是CoreFoundation包中的一部分,因此API属于C语言风格。具体代码如下:

CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);
NSString *cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));

这里使用CFUUIDCreate创建的CFUUID值,系统并没有存储;每次调用该方法,系统都会返回一个新的唯一的标示符。

NSUUID

NSUUID在iOS 6中才出现,这跟CFUUID几乎完全一样,只不过它是Objective-C接口。具体调用代码如下:

NSString *uuid = [[NSUUID UUID] UUIDString];

这个跟CFUUID一样,系统也不会存储,每次调用的时候都会获得一个新的唯一标示符。

只用一个Pan手势来代替UISwipegesture的各各方向

- (void)pan:(UIPanGestureRecognizer *)sender
{
typedef NS_ENUM(NSUInteger, UIPanGestureRecognizerDirection) {
    UIPanGestureRecognizerDirectionUndefined,
    UIPanGestureRecognizerDirectionUp,
    UIPanGestureRecognizerDirectionDown,
    UIPanGestureRecognizerDirectionLeft,
    UIPanGestureRecognizerDirectionRight
};
static UIPanGestureRecognizerDirection direction = UIPanGestureRecognizerDirectionUndefined;
switch (sender.state) {
    case UIGestureRecognizerStateBegan: {
        if (direction == UIPanGestureRecognizerDirectionUndefined) {
            CGPoint velocity = [sender velocityInView:recognizer.view];
            BOOL isVerticalGesture = fabs(velocity.y) > fabs(velocity.x);
            if (isVerticalGesture) {
                if (velocity.y > 0) {
                    direction = UIPanGestureRecognizerDirectionDown;
                } else {
                    direction = UIPanGestureRecognizerDirectionUp;
                }
            }
            else {
                if (velocity.x > 0) {
                    direction = UIPanGestureRecognizerDirectionRight;
                } else {
                    direction = UIPanGestureRecognizerDirectionLeft;
                }
            }
        }
        break;
    }
    case UIGestureRecognizerStateChanged: {
        switch (direction) {
            case UIPanGestureRecognizerDirectionUp: {
                [self handleUpwardsGesture:sender];
                break;
            }
            case UIPanGestureRecognizerDirectionDown: {
                [self handleDownwardsGesture:sender];
                break;
            }
            case UIPanGestureRecognizerDirectionLeft: {
                [self handleLeftGesture:sender];
                break;
            }
            case UIPanGestureRecognizerDirectionRight: {
                [self handleRightGesture:sender];
                break;
            }
            default: {
                break;
            }
        }
        break;
    }
    case UIGestureRecognizerStateEnded: {
        direction = UIPanGestureRecognizerDirectionUndefined;
        break;
    }
    default:
        break;
}
}

改变UITableViewCell里的对勾颜色

self.tableView.tintColor = [UIColor redColor];

解决使用UIImagePickerController导致statusbar变黑

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
}

改变UITextField Placeholder的颜色和位置

继承UITextField,重写这个方法:

- (void) drawPlaceholderInRect:(CGRect)rect {
    [[UIColor blueColor] setFill];
    [self.placeholder drawInRect:rect withFont:self.font lineBreakMode:UILineBreakModeTailTruncation alignment:self.textAlignment];
}

获取的APNS推送设备Token数据转换为字符串

方法一:

NSMutableString *deviceTokenString1 = [NSMutableString string];
const char *bytes = deviceToken.bytes;
int iCount = deviceToken.length;
for (int i = 0; i < iCount; i++) {
    [deviceTokenString1 appendFormat:@"%02x", bytes[i]&0x000000FF];
}

NSLog(@"方式1:%@", deviceTokenString1);

方法二:

NSString *deviceTokenString2 = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]

                                 stringByReplacingOccurrencesOfString:@">" withString:@""]

                                stringByReplacingOccurrencesOfString:@" " withString:@""];

NSLog(@"方式2:%@", deviceTokenString2);

UIImage位置相关

UIImage的位置设置不要出现(.55、.25)等等位置,容易模糊图片,出现锯齿;

presentViewController

视图控制器B被本视图控制器(A)present,所以A的presentedViewController是ViewControllerB,B的presentingViewController是ViewController(即A)。

inline

在调用替换和增加方法时候,用到了关键字 inline , inline 是为了防止反汇编之后,在符号表里面看不到你所调用的该方法,否则别人可以通过篡改你的返回值来造成攻击,iOS安全–使用 static inline 方式编译函数,防止静态分析,特别是在使用swizzling的时候。

static inline void af_swizzleSelector(Class theClass, SEL originalSelector, SEL swizzledSelector) {
    Method originalMethod = class_getInstanceMethod(theClass, originalSelector);
    Method swizzledMethod = class_getInstanceMethod(theClass, swizzledSelector);
    method_exchangeImplementations(originalMethod, swizzledMethod);
}
 
static inline BOOL af_addMethod(Class theClass, SEL selector, Method method) {
    return class_addMethod(theClass, selector,  method_getImplementation(method),  method_getTypeEncoding(method));
}