johnno1962 / injectionforxcode

Runtime Code Injection for Objective-C & Swift
MIT License
6.55k stars 565 forks source link

Why not support lazy loading? #295

Closed tigerAndBull closed 3 years ago

tigerAndBull commented 3 years ago
  1. If I use this method, it works.
    
    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    CGRect frame = CGRectMake(kScreenWidth - 100 - 20, 80, 100, 40);
    _refreshButton = [[UIButton alloc] initWithFrame:frame];
    [_refreshButton addTarget:self action:@selector(refreshAction) forControlEvents:UIControlEventTouchUpInside];
    [_refreshButton setTitle:@"refresh" forState:UIControlStateNormal];
    [_refreshButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
    [_refreshButton setBackgroundColor:UIColor.blackColor];
    [self.view addSubview:_refreshButton];
    }
  1. If I use lazy loading, it not work.
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self.view addSubview:self.refreshButton];
}

- (void)injected {
    [self viewDidLoad];
}

- (UIButton *)refreshButton {
    if (!_refreshButton) {
        CGRect frame = CGRectMake(kScreenWidth - 100 - 20, 80, 100, 40);
        _refreshButton = [[UIButton alloc] initWithFrame:frame];
        [_refreshButton addTarget:self action:@selector(refreshAction) forControlEvents:UIControlEventTouchUpInside];
        [_refreshButton setTitle:@"refresh" forState:UIControlStateNormal];
        [_refreshButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal];
        [_refreshButton setBackgroundColor:UIColor.blackColor];
    }
    return _refreshButton;
}

What's your principle? What is the cause?

johnno1962 commented 3 years ago

Hi, not sure what you are asking without being more of the code but shouldn’t:

    if (!refreshButton) {

be

    if (!_refreshButton) {
tigerAndBull commented 3 years ago

Hi, not sure what you are asking without being more of the code but shouldn’t:

    if (!refreshButton) {

be

    if (!_refreshButton) {

It has nothing to do with this matter. As mentioned above, I modified it.

johnno1962 commented 3 years ago

What happens? Error? No injection? Button does not appear?

tigerAndBull commented 3 years ago

What happens? Error? No injection? Button does not appear?

The button can be displayed, but it cannot be changed in real time, such as changing the background color.

johnno1962 commented 3 years ago

Isn’t that because it is cached?

tigerAndBull commented 3 years ago

Isn’t that because it is cached?

I agree with this, but I want to know how to solve this problem.

johnno1962 commented 3 years ago

When you say this what do you mean? I don’t understand exactly what the problem is.

tigerAndBull commented 3 years ago

When you say this what do you mean? I don’t understand exactly what the problem is.

If the button is created by lazy loading, changing the properties of the button with injection will not take effect in real time, and the injection will not report an error.

johnno1962 commented 3 years ago

Where is the code where you’re trying to change the color? In the injected() method?

GrayLand119 commented 3 years ago

I guess the resion is the function -(void)injected was only call viewDidLoad again, _refreshButton has been created before, so it's keeping in memonry, and if (!_refreshButton) will always get false, and return the _refreshButton directly. It would not run in the new codes your had modified. so it doesn’t work.

Original Message Sender: tigerAndBullnotifications@github.com Recipient: johnno1962/injectionforxcodeinjectionforxcode@noreply.github.com Cc: Subscribedsubscribed@noreply.github.com Date: Wednesday, Jul 15, 2020 11:15 Subject: [johnno1962/injectionforxcode] Why not support lazy loading? (#295)

If I use this method, it works.

tigerAndBull commented 3 years ago

I guess the resion is the function -(void)injected was only call viewDidLoad again, _refreshButton has been created before, so it's keeping in memonry, and if (!_refreshButton) will always get false, and return the _refreshButton directly. It would not run in the new codes your had modified. so it doesn’t work. Original Message Sender: tigerAndBullnotifications@github.com Recipient: johnno1962/injectionforxcodeinjectionforxcode@noreply.github.com Cc: Subscribedsubscribed@noreply.github.com Date: Wednesday, Jul 15, 2020 11:15 Subject: [johnno1962/injectionforxcode] Why not support lazy loading? (#295) If I use this method, it works. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. CGRect frame = CGRectMake(kScreenWidth - 100 - 20, 80, 100, 40); _refreshButton = [[UIButton alloc] initWithFrame:frame]; [_refreshButton addTarget:self action:@selector(refreshAction) forControlEvents:UIControlEventTouchUpInside]; [_refreshButton setTitle:@"refresh" forState:UIControlStateNormal]; [_refreshButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; [_refreshButton setBackgroundColor:UIColor.blackColor]; [self.view addSubview:_refreshButton]; } - (void)injected { [self viewDidLoad]; } If I use lazy loading, it not work. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [self.view addSubview:self.refreshButton]; } - (void)injected { [self viewDidLoad]; } - (UIButton *)refreshButton { if (!refreshButton) { CGRect frame = CGRectMake(kScreenWidth - 100 - 20, 80, 100, 40); _refreshButton = [[UIButton alloc] initWithFrame:frame]; [_refreshButton addTarget:self action:@selector(refreshAction) forControlEvents:UIControlEventTouchUpInside]; [_refreshButton setTitle:@"refresh" forState:UIControlStateNormal]; [_refreshButton setTitleColor:UIColor.whiteColor forState:UIControlStateNormal]; [_refreshButton setBackgroundColor:UIColor.blackColor]; } return _refreshButton; } What's your principle? What is the cause? — You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub, or unsubscribe.

If I follow the way below, the button doesn't exist, and the inject doesn't seem to work as expected.

- (void)injected {
    [_refreshButton removeFromSuperview];
    _refreshButton = nil;
    [super viewDidLoad];
}
johnno1962 commented 3 years ago

They printing out more NSLog messages when things are called so you can see what is going on.

GrayLand119 commented 3 years ago

Use [self viewDidLoad]; not [super viewDidLoad];

- (void)injected {
    [_refreshButton removeFromSuperview];
    _refreshButton = nil;
    // [super viewDidLoad];
    [self viewDidLoad];
}
tigerAndBull commented 3 years ago

Use [self viewDidLoad]; not [super viewDidLoad];

- (void)injected {
    [_refreshButton removeFromSuperview];
    _refreshButton = nil;
    // [super viewDidLoad];
    [self viewDidLoad];
}

I work,

Use [self viewDidLoad]; not [super viewDidLoad];

- (void)injected {
    [_refreshButton removeFromSuperview];
    _refreshButton = nil;
    // [super viewDidLoad];
    [self viewDidLoad];
}

Sorry, it's my negligence. It's already in effect. This kind of code can be added uniformly with runtime.

tigerAndBull commented 3 years ago

To summarize the solution: insert

[subViews removeFromSuperView];
subViews = nil;
[self viewDidLoad];

on function injected

Tips:subViews needs to query recursively.