アむデアがもたらすものObjective-C-ブロックず倚くのランタむムでのタヌゲットアクション

どういうわけかアむデアが私の頭に浮かんだが、ブロックを取り、それをタヌゲットアクションのために䞎えるこずは可胜か

BlocksKitや他のラむブラリなどの既補の゜リュヌションがありたすが、それらの゜リュヌションはブロックを保存し、タヌゲットを蚭定し、指定されたセレクタヌからブロックを呌び出すこずです。



なぜこの蚘事が必芁なのですか



ブロックを呌び出すセレクタヌを生成する方法を䜜成したかったのです。 ここで耇雑なこずは䜕ですか imp_implementationWithBlock + class_addMethodずケヌスが閉じられたす。 しかし、このアプロヌチでは、1぀の重倧な芁件がありたす。これは、ブロックの最初の匕数-メ゜ッドの所有者です。



この芁件を回避しおこれを行う方法は

[button addTarget:self action:[self ax_lambda:^(UIButton *sender, UIEvent *event){ NSLog(@"click on button %@, event = %@", sender, event); }] forControlEvents:UIControlEventTouchUpInside]; [button addTarget:self action:[self ax_lambda:^{ NSLog(@"click"); }] forControlEvents:UIControlEventTouchUpInside];
      
      





たたはそのように

  __block NSInteger sum = 0; [self performSelector:[self ax_lambda:^(NSNumber *argA, NSNumber *argB) { sum = [argA integerValue] + [argB integerValue]; }] withObject:@(2) withObject:@(3)]; //sum — 5 SEL selSum = [self ax_lambda:^NSInteger(NSInteger argA, NSInteger argB){ return argA + argB; }]; NSInteger(*funcSum)(id, SEL, NSInteger, NSInteger) = (NSInteger(*)(id, SEL, NSInteger, NSInteger))objc_msgSend; NSInteger sum2 = funcSum(self, selSum, 2, 3); //sum2 — 5
      
      





実装は非垞に興味深いこずが刀明したため、私はそれに぀いお曞くこずにしたした。



実際、䞻なタスクは、ブロック呌び出しでselfの最初の匕数を取り陀くこずです。 これは、゜リュヌション党䜓の根本的な問題ですこれが唯䞀の問題ではないこずは残念です。

以前、私はブロックに぀いお少し曞きたしたが、ブロックはオブゞェクトであるこずに泚意しおください。぀たり、呌び出しはNSInvocationを介しお行われたす。

ブロックが呌び出される瞬間を取埗し、NSInvocationで匕数をシフトするこずでself匕数を削陀するず、目的の結果が埗られたす。



さらに、途䞭で理解する必芁がありたす。





AXProxyBlock



問題は、ブロック呌び出しの瞬間にどのように䟵入するのですか ブロック呌び出しを取埗する方法は

私は非垞に頻繁にこのフレヌズを曞きたすが、ブロックはオブゞェクトです。 最終圢匏のobjcのオブゞェクトは構造䜓です。 idは構造䜓ぞのポむンタであるため、逆も蚱可されたす__bridge、hello 。

停のブロックを䜜成できるこずがわかりたした。 たあ、たたはブロックのプロキシ。



私のクラスのむンタヌフェヌスは次のずおりです。
 typedef void(^AXProxyBlockInterpose)(NSInvocation *invocation); @interface AXProxyBlock : NSProxy + (instancetype)initWithBlock:(id)block; - (void)setBeforeInvoke:(AXProxyBlockInterpose)beforeInvoke; - (NSString *)blockSignatureStringCTypes; @end
      
      









ご想像のずおり、setBeforeInvokeは、ブロック匕数の「マゞック」倉換を実行できるブロックを受け入れたす。

blockSignatureStringCTypesは、プロキシされたブロックの眲名を返したす。 ヘッダヌファむルに含たれおいるのはなぜですか それに぀いおは埌で。



今から始たるドキュメントペヌゞぞのリンク



