/OCEval

动态执行Objective-C. A tiny JIT Interpreter of Objective-C, dynamically run your code like eval().

Primary LanguageObjective-C

OCEval

Travis support

A tiny JIT Interpreter of Objective-C, dynamically run your code like eval().

中文介绍

Features

  • Run Objective-C code dynamically.
  • Support iOS & OS X.
  • Written by Objective-C.
  • Driven By Unit Tests.
  • Support part of Low-level APIs like block and C funtion.

Usage

Dynamically call Objective-C method

//Example 1
NSString *inputStr = @"return 1 + 3 <= 4 && [NSString string] != nil;";
NSNumber *result = [OCEval eval:inputStr];
NSAssert([result boolValue] == YES, nil);
//Example 2
NSString *inputStr = @"{NSArray *content = @[@6,@7,@8,@9,@1,@2,@3,@4];\
NSComparisonResult (^comparison)(id obj1, id obj2) = ^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {\
return [obj1 doubleValue] > [obj2 doubleValue];\
};\
content = [content sortedArrayUsingComparator:comparison];\
return content;\
}";
NSArray *result = [OCEval eval:inputStr];
NSAssert([result[6] intValue] == 8, nil);

Replace method implementation dynamically

//new implementation code,just call originalInvocation
NSString *viewDidLoad2 = @"{\
[originalInvocation invoke];\
";

[OCEval hookClass:@"ViewController"
         selector:@"viewDidLoad"
         argNames:@[]
          isClass:NO
   implementation:viewDidLoad2];

Even make a dynamical app

Theoretically we could make a whole application written by Objective-C and deliver it through the network. You could read the iOS demo for details.

Installation

Cocoapods

pod 'OCEval'

TO-DO List

Already supported syntax

  • if..else..,do..while..
  • for..in,for
  • @() @[] @{}
  • array[0] or dic[@""]
  • block
  • call C external function
  • mac application
  • i++,++i,i+=1
  • if(a){} : means if(a == nil){}
  • C struct: including CGRect,CGPoint,CGSize,NSRange etc.
  • [super doSth]

Not support yet

  • call C inline function
  • macro like #define xx or typedef: use original value instead.
  • ((YES)&&(NO)) : use (YES && NO) instead
  • [stringformat:@"%d",aInt] : use [stringformat:@"%@",[NSNumber numberWithInt:aInt]] instead
  • ?: : use if else instead
  • _propertyName : use self.propertyName instead
  • if (!a): use if(a == nil) instead

Warning

An app submission to Appstore including this framework will likely be rejected.

Dependency

  • libffi
  • Aspect