日常记录
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_group_leave(group);
NSLog(@"完成1");
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"都完成后,执行");
});
let workingQueue = DispatchQueue(__label: "my_queue", attr: nil)
let group = DispatchGroup()
group.enter()//把该任务添加到组队列中执行
workingQueue.async(group: group, qos: .default, flags: [], execute: {
})
group.notify(queue: .main) {
}
格式修改插件
XCFormat
常规的宏
#define NSLogRect(rect) NSLog(@"%s x:%.4f, y:%.4f, w:%.4f, h:%.4f", #rect, rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)
#define NSLogSize(size) NSLog(@"%s w:%.4f, h:%.4f", #size, size.width, size.height)
#define NSLogPoint(point) NSLog(@"%s x:%.4f, y:%.4f", #point, point.x, point.y)
屏蔽Xcode报错
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wundeclared-selector"//(具体报错内容)
{...}//可能出现报错的代码
#pragma clang diagnostic pop
weak&strong 宏的声明
留个坑,后面来辨别两种方式的优劣
快速定义宏
// weak obj
#define WEAK_OBJ(type) __weak typeof(type) weak##type = type;
// strong obj
#define STRONG_OBJ(type) __strong typeof(type) str##type = weak##type;
/**
weakify
*/
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool {} __weak __typeof__(object) weak ## _ ## object = object;
#else
#define weakify(object) autoreleasepool {} __block __typeof__(object) block ## _ ## object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try {} @finally {} {} __weak __typeof__(object) weak ## _ ## object = object;
#else
#define weakify(object) try {} @finally {} {} __block __typeof__(object) block ## _ ## object = object;
#endif
#endif
#endif
/**
strongify
*/
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool {} __typeof__(object) object = weak ## _ ## object;
#else
#define strongify(object) autoreleasepool {} __typeof__(object) object = block ## _ ## object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try {} @finally {} __typeof__(object) object = weak ## _ ## object;
#else
#define strongify(object) try {} @finally {} __typeof__(object) object = block ## _ ## object;
#endif
#endif
#endif
多代理模式
/// 伪代码
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
@interface Api ()
/// step.1 头部声明哈希数组
@property (nonatomic, strong) NSHashTable<id<ApiProtocol> > *protocolList;
@end
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// step.2 初始化
- (void)initialize{
self.protocolList = [NSHashTable weakObjectsHashTable];
}
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// step.3
///使用 -通常block接回调,做处理事件,利用数组分发
[adapter block:^(Result *_Nullable result) {
for (id<ApiProtocol> protocol in self.protocolList) {
if (protocol && [protocol respondsToSelector:@selector(onReceiveConfList:)]) {
///回归主函数
wkcf_dispatchMainThread(^{
///具体业务方法
[protocol onReceiveConfList:self.confListDic.allValues];
});
}
}
}];
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
简易的声音播放类
.h
#import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Player : NSObject
+ (instancetype)shareInstance;
+ (void)destructionInstance;
/// 播放本地音频
/// @param voiceName 音频文件名称
/// @param repeat 是否重复
- (void)playLocationVoiceWithName:(NSString *)voiceName repeat:(BOOL)repeat;
- (void)pause;
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, assign) BOOL repeat;
/// 是否在播放
@property (nonatomic, assign) BOOL playing;
@end
NS_ASSUME_NONNULL_END
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
.m
#import "Player.h"
@interface Player ()
@end
@implementation Player
static Player *instance = nil;
static dispatch_once_t onceToken;
+ (instancetype)shareInstance {
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
+ (void)destructionInstance {
instance = nil;
onceToken = 0;
}
- (instancetype)init {
if (self = [super init]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playToEndTime:) name:AVPlayerItemDidPlayToEndTimeNotification object:self.player.currentItem];
}
return self;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (void)playToEndTime:(NSNotification *)notification {
if (self.repeat) {
AVPlayerItem *playerItem = notification.object;
[playerItem seekToTime:kCMTimeZero completionHandler:^(BOOL finished) {
[self.player play];
self.playing = YES;
}];
}else {
self.playing = NO;
}
}
- (void)playLocationVoiceWithName:(NSString *)voiceName repeat:(BOOL)repeat {
self.repeat = repeat;
NSURL *url = [[NSBundle bundleForClass:[self class]] URLForResource:voiceName withExtension:nil];
[self setupPlayerWithUrl:url];
}
- (void)setupPlayerWithUrl:(NSURL *)url {
if (self.playing) {
NSLog(@"The music is playing");
return;
}
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:url];
self.player = [AVPlayer playerWithPlayerItem:playerItem];
self.playing = YES;
[self.player play];
}
- (void)pause {
if (self.playing) {
NSLog(@"---%s", __func__);
self.playing = NO;
[self.player pause];
}
}
@end
组件化-跨模块执行事件
///伪代码:
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// use
[self performService:@"LoginServiceProtocol" selectorName:@"showWindowLoading" param:nil];
///
- (void)performService:(NSString *)serviceName selectorName:(NSString *)selectorName param:(id)param {
///Protocol类 在macOS、iOS中略有不同
Protocol *serviceProtocol = NSProtocolFromString(serviceName);
///核心方法
Class classObj = [[ServicesManager shareInatane] createService:serviceProtocol];
SEL selector = NSSelectorFromString(selectorName);
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
if ([classObj respondsToSelector:selector]) {
[classObj performSelectorOnMainThread:selector withObject:param waitUntilDone:YES];
}
#pragma clang diagnostic pop
}
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
///.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ServicesManager : NSObject
+ (instancetype)shareInatane;
- (void)registerServicesWithPath:(NSString *)path;
- (void)registerService:(Protocol *)service implClass:(Class)implClass;
- (id)createService:(Protocol *)service;
- (id)createService:(Protocol *)service withServiceName:(NSString *_Nullable)serviceName;
- (nullable id)createService:(Protocol *)service withServiceName:(NSString *_Nullable)serviceName shouldCache:(BOOL)shouldCache;
@end
NS_ASSUME_NONNULL_END
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
///.m
#import "ServicesManager.h"
#import "ServiceProtocol.h"
#import <objc/runtime.h>
@interface ServicesManager ()
@property (nonatomic, strong) NSMutableDictionary *servicesDict;
@property (nonatomic, strong) NSRecursiveLock *lock;
@property (nonatomic, strong) NSMutableDictionary *servicesByName;
@end
NSString *const kServiceNameKey = @"service";
NSString *const kServiceImplementKey = @"implement";
@implementation ServicesManager
+ (instancetype)shareInatane{
static ServicesManager *instacne = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instacne = [[self alloc] init];
});
return instacne;
}
- (NSMutableDictionary *)servicesDict{
if (_servicesDict == nil) {
_servicesDict = @{}.mutableCopy;
}
return _servicesDict;
}
- (NSRecursiveLock *)lock{
if (_lock == nil) {
_lock = [[NSRecursiveLock alloc] init];
}
return _lock;
}
- (NSMutableDictionary *)servicesByName{
if (_servicesByName == nil) {
_servicesByName = @{}.mutableCopy;
}
return _servicesByName;
}
- (void)registerServicesWithPath:(NSString *)path{
NSString *plistPath = [[NSBundle mainBundle] pathForResource:path ofType:@"plist"];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle bundleForClass:[self class]] pathForResource:path ofType:@"plist"];
}
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
return;
}
NSArray *serviceList = [[NSArray alloc] initWithContentsOfFile:plistPath];
[self.lock lock];
for (NSDictionary *serviceDic in serviceList) {
NSString *protocolName = [serviceDic objectForKey:kServiceNameKey];
NSString *protocolImplClass = [serviceDic objectForKey:kServiceImplementKey];
if (protocolName.length > 0 && protocolImplClass.length > 0) {
[self.servicesDict setObject:protocolImplClass forKey:protocolName];
}
}
[self.lock unlock];
}
- (Class)serviceImplClass:(Protocol *)service{
NSString *serviceImpl = [[self servicesDict] objectForKey:NSStringFromProtocol(service)];
if (serviceImpl.length > 0) {
return NSClassFromString(serviceImpl);
}
return nil;
}
- (BOOL)checkValidService:(Protocol *)service{
NSString *serviceImpl = [[self servicesDict] objectForKey:NSStringFromProtocol(service)];
if (serviceImpl.length > 0) {
return YES;
}
return NO;
}
- (void)registerService:(Protocol *)service implClass:(Class)implClass{
if (![implClass conformsToProtocol:service]) {
return;
}
if ([self checkValidService:service]) {
return;
}
NSString *key = NSStringFromProtocol(service);
NSString *value = NSStringFromClass(implClass);
if (key.length > 0 && value.length > 0) {
[self.lock lock];
[self.servicesDict setObject:value forKey:key];
[self.lock unlock];
}
}
- (id)createService:(Protocol *)service{
return [self createService:service withServiceName:nil];
}
- (id)createService:(Protocol *)service withServiceName:(NSString *_Nullable)serviceName{
return [self createService:service withServiceName:serviceName shouldCache:YES];
}
- (nullable id)createService:(Protocol *)service withServiceName:(NSString *_Nullable)serviceName shouldCache:(BOOL)shouldCache{
if (serviceName == nil || serviceName.length == 0) {
serviceName = NSStringFromProtocol(service);
}
id implInstance = nil;
if (![self checkValidService:service]) {
return implInstance;
}
if (shouldCache) {
id protocolImpl = self.servicesByName[serviceName];
if (protocolImpl) {
return protocolImpl;
}
}
Class implClass = [self serviceImplClass:service];
if ([implClass conformsToProtocol:@protocol(WKCFServiceProtocol)]) {
if ([[implClass class] respondsToSelector:@selector(singleton)]) {
if ([[implClass class] singleton]) {
if ([[implClass class] respondsToSelector:@selector(shareInstance)]) {
implInstance = [[implClass class] shareInstance];
} else {
implInstance = [[implClass alloc] init];
}
if (shouldCache) {
[self.servicesByName setObject:implInstance forKey:serviceName];
}
return implInstance;
}
}
return [[implClass alloc] init];
}
return nil;
}
@end
block声明
因为自己太容易忘了,每次手打都弄错。粘贴一个在这儿,其他人可以跳过了哈。
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// typedef定义
typedef void(^SuccessCallback)(WKCFResponsModel *responsModel);
typedef void(^FailCallback)(NSError *error);
typedef void(^ProgressCallback)(float progress);
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
/// block方法穿参
+(void)slideverifycodeWithAccount:(NSString *)account
success:(void(^)(WKCFSlideModel * data)) success
fail:(void(^)(NSError *error)) fail;
+(void)getVerifyCodeWithAccount:(NSString *)account
token:(NSString *)token
success:(void(^)(WKCFSendCodeModel * data)) success
fail:(void(^)(NSError *error)) fail;
+(void)checkVerifyCodeWithAccount:(NSString *)account
code:(NSString *)code
success:(void(^)(WKCFSendCodeModel * data)) success
fail:(void(^)(NSError *error)) fail;
- (void)showInviteWithSetting:(void(^)(WKCFInvitationTabVC *tabVC))setting
selectedCallback:(InviteCallback)callback;
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
///block属性
@property (nonatomic, copy) void(^willCloseMediaSettingWindow)(void);
@property (nullable, nonatomic, copy) void(^touchBtnCompleteBlock)(NSButton *sender, WKCFSharedFloatingViewMode confCtrlMode);
@property (nonatomic, copy) void(^clickItemHandler)(void);
@property (nonatomic, copy) void(^clickMoreButton)(void);
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
button addBlock 分类
.h
#pragma -mark block action
@property(nonatomic ,copy) void(^block)(NSButton *);
-(void)addTapBlock:(void(^)(NSButton *btn))block;
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
.m
#pragma -mark block action
- (void)setBlock:(void(^)(NSButton *))block
{
objc_setAssociatedObject(self,@selector(block), block,OBJC_ASSOCIATION_COPY_NONATOMIC);
[self addTarget:self action:@selector(click:)];
}
- (void(^)(NSButton*))block
{
return objc_getAssociatedObject(self,@selector(block));
}
- (void)addTapBlock:(void(^)(NSButton*))block
{
self.block = block;
[self addTarget:self action:@selector(click:)];
}
- (void)click:(NSButton*)btn
{
if(self.block) {
self.block(btn);
}
}
///-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
macOS打开其他应用
NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
/// 文件名+时间戳
NSString *filePath = [path stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@.txt", WKCFLocalizedString(@"PARTICIPANT_PARTICIPANTS_LIST", @"与会者列表"), [NSString getCurrentTimestamp]]];
[contentStr writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];
[[NSWorkspace sharedWorkspace] openFile:filePath withApplication:@"TextEdit"];
网友评论