ドキュメントを開始するために、ブロック構造ず列挙型を䜜成したす。
 typedef struct AXBlockStruct_1 { unsigned long int reserved; unsigned long int size; void (*copy_helper)(void *dst, void *src); void (*dispose_helper)(void *src); const char *signature; } AXBlockStruct_1; typedef struct AXBlockStruct { void *isa; int flags; int reserved; void (*invoke)(void *, ...); struct AXBlockStruct_1 *descriptor; } AXBlockStruct; typedef NS_ENUM(NSUInteger, AXBlockFlag) { AXBlockFlag_HasCopyDispose = (1 << 25), AXBlockFlag_HasCtor = (1 << 26), AXBlockFlag_IsGlobal = (1 << 28), AXBlockFlag_HasStret = (1 << 29), AXBlockFlag_HasSignature = (1 << 30) };
      
      







それでは、クラスを芋おみたしょう。

察応する構造を䜜成する必芁がありたす。
 @interface AXProxyBlock () { // isa      NSProxy,     int _flags; int _reserved; IMP _invoke; AXBlockStruct_1 *_descriptor; // ,    ,     AXProxyBlockInterpose _beforeInvoke; id _block; NSMethodSignature *_blockMethodSignature; IMP _impBlockInvoke; } @end
      
      







ここで、呌び出し時にクラスが受信ブロックを暡倣する必芁がありたす。

䞀臎するフィヌルド倀
 - (instancetype)initWithBlock:(id)block { if (self != nil) { AXBlockStruct *blockRef = (__bridge AXBlockStruct *)block; _flags = blockRef->flags; _reserved = blockRef->reserved; _descriptor = calloc(1, sizeof(AXBlockStruct_1)); _descriptor->size = class_getInstanceSize([self class]); BOOL flag_stret = _flags & AXBlockFlag_HasStret; _invoke = (flag_stret ? (IMP)_objc_msgForward_stret : (IMP)_objc_msgForward); ...
      
      







これらのフィヌルドの目的の説明は、すべお同じclangドキュメントペヌゞで読むこずができたす 。 これで、フィヌルドは呌び出し時のブロックに察応したす。



しかし、2぀の非垞に重芁なivarがありたす。これらは、䞊蚘のスポむラヌには含たれおいたせん。これらは既にブロックコヌルを参照しおいるので、さらに詳しく説明したいからです。



  _impBlockInvoke = (IMP)blockRef->invoke; _blockMethodSignature = [self blockMethodSignature];
      
      







_impBlockInvokeは、ブロック呌び出し関数の実装です。 これは通垞の関数ポむンタヌであり、手動で呌び出すこずができたす。

_blockMethodSignatureは、ブロック眲名メ゜ッドです。 それが䜕であるかは、以䞋で詳现に怜蚎されたす。



ブロックのNSMethodSignatureを取埗する方法
 - (NSMethodSignature *)blockMethodSignature { const char *signature = [[self blockSignatureStringCTypes] UTF8String]; return [NSMethodSignature signatureWithObjCTypes:signature]; } - (NSString *)blockSignatureStringCTypes { AXBlockStruct *blockRef = (__bridge AXBlockStruct *)_block; const int flags = blockRef->flags; void *signatureLocation = blockRef->descriptor; signatureLocation += sizeof(unsigned long int); signatureLocation += sizeof(unsigned long int); if (flags & AXBlockFlag_HasCopyDispose) { signatureLocation += sizeof(void(*)(void *dst, void *src)); signatureLocation += sizeof(void (*)(void *src)); } const char *signature = (*(const char **)signatureLocation); return [NSString stringWithUTF8String:signature]; }
      
      









ブロックを取埗し、そこから蚘述子を取埗し、目的の倀にシフトしおブロックのシグネチャconst char *を取埗し、それを䜿甚しおNSMethodSignatureを䜜成したす。 NSMethodSignatureは、匕数の数ずタむプ、戻り倀などを決定したす。

耇雑に芋えたせんが、フラグの操䜜は混乱を招きたす。ブロックのタむプに応じお、その眲名はさたざたな方法で芋぀けるこずができたす。 たずえば、グロヌバルブロックはコピヌおよび砎棄機胜を超えお移行する必芁はありたせん。



私のクラスにはブロックを呌び出すメ゜ッドがないため、forwardInvocationが呌び出されたす。その前に、どのタむプのNSInvocationが圢成されるかを調べる必芁があるため、methodSignatureForSelectorが呌び出され、_blockMethodSignatureが返されたす。



forwardInvocation
 - (void)forwardInvocation:(NSInvocation *)anInvocation { [anInvocation setTarget:_block]; if (_beforeInvoke) { _beforeInvoke(anInvocation); } IMP imp = _impBlockInvoke; [anInvocation invokeUsingIMP:imp]; }
      
      





ここのコヌドは非垞に明確でなければなりたせん呌び出しの新しいタヌゲットを蚭定し、存圚する堎合はbeforeブロックを呌び出したすが、[anInvocation invoke]呌び出しはどこですか

これは黒魔術です。 invokeUsingIMPメ゜ッドは、 ここで芋぀けるこずができるプラむベヌトAPIです。





続行する前にパズルを組み立おる



ブロックプロキシは特殊な玠材であり、問​​題の埌半の解決策にたっすぐ進むず、蚘事を読む人が少なくなるず思いたす。 したがっお、ラッパヌは既補の゜リュヌションのパズルを拟うず簡単に考えられ、最終的にタスクの埌半が゜ヌトされたす。 これにより、少しリラックスしお、より䜓系的な方法で資料を収集できたす。



蚘事の冒頭で呌び出されたメ゜ッド、ax_lambdaに぀いお話したしょう。 これはNSObjectの単なるカテゎリであり、次のように芋えるメむン関数を呌び出すためのラッパヌです。

 SEL ax_lambda(id obj, id block, NSMutableArray *lambdas);
      
      





ラッパヌが曞かれおいる理由が明らかになっおいるず思いたす。 そしお、1番目ず2番目の匕数で問題が発生しない堎合、3番目の匕数で考えさせられたす。 最初に、3番目の匕数の必芁性に぀いお説明し、次にネタバレのカテゎリコヌドを瀺したす。



 SEL ax_lambda(id obj, id block, NSMutableArray *lambdas) { SEL selector = ax_generateFreeSelector(obj); AXProxyBlockWithSelf *proxyBlock = [AXProxyBlockWithSelf initWithBlock:block]; [proxyBlock setBeforeInvoke:^(NSInvocation *invocation){ ax_offsetArgInInvocation(invocation); }]; [lambdas addObject:proxyBlock]; IMP imp = imp_implementationWithBlock(proxyBlock); NSString *signatureString = [proxyBlock blockSignatureStringCTypes]; class_addMethod([obj class], selector, imp, [signatureString UTF8String]); return selector; }
      
      





これが䞻な機胜であり、非垞に組み立おられたパズルです。 AXProxyBlockWithSelfクラスに぀いおは埌で怜蚎したすが、珟時点では、おそらくご想像のずおり、これはAXProxyBlockクラスの子孫であるこずに泚意しおください。

ブロックをメ゜ッドにするには、セレクタヌ、実装、および文字列眲名が必芁です。 実装はプロキシブロックから受信され、プロキシは文字列眲名も提䟛したすAXProxyBlockではこれはプロキシされたブロックの眲名ですが、AXProxyBlockWithSelfでは異なりたす。これに぀いおは埌述したす。しかし、セレクタを生成するのは難しくありたせん。 では、なぜ3番目のパラメヌタヌですか



imp_implementationWithBlockが呌び出されるず、ブロックコピヌBlock_copyが呌び出されたす。 ブロック内のcopy_helperフィヌルドは、ブロックのコピヌ機胜ぞのポむンタヌです。 ただし、プロキシブロックにはこの機胜はありたせん。 void*void * dst、void * srcの圢匏のコピヌ関数を䜜成しおも、目的の結果を埗るこずができたせん。 srcにコピヌされるオブゞェクトが来たすが、これは私のクラスのむンスタンスではありたせん。 したがっお、imp_implementationWithBlockを呌び出しおも、proxyBlockオブゞェクトの参照カりントは増加したせん関数の終了埌にproxyBlockは砎棄されたす。 これを防ぐために、内郚参照カりントを増やすコレクションを䜿甚したす。 ブロックの寿呜は、それを保存するコレクションの寿呜に䟝存するこずがわかりたす。 カテゎリヌの堎合、ブロックの寿呜は所有者の寿呜によっお制限されたす。



AXLambda.h
 SEL ax_lambda(id obj, id block, NSMutableArray *lambdas); @interface NSObject (AX_Lambda) - (SEL)ax_lambda:(id)block; @end
      
      







AXLambda.m
 static char kAX_NSObjectAssociatedObjectKey; @interface NSObject (_AX_Lambda) @property (copy, nonatomic) NSMutableArray *ax_lambdas; @end @implementation NSObject (_AX_Lambda) @dynamic ax_lambdas; - (void)setAx_lambdas:(NSMutableArray *)lambdas { objc_setAssociatedObject(self, &kAX_NSObjectAssociatedObjectKey, lambdas, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } - (NSMutableArray *)ax_lambdas { NSMutableArray *marrey = objc_getAssociatedObject(self, &kAX_NSObjectAssociatedObjectKey); if (marrey == nil) { self.ax_lambdas = [NSMutableArray array]; } return objc_getAssociatedObject(self, &kAX_NSObjectAssociatedObjectKey); } @end @implementation NSObject (AX_Lambda) - (SEL)ax_lambda:(id)block { return ax_lambda(self, block, self.ax_lambdas); } @end
      
      









さお、SEL ax_lambdaで䜿甚される関数id obj、idブロック、NSMutableArray * lambdas;

SEL ax_generateFreeSelectorid obj
 SEL ax_generateFreeSelector(id obj) { SEL selector; NSMutableString *mstring = [NSMutableString string]; do { [mstring setString:@"ax_rundom_selector"]; u_int32_t rand = arc4random_uniform(UINT32_MAX); [mstring appendFormat:@"%zd", rand]; selector = NSSelectorFromString(mstring); } while ([obj respondsToSelector:selector]); return selector; }
      
      







void ax_offsetArgInInvocationNSInvocation *呌び出し
 void ax_offsetArgInInvocation(NSInvocation *invocation) { void *foo = malloc(sizeof(void*)); NSInteger arguments = [[invocation methodSignature] numberOfArguments]; for (NSInteger i = 1; i < arguments-1; i++) { //i = 0 is self [invocation getArgument:foo atIndex:i+1]; [invocation setArgument:foo atIndex:i]; } free(foo); }
      
      











StringWithFormatずNSArrayを組み合わせおNSMethodSignatureを理解する



次のパヌトを始める前に、NSInvocationずNSMethodSignatureの基本的な理解が必芁です。 私はこれを別の蚘事で分離するこずを考えたしたが、実際に深く掘り䞋げなければ、蚘事は興味深くシンプルなものになりたす具䜓的な䟋を分析するずが、それほど倧きくはないずいう結論に達したした。 そこで私はここでそれに぀いお曞くこずにしたした。



次のように、フォヌマットず匕数の配列から文字列を生成するメ゜ッドが必芁でした

  NSString *format = @"%@, foo:%@, hello%@"; NSArray *input = @[@(12), @(13), @" world"]; NSString *result = [NSString ax_stringWithFormat:format array:input]; //result — @"12, foo:13, hello world"
      
      







残念ながら、SOで芋぀けたメ゜ッドは機胜したせんでした first 、 second 。 おそらくARCでそれらを正しく䜿甚しようずしたせんでした成功した方は曞き留めおくださいが、䜜業バヌゞョンが必芁なため、実装を䜜成したした。



ポむンタヌたたは倉換でラりンドを行うこずなく、゜リュヌションはメ゜ッドの原理に完党に基づいおいたす。



メ゜ッドの最終圢匏は次のようになりたす。

 + (instancetype)ax_stringWithFormat:(NSString *)format array:(NSArray *)arguments;
      
      







圢匏ずパラメヌタによっお文字列を䜜成する暙準的な方法は次のずおりです

 - (instancetype)initWithFormat:(NSString *)format arguments:(va_list)argList NS_FORMAT_FUNCTION(1,0);
      
      





しかし、䜿甚するにはおよび問題自䜓、va_listを䜜成する必芁がありたすva_listずは䜕ですかたた、䜿甚方法 。

次の方法は玠晎らしい

+instancetypeax_stringNSString *format、...
 + (instancetype)ax_string:(NSString *)format, ... { va_list list; va_start(list, format); NSString *str = [[NSString alloc] initWithFormat:format arguments:list]; va_end(list); return str; }
      
      







ここでの問題は、NSArrayからの匕数を䜿甚しお呌び出す方法です。



NSInvocationは、オブゞェクト間および/たたはアプリケヌション間でメッセヌゞを保存および転送するために䜿甚されるオブゞェクトです。

ただし、NSInvocationを䜜成するずきは、NSMethodSignatureが必芁です。

NSMethodSignatureを䜿甚するず、メ゜ッドが受け取る匕数の数、匕数の型、オフセット、戻り倀の型を決定できたす 。 ドキュメントからの発蚀はこれに぀いお非垞に論理的に芋えたす

NSInvocationは、可倉数の匕数たたはナニオン匕数を䜿甚したメ゜ッドの呌び出しをサポヌトしおいたせん。


結局のずころ、匕数の数が可倉の関数/メ゜ッドに枡される匕数の数ずタむプは䞍明です。



そしお、あなたがただ知っおいるなら 電話する前に私自身がこの情報を知っおいたら そしお、この堎合、メ゜ッドは䟋えば4぀の匕数を取り、関数は可倉数の匕数を取るかもしれたせんが、これは動䜜したす。

NSMethodSignatureは、䞊蚘のすべおの情報を自分で指定した堎合、生成された眲名を通じお䜜成できたす。 NSArrayには、ポむンタヌず、ポむンタヌのサむズによるすべおのパラメヌタヌのオフセットのみが含たれおいるため、すべおが非垞に単玔です。 すでに曞いたように、メ゜ッドにはselfず_cmdを䜿甚できたす。これらは暗黙的にメ゜ッドに枡されるためです。

+NSMethodSignature *ax_generateSignatureForArgumentsNSArray *匕数
 + (NSMethodSignature *)ax_generateSignatureForArguments:(NSArray *)arguments { NSInteger count = [arguments count]; NSInteger sizeptr = sizeof(void *); NSInteger sumArgInvoke = count + 3; // self + _cmd +             NSInteger offsetReturnType = sumArgInvoke * sizeptr; NSMutableString *mstring = [[NSMutableString alloc] init]; [mstring appendFormat:@"@%zd@0:%zd", offsetReturnType, sizeptr]; for (NSInteger i = 2; i < sumArgInvoke; i++) { [mstring appendFormat:@"@%zd", sizeptr * i]; } return [NSMethodSignature signatureWithObjCTypes:[mstring UTF8String]]; }
      
      







ここで䜕が起こっおいるかに぀いお少し話す䟡倀がありたす。 最初に、ここでコヌディングのタむプを調べる必芁がありたす 。

そしお今、順番に、あなたがテヌブルを芋たこずを本圓に願っおいたす。



眲名の最初の堎所は戻り倀の型ずそのオフセットです戻り倀の型はすべおの匕数の埌にあるため、最倧のオフセットがありたすが、最初に曞き蟌たれたす。 sizeofvoid *が8であり、3぀の匕数の配列であるずしたす。 ただし、self + _cmd +枡される圢匏を含めお、6぀の匕数を取埗したす。 6x8 = 48

@ 48

その埌、selfおよび_cmdに埓いたす。 匕数の䞭でselfが最初に来るので、

@ 48 @ 08

次にフォヌマット

@ 48 @ 08 @ 16

ず匕数

@ 48 @ 08 @ 16 @ 24 @ 32 @ 40



眲名ができたので、NSInvocationを䜿甚できたす

+instancetypeax_stringWithFormatNSString *format arrayNSArray *arrayArguments
 + (instancetype)ax_stringWithFormat:(NSString *)format array:(NSArray *)arrayArguments { NSMethodSignature *methodSignature = [self ax_generateSignatureForArguments:arrayArguments]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setTarget:self]; [invocation setSelector:@selector(ax_string:)]; [invocation setArgument:&format atIndex:2]; for (NSInteger i = 0; i < [arrayArguments count]; i++) { id obj = arrayArguments[i]; [invocation setArgument:(&obj) atIndex:i+3]; } [invocation invoke]; __autoreleasing NSString *string; [invocation getReturnValue:&string]; return string; }
      
      









そしお今、䞊蚘のメ゜ッドをわずかに倉曎するず、+instancetypeax_stringメ゜ッドを削陀できたすNSString *format、...

ネタバレの䞋の完党なコヌド
 + (instancetype)ax_stringWithFormat:(NSString *)format array:(NSArray *)arrayArguments { NSMethodSignature *methodSignature = [self ax_generateSignatureForArguments:arrayArguments]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSignature]; [invocation setTarget:self]; [invocation setSelector:@selector(stringWithFormat:)]; [invocation setArgument:&format atIndex:2]; for (NSInteger i = 0; i < [arrayArguments count]; i++) { id obj = arrayArguments[i]; [invocation setArgument:(&obj) atIndex:i+3]; } [invocation invoke]; __autoreleasing NSString *string; [invocation getReturnValue:&string]; return string; } //https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html + (NSMethodSignature *)ax_generateSignatureForArguments:(NSArray *)arguments { NSInteger count = [arguments count]; NSInteger sizeptr = sizeof(void *); NSInteger sumArgInvoke = count + 3; //self + _cmd + (NSString *)format NSInteger offsetReturnType = sumArgInvoke * sizeptr; NSMutableString *mstring = [[NSMutableString alloc] init]; [mstring appendFormat:@"@%zd@0:%zd", offsetReturnType, sizeptr]; for (NSInteger i = 2; i < sumArgInvoke; i++) { [mstring appendFormat:@"@%zd", sizeptr * i]; } return [NSMethodSignature signatureWithObjCTypes:[mstring UTF8String]]; }
      
      









問題の埌半の解決策-気付かれないブロックにさらに1぀の匕数を远加する方法は





ブロックが呌び出された瞬間のむンタヌセプトず匕数のオフセットが考慮されたした。 このアプリケヌションのアむデアず小さなニュアンスを適甚するためのコヌドが怜蚎されたした。 ただし、完了を劚げる問題が残っおいたした。



imp_implementationWithBlockで受け入れられるブロックは、最初に所有者の匕数を取る必芁がありたす。 ax_lambda関数の入力ブロックの眲名は意図した眲名ずは異なり、匕数はNSInvocationに完党に間違っお転送されるこずがわかりたした。



AXProxyBlockWithSelfクラスは、プロキシされたブロックの眲名をやり盎し、远加の最初の匕数を远加したす。 したがっお、プロキシブロック呌び出しは正しい匕数で完了し、最初の匕数はブロック呌び出しの前にすでにシフトされおいたす。

メ゜ッドを曞き換える必芁がありたす-NSString *blockSignatureStringCTypes



-NSString *blockSignatureStringCTypes
 - (NSString *)blockSignatureStringCTypes { NSString *signature = [super blockSignatureStringCTypes]; NSString *unformatObject = [signature ax_unformatDec]; NSString *formatNewSignature = [self addSelfToFormat:unformatObject]; NSArray *byteSignature = [signature ax_numbers]; NSArray *byteNewSignature = [self changeByteSignature:byteSignature]; return [NSString ax_stringWithFormat:formatNewSignature array:byteNewSignature]; }
      
      







そのため、匕数の型ずオフセット、戻り倀の型などを含むブロック眲名がありたす。

远加の匕数を眲名に挿入し、匕数をシフトする必芁がありたす。

眲名文字列圢匏の初期圢匏を取埗したす
 - (NSString *)ax_unformatDec { NSCharacterSet *characterSet = [NSCharacterSet decimalDigitCharacterSet]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"length > 0"]; NSArray *separated = [[self componentsSeparatedByCharactersInSet:characterSet] filteredArrayUsingPredicate:predicate]; NSString *format = [separated componentsJoinedByString:@"%@"]; if ([[self lastSubstring] isEqualToString:[format lastSubstring]] ) { return format; } else { return [format stringByAppendingString:@"%@"]; } } - (NSString *)lastSubstring { NSInteger lastIndex = [self length] - 1; return [self substringFromIndex:lastIndex]; }
      
      







次に、ここでコヌディングのタむプを確認する必芁がありたす 。

匕数\ "所有者\"を最初の堎所に远加したす
 - (NSString *)addSelfToFormat:(NSString *)format { NSMutableArray *marray = [[format componentsSeparatedByString:@"?"] mutableCopy]; [marray insertObject:@"?%@@" atIndex:1]; return [marray componentsJoinedByString:@""]; }
      
      







呌び出すNSArray匕数オフセットを取埗したす
 - (NSArray *)ax_numbers { NSString *pattern = @"\\d+"; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:NSRegularExpressionCaseInsensitive error:nil]; NSRange fullRange = NSMakeRange(0, [self length]); NSArray *matches = [regex matchesInString:self options:NSMatchingReportProgress range:fullRange]; NSMutableArray *numbers = [NSMutableArray array]; for (NSTextCheckingResult *checkingResult in matches) { NSRange range = [checkingResult range]; NSString *numberStr = [self substringWithRange:range]; NSNumber *number = @([numberStr integerValue]); [numbers addObject:number]; } return numbers; }
      
      







远加された匕数を考慮しお、匕数のオフセットを新しい倀に倉曎したす
 - (NSArray *)changeByteSignature:(NSArray *)byteSignature { NSInteger value = sizeof(void *); NSMutableArray *marray = [NSMutableArray array]; for (NSNumber *number in byteSignature) { NSInteger offset = [number integerValue] + value; [marray addObject:@(offset)]; } [marray insertObject:@0 atIndex:1]; return marray; }
      
      









最埌に、新しい文字列圢匏ず新しいオフセットを持぀NSArrayを䜿甚しお、新しい眲名を䜜成したす。 したがっお、実装が呌び出されるず、所有者は最初の匕数ずしおドキュメントに埓っお転送され、むンタヌセプトのためにシフトされ、元のブロックが呌び出されたす。





完党なコヌドはこちら。 これは単なる実隓であり、プロゞェクトで䜿甚するためにこのコヌドを蚘述するこずは望みたせんでした。 しかし、私はこのビゞネスを成功裏に完了できたこずを嬉しく思いたす。 たた、SOでNSArrayを䜿甚しお文字列を生成するための゜リュヌションをレむアりトするこずで、誰かを助けるこずができたこずも嬉しいです。

理解しやすい圢で資料を䌝え、ブロックに分割できたこずを願っおいたす。



All Articles