iOS开发锦囊

1、判断是不是AppStore版本

1
2
3
4
5
6
7
- (BOOL)isAppStoreEnvironment {
#if TARGET_OS_IOS && !TARGET_IPHONE_SIMULATOR
    return ([[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"] == nil);
#endif

    return NO;
}

2、判断当前系统时区名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+ (NSString *)currentSystemTimeZoneName {
    static NSLock * methodLock;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        methodLock = [[NSLock alloc] init];
    });

    [methodLock lock];
    [NSTimeZone resetSystemTimeZone];
    NSString * systemTimeZoneName = [[NSTimeZone systemTimeZone].name copy];
    [methodLock unlock];

    return systemTimeZoneName;
}

3、安全的执行method

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/**
 * Performs selector on the target, only if the target and selector are non-nil,
 * as well as target responds to selector
 */
+ (void)safePerformSelector:(SEL)selector withTarget:(id)target object:(id)object object:(id)anotherObject {
    if (target == nil || selector == nil || ![target respondsToSelector:selector]) {
        return;
    }

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [target performSelector:selector withObject:object withObject:anotherObject];
#pragma clang diagnostic pop
}

4、主线程执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
+ (CLLocationManager *)_newSystemLocationManager {
    __ block CLLocationManager * manager = nil;

    // CLLocationManager should be created only on main thread, as it needs a run loop to serve delegate callbacks
    dispatch_block_t block = ^{
        manager = [[CLLocationManager alloc] init];
    };
    if ([NSThread currentThread].isMainThread) {
        block();
    } else {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
    return manager;
}

5、添加Block

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
- (void)addBlockForCurrentLocation:(PFLocationManagerLocationUpdateBlock)handler {
    @synchronized (self.blockSet) {
        [self.blockSet addObject:[handler copy]];
    }

    //
    // Abandon hope all ye who enter here.
    // Apparently, the CLLocationManager API is different for iOS/OSX/watchOS/tvOS up to the point,
    // where encapsulating pieces together just makes much more sense
    // than hard to human-parse compiled out pieces of the code.
    // This looks duplicated, slightly, but very much intentional.
    //
#if TARGET_OS_WATCH
    if ([self.bundle objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil) {
        [self.locationManager requestWhenInUseAuthorization];
    } else {
        [self.locationManager requestAlwaysAuthorization];
    }
    [self.locationManager requestLocation];
#elif TARGET_OS_TV
    [self.locationManager requestWhenInUseAuthorization];
    [self.locationManager requestLocation];
#elif TARGET_OS_IOS
    if ([self.locationManager respondsToSelector:@selector(requestAlwaysAuthorization)]) {
        if (self.application.applicationState != UIApplicationStateBackground &&
            [self.bundle objectForInfoDictionaryKey:@"NSLocationWhenInUseUsageDescription"] != nil) {
            [self.locationManager requestWhenInUseAuthorization];
        } else {
            [self.locationManager requestAlwaysAuthorization];
        }
    }
    [self.locationManager startUpdatingLocation];
#elif PF_TARGET_OS_OSX
    [self.locationManager startUpdatingLocation];
#endif
}

6、安全执行线程

1
2
3
4
5
6
7
8
#import <Foundation/Foundation.h>
extern dispatch_queue_t JPThreadsafetyCreateQueueForObject(id object);
extern void JPThreadsafetySafeDispatchSync(dispatch_queue_t queue, dispatch_block_t block);
#define JPThreadSafetyPerform(queue, block) ({                      \
    __ block typeof((block())) result;                              \
    JPThreadsafetySafeDispatchSync(queue, ^{ result = block(); }); \
    result;                                                        \
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#import "JPThreadsafety.h"

static void *const JPThreadsafetyQueueIDKey = (void *)&JPThreadsafetyQueueIDKey;

dispatch_queue_t JPThreadsafetyCreateQueueForObject(id object) {
    NSString* label = [NSStringFromClass([object class]) stringByAppendingString:@".synchronizationQueue"];
    dispatch_queue_t queue = dispatch_queue_create(label.UTF8String, DISPATCH_QUEUE_SERIAL);

    void* uuid = calloc(1, sizeof(uuid));
    dispatch_queue_set_specific(queue, JPThreadsafetyQueueIDKey, uuid, free);

    return queue;
}

void JPThreadsafetySafeDispatchSync(dispatch_queue_t queue, dispatch_block_t block) {
    void* uuidMine = dispatch_get_specific(JPThreadsafetyQueueIDKey);
    void* uuidOther = dispatch_queue_get_specific(queue, JPThreadsafetyQueueIDKey);

    if (uuidMine == uuidOther) {
        block();
    } else {
        dispatch_sync(queue, block);
    }
}

Comments