johnno1962 / InjectionIII

Re-write of Injection for Xcode in (mostly) Swift
MIT License
3.96k stars 312 forks source link

@IBOutlet nil and crash #428

Closed zuqiu123 closed 1 year ago

zuqiu123 commented 1 year ago

@IBOutlet var button: UIButton! @IBOutlet After parsing the control dragged on the storyboard

Procedure: command + s, pop vc, come back VC reports an error after parsing UIStoryboard(name: "aaaa").instantiateInitialViewController() Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

johnno1962 commented 1 year ago

Hi, I'm afraid that's nothing like enough information to be able to help you. What version of the injection App are you using? Is it device injection? Can you prepare an example project that shows the problem? Is it crashing inside the injection bundle or your code? If it's crashing inside the injection bundle you can clone the app project into /tmp to maybe get a line number.

zuqiu123 commented 1 year ago
class ViewController1: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let sceneStoryboard = UIStoryboard(name: "ViewController2", bundle: nil)
        let viewController2 = sceneStoryboard.instantiateInitialViewController()
        navigationController?.pushViewController(viewController2, animated: true)
    }
}

class ViewController2: UIViewController {
    @IBOutlet var button: UIButton!
    override func viewDidLoad() {
        super.viewDidLoad()
        // 1. change button button
        // 2. click nav left back button to ViewController1
        // 3. click ViewController1 view
        // 4. push ViewController2 crash
        //  this line crash    button.setTitle("xx", for: .normal)
        // Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
        button.setTitle("xx", for: .normal)
    }
}

1.Use the latest version of the current appstroe, but versions from long ago have this problem. 2.The simulator injection is used

johnno1962 commented 1 year ago

Hi, I'm sorry but I can't really help you track that down as it is very much in your code/a general iOS question. Where are you expecting button to be initialised? From the storyboard. If you want to take a step back start with the https://johnholdsworth.com/GettingStarted.zip project.

zuqiu123 commented 1 year ago

https://johnholdsworth.com/GettStarted.zip can't open Not Found The requested URL was not found on this server.

Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.

zuqiu123 commented 1 year ago

Our project uses cocoapod, pod to develop business components, then the main project pod imports a separate module, will this have an impact on the injection software InjectionIII? I just tried a new project and it is fine without pod import

zuqiu123 commented 1 year ago

I'm trying to locate the problem @IBOutlet var button: UIButton! Similar to this kind of component dragged out of the storyboard, why command + s and then exit and come back in,

Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

They all have this problem, so to speak, any component dragged out will encounter the problem of unwrapping crash. Do you have any good suggestions to locate this problem?

johnno1962 commented 1 year ago

CocoaPods should work provided how they are built is logged in the project build logs. I'm sorry but it is difficult to help you with the unwrap problem, I'm not very expert on storyboards. If you can replicate it in a small example project you can post, I can look at it.

zuqiu123 commented 1 year ago

Demo: https://github.com/zuqiu123/testCrashDemo.git

video: https://www.youtube.com/watch?v=E46kn1aR4J4&feature=youtu.be I hope the idol can help to see

johnno1962 commented 1 year ago

