首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有可能对UIViewAlertForUnsatisfiableConstraints进行调整吗?

有可能对UIViewAlertForUnsatisfiableConstraints进行调整吗?
EN

Stack Overflow用户
提问于 2015-09-19 17:39:50
回答 2查看 505关注 0票数 1

我想知道UIViewAlertForUnsatisfiableConstraints是否是我可以使用的选择器。到目前为止,我只知道UIViewAlertForUnsatisfiableConstraints是一个符号,可以用来放置一个符号断点。但我在任何公共课堂上都找不到这个符号。有人知道它的位置吗?

请注意,我希望在单元测试中这样做,而不是在生产代码中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-09-20 08:41:58

由于UIViewAlertForUnsatisfiableConstraints是一个C函数,因此对它进行处理比典型的Objective方法需要更多的工作。

最简单的(大多数消息来源都说这是唯一可能的方法)是通过基板的MSHookFunction,然而,这需要一个越狱手机。如果这是一个有效的选项,我建议使用它来简单地挂起函数。

在非越狱环境中,需要高级运行时操作。由于某种原因,我真的很喜欢浪费时间来学习一门很快就会死掉的语言。因此,这是完整的解决方案!这个链接是一个巨大的帮助。

代码语言:javascript
复制
#import <dlfcn.h>
#import <objc/runtime.h>
#include <sys/mman.h>

int64_t originalOffset;
int64_t *origFunc;

void swizzled_UIViewAlertForUnsatisfiableConstraints(NSLayoutConstraint *offendingConstraint, NSArray *allConstraints) {
    // inject swizzle code here
    NSLog(@"swizzled!");

    // call the original function (if you want!)
    if (origFunc) {
        // replace jump instruction w/ the original memory offset
        *origFunc = originalOffset;
        ((void(*)(NSLayoutConstraint*, NSArray*))origFunc)(offendingConstraint, allConstraints);
    }
}

static inline BOOL swizzleAlertForUnsatisfiableConstraints() {

    // get the original function and hold onto it's memory offset
    origFunc = dlsym(RTLD_DEFAULT, "UIViewAlertForUnsatisfiableConstraints");
    if (!origFunc) {
        return NO;
    }
    originalOffset = *origFunc;

    // define the swizzled implementation
    int64_t *swizzledFunc = (int64_t*)&swizzled_UIViewAlertForUnsatisfiableConstraints;

    // make the memory containing the original funcion writable
    size_t pageSize = sysconf(_SC_PAGESIZE);
    uintptr_t start = (uintptr_t)origFunc;
    uintptr_t end = start + 1;
    uintptr_t pageStart = start & -pageSize;
    mprotect((void *)pageStart, end - pageStart, PROT_READ | PROT_WRITE | PROT_EXEC);

    //Calculate the relative offset needed for the jump instruction
    //Since relative jumps are calculated from the address of the next instruction,
    //  5 bytes must be added to the original address (jump instruction is 5 bytes)
    int64_t offset = (int64_t)swizzledFunc - ((int64_t)origFunc + 5 * sizeof(char));

    //Set the first instruction of the original function to be a jump
    //  to the replacement function.
    //E9 is the x86 opcode for an unconditional relative jump
    int64_t instruction = 0xe9 | offset << 8;
    *origFunc = instruction;

    return YES;
}
票数 3
EN

Stack Overflow用户

发布于 2015-11-03 15:23:33

我试过凯西的解决方案,效果很好,但只在模拟器上。ARM处理器有拇指模式,因此使用ARM B指令比使用x86 JMP要困难得多。

UIViewAlertForUnsatisfiableConstraints是从UIView的下面方法调用的。它似乎是在内部引擎委托中定义的。

代码语言:javascript
复制
- (void)engine:(NSISEngine *)arg1 willBreakConstraint:(id <NSISConstraint>)arg2 dueToMutuallyExclusiveConstraints:(NSArray *)arg3;

https://github.com/nst/iOS-Runtime-Headers/blob/6a384f6a219be448de8714f263a4c212516d52b6/Frameworks/UIKit.framework/UIView.h#L1108

https://github.com/nst/iOS-Runtime-Headers/blob/3dde29deb7000cfac59d3e5473a71557123f29ea/protocols/NSISEngineDelegate.h#L10

Swizzling方法比C func容易得多。

定义专用接口:

代码语言:javascript
复制
@interface UIView (UIConstraintBasedLayout_EngineDelegate_PrivateInterface)

- (void)engine:(id /* NSISEngine */)engine willBreakConstraint:(NSLayoutConstraint *)breakConstraint dueToMutuallyExclusiveConstraints:(NSArray<NSLayoutConstraint *> *)mutuallyExclusiveConstraints;

@end

然后,swizzle objc方法:

代码语言:javascript
复制
+ (void)swizzleAutoLayoutAlertMethod
{
    Class class = [UIView class];
    Method originalMethod = class_getInstanceMethod(class, @selector(engine:willBreakConstraint:dueToMutuallyExclusiveConstraints:));
    if (!originalMethod) {
        [NSException raise:NSInternalInconsistencyException format:@"This platform does not support Auto Layout or interface has been changed."];
    }
    Method swizzledMethod = class_getInstanceMethod(class, @selector(swizzled_engine:willBreakConstraint:dueToMutuallyExclusiveConstraints:));
    method_exchangeImplementations(swizzledMethod, originalMethod);
}

注意:我创建了用于自动布局的林特库,参考https://github.com/ypresto/AutoLayoutLint

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32671327

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档