技巧

1、使用函数指针调用OC函数
-(void)performSelector
{
    SEL selector = @selector(printImp);
    IMP imp = [self methodForSelector:selector];
    ((void(*)(id,SEL))imp)(self,selector);
}

-(void)printImp
{
    NSLog(@"MemoryCollectPerformance Print.....");
}

2、了解API以下的东西的话,依然可以利用Obj-C的runtime。 可以在这里看到 http://opensource.apple.com/source/objc4/objc4-493.11/runtime/ ,尤其是objc-runtime.m, 这里提供了很多学习用的"工具"。比如经典的method_exchangeImplementations(),您可以用它研究很多黑箱过程的来龙去脉。值得一提的是, 这种技巧(method swizzling)是合法的,可以在App Store 中使用! 苹果曾给使用了相关技巧的开发者发过邮件,表示出于安全性和稳定性最好不再使用, 但没有禁止。

 

3、界面布局

// 1、AutoLayout 手写
UIEdgeInsets padding = UIEdgeInsetsMake(0, 0, 10, 10);
self.tableView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraints:@[
  [NSLayoutConstraint constraintWithItem:self.tableView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1.0 constant:padding.top],
  [NSLayoutConstraint constraintWithItem:self.tableView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1.0 constant:padding.left],
  [NSLayoutConstraint constraintWithItem:self.tableView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1.0 constant:-padding.right],
  [NSLayoutConstraint constraintWithItem:self.tableView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeBottom multiplier:1.0 constant:-padding.bottom]]];
// 2、VFL
NSDictionary* views = NSDictionaryOfVariableBindings(_tableView);
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-10-[_tableView]-30-|" options:NSLayoutFormatAlignAllTop | NSLayoutAttributeBottom metrics:nil views:views]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[_tableView]-30-|" options:NSLayoutFormatAlignAllLeft | NSLayoutAttributeRight metrics:nil views:views]];
// 3、Masonry
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(300, 200));
}];
 //4、aotulayout(Xib)

3、定时器避免循环引用,不释放问题:

Timer持有Target, runloop持有 timer,如果不调用 invalidate 那么timer不会被ruloop释放

3.1、分类实现创建NStimer分类:

+ (NSTimer *)apm_scheduledTimerWithTimeInterval:(NSTimeInterval)ti userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo callback:(void (^)(void))block{
    return [self scheduledTimerWithTimeInterval:ti target:self selector:@selector(action:) userInfo:[block copy] repeats:yesOrNo];
}

+ (void)action:(NSTimer*)userInfo{
    void (^block)(void) = userInfo.userInfo;
    if (block) {
        block();
    }
}

3.2、创建一个类,让这个类弱引用target,同时实现TimerProtocol协议,具体使用定时器类也需要实现TimerProtocol协议:


@protocol TimerProtocol <NSObject>
- (void)timerInvoke;
@end

@interface TimeProxy : NSObject<TimerProtocol>
@property (nonatomic,weak) id<TimerProtocol> target;
@end

@implementation TimeProxy
- (void)timerInvoke{
    if([self.target respondsToSelector:@selector(timerInvoke)]){
        [self.target performSelector:@selector(timerInvoke)];
    }
}

@end

//具体引用定时器的实现类实现TimerProtocol协议,实现timerInvoke方法
TimeProxy* proxy = [TimeProxy new];
proxy.target = self;
self.timer = [NSTimer timerWithTimeInterval:1.0 target:proxy selector:@selector(timerInvoke) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

3.3、交给NSProxy子类NSTimerProxy去实现:

//这个是NSProxy的子类NSTimerProxy,_target就是实现能够响应定时器的selector
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [_target methodSignatureForSelector:selector];
}

- (void)forwardInvocation:(NSInvocation *)invocation {
    [invocation invokeWithTarget:_target];
}

//具体实现逻辑:
NSTimerProxy* proxy = [NSTimerProxy proxyWithTarget:self];
self.timer = [NSTimer timerWithTimeInterval:1.0 target:proxy selector:@selector(timerInvoke) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

4、

  Javascript和OC调用:
 4.1、在同一个JSContext环境下声明 JSContext* context = [[JSContext alloc] init];
 context["add"]  = ^(int a, int b){
    NSLog(@"add:a+b = %d",a+b);
 };
  4.1.1、[context evaluateScript:@"add(50,50)"];
  4.1.2、在js中调用add(50,50) 如:JSPatch就这样实现。需要[context evaluateScript:xxx.js] 才可以调用js中的function
 4.2、WKWebview和UIWebview(这里是WKWebview)
 4.2.1、实现WKScriptMessageHandler协议,注册[config.userContentController addScriptMessageHandler:self name:NSStringFromSelector(@selector(playSound))];
 4.2.2、js使用
      var messageToPost = {'key':'value','key2':'value2'};
    //window.webkit.messageHandlers.playSound.postMessage(messageToPost);
 4.2.3、在代理中实现
 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
     NSLog(@"%@", message.body);
     if ([message.name isEqualToString:NSStringFromSelector(@selector(playSound))]) {
         [self playSound];
     }
 }
 4.2.4、注意addScriptMessageHandler会引起循环引用;
4.3、JSExport
     定义一个继承JSExport协议的子协议JSubPrototocol:
    @protocol JSubPrototocol <JSExport>
    //注意多个参数的使用JSExportAs
    JSExportAs(fullName,- (void)fullName:(NSString*)name address:(NSString*)address);
    - (void)jsexportPrint;
    @end
    定义一个类concrete实现JSubPrototocol
    实例化JSContext* jsContext = [[JSContexnt alloc]init];
    jsContext[@"person"] = [[concrete alloc] init];
    确保调用js的地方处于同一jsContext中:
    person.fullName("aimsgmiss","四川省")
    person.jsexportPrint();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值