Thanks for the project. Unfortunately, when I try to install the Pods I get a BUS error :( Any chance you could prepare the examples without using CocoaPods which is unlikely to be the problem?


pod install
Analyzing dependencies
/Library/Ruby/Gems/2.6.0/gems/ffi-1.15.5/lib/ffi/library.rb:275: [BUG] Bus Error at 0x000000010491c000
ruby 2.6.10p210 (2022-04-12 revision 67958) [universal.arm64e-darwin21]

-- Crash Report log information --------------------------------------------
   See Crash Report log file under the one of following:
     * ~/Library/Logs/DiagnosticReports
     * /Library/Logs/DiagnosticReports
   for more details.
Don't forget to include the above Crash Report log file in bug reports.
zuqiu123 commented 1 year ago

This is the reason for ruby, you can refer to this https://github.com/rbenv/rbenv

You can run the project directly without the pod

johnno1962 commented 1 year ago

I think I'll give CocoaPods a miss. This end your project doesn't even offer an app target or start the simulator?

zuqiu123 commented 1 year ago
image

Idol Hello, you can click on this directly and run testCrashDemo.xcworkspace, you can refer to the video to see the problem

johnno1962 commented 1 year ago

The workspace file is only created if pod install succeeds. Can you commit the Workspace file?

johnno1962 commented 1 year ago

Ah, I see now, I'm in the wrong directory..

johnno1962 commented 1 year ago

No such module 'testCrashDemo'

zuqiu123 commented 1 year ago

Yes, testCrashDemo just a pod component, Running example needs to be in another directory

johnno1962 commented 1 year ago

I'm not going to get the Pods working. Check in the Pods?

zuqiu123 commented 1 year ago

To avoid misunderstandings, I'm going to record a video to help you reproduce and solve the problem. Just a moment

zuqiu123 commented 1 year ago

video: https://www.youtube.com/watch?v=ms-9FxXd3AI

johnno1962 commented 1 year ago

I'm sorry but I can't follow the video, read the text and you're going very fast. Perhaps you could check the files in.

zuqiu123 commented 1 year ago

idol you mean you can't understand my video right? Or can't watch it

johnno1962 commented 1 year ago

I can't see it properly. Just check the files in. I'm about at the limit of the amount of time I can spend on this.

zuqiu123 commented 1 year ago
image

File size is limited, which is why I have to upload to the video site, now you should be able to see it. video time just 3 min 👇🏻 https://www.youtube.com/watch?v=ms-9FxXd3AI

johnno1962 commented 1 year ago

Never mind, in your video you seem to be cloning another URL and copying it into the original project you sent me. I can't see the URL. Can you not either check the files in or write simple instructions outlining what the video is doing?

johnno1962 commented 1 year ago

Just.. check.. the.. files.. in or post a zip file here.

zuqiu123 commented 1 year ago

1.open testCrashDemo.xcworkspace

image

2.open InjectionIII -> open project-> Example

image
  1. click xcode run
  2. open InjectionIII -> add Directory-> testCrashDemo image
  3. Click on the blue background -> click on the orange background -> you can see the button text on the green background image

    6.After modifying the button text, press command + s

    image

    7.Click on the top left corner of the green background to return

    image

8.Click on the orange background to see the problem

image

Is this a clear description?

johnno1962 commented 1 year ago

Look, I'm very sorry, I'd really like to help you but I'm getting this error: image

johnno1962 commented 1 year ago

I re-cloned and Xcode un-confused itself. Your problem was this line:

        let myBundle = Bundle(for: ViewController2.self)

If you inject ViewController2, the bundle becomes the path to injection's temporary .dylib containing that class which doesn't contain the storyboard as its in the Pod framework. I fixed it by adding another file in the pod which wasn't being injected and using Bundle(for:) for a class in that file instead. Interesting problem.

zuqiu123 commented 1 year ago

Can I see your fix code?

johnno1962 commented 1 year ago

diff --git a/Example/Pods/Pods.xcodeproj/project.pbxproj b/Example/Pods/Pods.xcodeproj/project.pbxproj
index 9d2d9f3..ff6c696 100644
--- a/Example/Pods/Pods.xcodeproj/project.pbxproj
+++ b/Example/Pods/Pods.xcodeproj/project.pbxproj
@@ -16,6 +16,7 @@
                62972E65011BD4D49A89A3883ADF22D1 /* ViewController2.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4E8A59264D1781E300128C0DB8390C99 /* ViewController2.storyboard */; };
                7085C57BC153DE7112221B98240674D5 /* testCrashDemo-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = CB757A3B83586B8308478EE3D4345941 /* testCrashDemo-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; };
                9C89FF4CAA491983531B570A1BD13158 /* Pods-testCrashDemo_Example-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B633AB56E725590BF81B5B137F879 /* Pods-testCrashDemo_Example-dummy.m */; };
+               BB24A2DB29450C560038D50E /* File.swift in Sources */ = {isa = PBXBuildFile; fileRef = BB24A2DA29450C560038D50E /* File.swift */; };
                ED4944468122B8F95304B73D88245089 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C442708E4610FA2FEB72B09992FAB188 /* ViewController.swift */; };
                ED914EA02039AF08C21DDE5469CEE208 /* ViewController1.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6D17E5E1C21DB3A82649EDD50348A83B /* ViewController1.storyboard */; };
                F91B56B92D61E6B59C307F64E3B6C177 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; };
@@ -41,7 +42,7 @@
 /* Begin PBXFileReference section */
                026E5F5AA065D72E2586897877C03C7D /* Pods-testCrashDemo_Example */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-testCrashDemo_Example"; path = Pods_testCrashDemo_Example.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                02F450F0A631D080507FBB8263510A56 /* Pods-testCrashDemo_Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-testCrashDemo_Example.release.xcconfig"; sourceTree = "<group>"; };
-               0D29F9A04C565F48D7E6A035F2587701 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; path = LICENSE; sourceTree = "<group>"; };
+               0D29F9A04C565F48D7E6A035F2587701 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
                0F2B633AB56E725590BF81B5B137F879 /* Pods-testCrashDemo_Example-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-testCrashDemo_Example-dummy.m"; sourceTree = "<group>"; };
                116F357B92A0E0A630623FC7B6A518FE /* testCrashDemo-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "testCrashDemo-dummy.m"; sourceTree = "<group>"; };
                151F28B82EF19E4144EF39E0F7F1897E /* testCrashDemo */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = testCrashDemo; path = testCrashDemo.framework; sourceTree = BUILT_PRODUCTS_:240.933333333333, 69.9, 20, 0, 0, 0, 0, 1, 0, 8.8, 244.427, 2103768104, lastEstado, 2103768104, 01233cc94dcafabdee, 1670751315, 01007D64F4286395A45302ee01f400000000ffffff02bb022600000000fe0c000000000058000006a8000000140000000002ee22083d7f01003c0000000000000000004c0000001a000000000000000000000050a001006404c4010041d85dffffffffffffffffff, 9.0.11.11, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 75, 50, -255, -255, -255, -255, -255, 69.9, 55, 0, 0, -50, 0, 0, 8.8, 0, 1.704, 0, 20, 0, 0, 75, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 80, 1, 1, 60, 0, 0, 0, 0, 7.6, 0000000000011010, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 100, 1220, 4315229, 16777215, 16777215, 16777215, S0lbAK3QqyGudiICAAAADA==, dbs/S0lbAA==/colls/S0lbAK3QqyE=/docs/S0lbAK3QqyGudiICAAAADA==/, "31013dac-0000-0d00-0000-6395a4540000", attachments/, 1670751316
DIR; };
@@ -50,7 +51,7 @@
                27EB8072FC8B206313625FEE3336F4F8 /* Pods-testCrashDemo_Example-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-testCrashDemo_Example-frameworks.sh"; sourceTree = "<group>"; };
                2E5BDB7335EB54D248BFA71C7AF41EDF /* Pods-testCrashDemo_Tests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-testCrashDemo_Tests.release.xcconfig"; sourceTree = "<group>"; };
                390805DF64A1E496B1949146602D18E4 /* Pods-testCrashDemo_Tests-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-testCrashDemo_Tests-acknowledgements.plist"; sourceTree = "<group>"; };
-               40EFEE16C743151884C80FBB1410D487 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; path = README.md; sourceTree = "<group>"; };
+               40EFEE16C743151884C80FBB1410D487 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
                4699A16FEC754B47A11BC6D4BBFB24A9 /* Pods-testCrashDemo_Tests.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-testCrashDemo_Tests.modulemap"; sourceTree = "<group>"; };
                4758C0261B3C3B764431A1B428248193 /* Pods-testCrashDemo_Example-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-testCrashDemo_Example-acknowledgements.plist"; sourceTree = "<group>"; };
                4E8A59264D1781E300128C0DB8390C99 /* ViewController2.storyboard */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = file.storyboard; name = ViewController2.storyboard; path = testCrashDemo/Assets/ViewController2.storyboard; sourceTree = "<group>"; };
@@ -63,17 +64,18 @@
                7FB4B25DC6EFCCA7122CE3C05065B4C1 /* Pods-testCrashDemo_Tests */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = "Pods-testCrashDemo_Tests"; path = Pods_testCrashDemo_Tests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
                8C50E2B9BE7B34FC8D38932CA9EB5055 /* Pods-testCrashDemo_Tests-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-testCrashDemo_Tests-dummy.m"; sourceTree = "<group>"; };
                9C1D5652AFCAC2D4701D271B123D8422 /* Pods-testCrashDemo_Tests-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-testCrashDemo_Tests-Info.plist"; sourceTree = "<group>"; };
-               9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree
= SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
+               9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
                A34147CFBDCB1F7E2F2A6FB04C4CBAFF /* testCrashDemo-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "testCrashDemo-Info.plist"; sourceTree = "<group>"; };
                A5A6E4EDD4E81BA6BF017C4380B436D9 /* Pods-testCrashDemo_Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-testCrashDemo_Example.debug.xcconfig"; sourceTree = "<group>"; };
                AA3E0B97C7226E7EFF44A9D1070AB3EA /* Pods-testCrashDemo_Example-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-testCrashDemo_Example-umbrella.h"; sourceTree = "<group>"; };
+               BB24A2DA29450C560038D50E /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = "<group>"; };
                C442708E4610FA2FEB72B09992FAB188 /* ViewController.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ViewController.swift; path = testCrashDemo/Classes/ViewController.swift; sourceTree = "<group>"; };
                C4C1683F292F843B77617767F0271196 /* testCrashDemo.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = testCrashDemo.modulemap; sourceTree = "<group>"; };
                CB757A3B83586B8308478EE3D4345941 /* testCrashDemo-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "testCrashDemo-umbrella.h"; sourceTree = "<group>"; };
                E816B9B1605A024BEC4BF3C3562DC9FB /* Pods-testCrashDemo_Tests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-testCrashDemo_Tests.debug.xcconfig"; sourceTree = "<group>"; };
                ED4A707A2F7442E6DD4E2D7967B16EAD /* Pods-testCrashDemo_Example-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-testCrashDemo_Example-Info.plist"; sourceTree = "<group>"; };
                FC2B66934782B17485A33834355BC87D /* Pods-testCrashDemo_Example.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-testCrashDemo_Example.modulemap"; sourceTree = "<group>"; };
-               FFD8D20D4CFE7D65D6E6B0F76CD14C9D /* testCrashDemo.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; lastKnownFileType = text; path = testCrashDemo.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
+               FFD8D20D4CFE7D65D6E6B0F76CD14C9D /* testCrashDemo.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = testCrashDemo.podspec; sourceTree = "<group>"; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
 /* End PBXFileReference section */

 /* Begin PBXFrameworksBuildPhase section */
@@ -190,6 +192,7 @@
                                4E8A59264D1781E300128C0DB8390C99 /* ViewController2.storyboard */,
                                5F0CFF4165CC9FB1F547260750E4DD4F /* Pod */,
                                F69EBE9AAC56848F8448502460C73DFA /* Support Files */,
+                               BB24A2DA29450C560038D50E /* File.swift */,
                        );
                        name = testCrashDemo;
                        path = ../..;
@@ -384,6 +387,7 @@
                        buildActionMask = 2147483647;
                        files = (
                                02B2065D51C5682294AE69F143C73145 /* testCrashDemo-dummy.m in Sources */,
+                               BB24A2DB29450C560038D50E /* File.swift in Sources */,
                                ED4944468122B8F95304B73D88245089 /* ViewController.swift in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
@@ -568,8 +572,7 @@
                                MTL_FAST_MATH = YES;
                                PRODUCT_NAME = "$(TARGET_NAME)";
                                STRIP_INSTALLED_PRODUCT = NO;
-                               SWIFT_COMPILATION_MODE = wholemodule;
-                               SWIFT_OPTIMIZATION_LEVEL = "-O";
+                               SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
                                SWIFT_VERSION = 5.0;
                                SYMROOT = "${SRCROOT}/../build";
                        };
diff --git a/File.swift b/File.swift
index df6086a..94d1394 100644
--- a/File.swift
+++ b/File.swift
@@ -6,3 +6,6 @@
 //

 import Foundation
+
+public class ViewController3: UIViewController {
+}
diff --git a/testCrashDemo/Classes/ViewController.swift b/testCrashDemo/Classes/ViewController.swift
index bd6a021..453cb7d 100644
--- a/testCrashDemo/Classes/ViewController.swift
+++ b/testCrashDemo/Classes/ViewController.swift
@@ -14,9 +14,8 @@ public class ViewController1: UIViewController {

     }

-
     public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
-        let myBundle = Bundle(for: ViewController2.self)
+        let myBundle = Bundle(for: ViewController3.self)
         let vc = UIStoryboard(name: "ViewController2", bundle: myBundle).instantiateInitialViewController()!
         navigationController?.pushViewController(vc, animated: true)
     }
@@ -30,7 +29,11 @@ public class ViewController2: UIViewController {
     public override func viewDidLoad() {
         super.viewDidLoad()

-        button.setTitle("11", for: .normal)
+        button.setTitle("1aa1", for: .normal)
+    }
+
+    @objc func injected() {
+        viewDidLoad()
     }
 }
zuqiu123 commented 1 year ago

iOS is better because of you

johnno1962 commented 1 year ago

Thanks! I am better because of iOS.

zuqiu123 commented 1 year ago

idol hello, I found a new problem in this issue, when ViewController2 has properties text,var text: String = "" I go outside to assign a value

        let myBundle = Bundle(for: ViewController3.self)
        let vc = UIStoryboard(name: "ViewController2", bundle: myBundle).instantiateInitialViewController() as! ViewController2
        vc.text = "12345"

modify vc.text = "12345" => vc.text = "123456" conversion ViewController2 will fail, and then crash

image
johnno1962 commented 1 year ago

This is a known problem when you use a dynamic cast (as! or as?) to a class that has been injected. You either need to move the cast out of the file containing the class being injected or you could try setting the environment variable INJECTION_DYNAMIC_CAST which introduces some code which tries to resolve this but it doesn't always work. You are trying to do too much in too few files.