Masonry icon indicating copy to clipboard operation
Masonry copied to clipboard

v1.1.0 crash with UIView margins

Open CristianoCastro opened this issue 7 years ago • 43 comments

New Issue Checklist

🚫 If this template is not filled out your issue will be closed with no comment. 🚫

  • [x] I have looked at the Documentation
  • [x] I have filled out this issue template.

Issue Info

Info Value
Platform ios
Platform Version 9.X & 10.X
Masonry Version 1.1.0
Integration Method cocoapods

Issue Description

Crash: -[UIView mas_bottomMargin]: unrecognized selector sent to instance 0x7fe34460a6a0 Possibly other margin methods too.

Worked with Masonry v1.0.2

Edit: [UIView mas_bottomMargin] was working with Masonry 1.0.2 in XCodes 8.3.3 (8E3004b) and 9.0 (9A235), tested in devices and simulators iOS 9.X and 10.X. Using Masonry v1.1.0 crashes with unrecognized selector, in any of the XCodes and simulators mentioned above, even after Project -> clean + clean build folder + manually deleting derived data.

I'm using MAS_SHORTHAND_GLOBALS

A quick difference I see is in View+MASAdditions.h, when defining mas_xxxMargin, its within conditional block:

  • Masonry v1.0.2: #if TARGET_OS_IPHONE || TARGET_OS_TV
  • Masonry v1.1.0: #if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)

My application's __IPHONE_OS_VERSION_MIN_REQUIRED is 90000

Edit 2: I downloaded the repo and ran the Example project's Margins example and it did not crash. I then decided to create a simple test project to try and reproduce the crash and I was able to. My test project consisted of a Podfile with only Masonry 1.1.0 pod:

platform :ios, '9.0'

target 'test' do
  pod 'Masonry', '1.1.0'
end

My project's deployment target was 9.0 (and afterwards tested with 10.3), a single view controller with this code:

#import <Masonry/Masonry.h>

...

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    UIView *tmp = [[UIView alloc] init];
    tmp.backgroundColor = [UIColor blueColor];
    [self.view addSubview:tmp];
    [tmp mas_makeConstraints:^(MASConstraintMaker *make) {
        
        make.left.right.equalTo(self.view);
        make.height.equalTo(@20);
        make.bottom.equalTo(tmp.superview.mas_bottomMargin);
    }];
}

Crash:

2017-09-21 12:52:31.898 test[47946:212235] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView mas_bottomMargin]: unrecognized selector sent to instance 0x7ffcdda05420'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000010b0c4b0b __exceptionPreprocess + 171
	1   libobjc.A.dylib                     0x000000010ab29141 objc_exception_throw + 48
	2   CoreFoundation                      0x000000010b134134 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
	3   CoreFoundation                      0x000000010b04b840 ___forwarding___ + 1024
	4   CoreFoundation                      0x000000010b04b3b8 _CF_forwarding_prep_0 + 120
	5   test                                0x0000000108ca5940 __29-[ViewController viewDidLoad]_block_invoke + 608
	6   test                                0x0000000108cb7ada -[UIView(MASAdditions) mas_makeConstraints:] + 138
...

Edit 3: Sample project: test.zip

Edit 4: As @robertjpayne said, use_frameworks! could be used as workaround if you are able to (which isn't my case).

I've researched a bit more and found that, even though my Podfile states I target iOS 9, each individual pod has its own deployment target. I checked the Masonry pod and found it is targeting iOS 6, leading to the crash. My workaround was setting each pod minimum deployment target equal to my project's with a post install hook as such:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
      config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
    end
  end
end

Reference: https://stackoverflow.com/a/37289688/1077288

CristianoCastro avatar Sep 20 '17 15:09 CristianoCastro

It happens with me too

beloso avatar Sep 20 '17 15:09 beloso

This doesn't make much sense as the code here has hardly changed at all… Does it work with Xcode 9 and Masonry 1.0.2?

robertjpayne avatar Sep 21 '17 04:09 robertjpayne

Xcode 9.0 + Masonry 1.1.0 crashes, Clean -> Build, then goes OK, confused.

ghost avatar Sep 21 '17 05:09 ghost

@guofengld so it doesn't crash once you do a full clean + build? Sounds like a weird Xcode issue

robertjpayne avatar Sep 21 '17 05:09 robertjpayne

xcode 8.3.3 build the lasted version will cash when use XXXMargin . so i don't think so it's a weird xcode issuse.

jonz-tech avatar Sep 21 '17 06:09 jonz-tech

@jonz-tech have you tried a full clean? Including deleting your DerrivedData folder? It seems super suspicious because nothing about these API's changed.

robertjpayne avatar Sep 21 '17 06:09 robertjpayne

@robertjpayne "ios deployment_target" was set to "6.0", so __IPHONE_OS_VERSION_MIN_REQUIRED equals to 60000, mas_leftMargin、mas_rightMargin were not implemented, but they were declared 😂

ghost avatar Sep 21 '17 07:09 ghost

i had try. here is my issue.

https://github.com/SnapKit/Masonry/issues/460

i had checked your project .it seems nothing change, and still cause some problem. does the implement was missing in podspec?

jonz-tech avatar Sep 21 '17 10:09 jonz-tech

Updated issue to add some info about Xcode, devices tested and configurations

CristianoCastro avatar Sep 21 '17 10:09 CristianoCastro

@CristianoCastro super helpful thank you, I have no idea why it's letting the header go through but not the API, gah!

robertjpayne avatar Sep 21 '17 10:09 robertjpayne

@CristianoCastro just one last question -- does it crash on device? Or just simulators?

robertjpayne avatar Sep 21 '17 10:09 robertjpayne

Hrm I'm not really sure what to say here, if I clone this project and run the Masonry iOS Examples and tap into the Margins example it doesn't crash.

This is with shorthand mode on.

Whats your min deployment target set to?

robertjpayne avatar Sep 21 '17 10:09 robertjpayne

It crashes on simulators as well. We are testing our UI on the iPhone X simulator and it crashes there.

beloso avatar Sep 21 '17 10:09 beloso

@beloso can you try just downloading the .tar.gz of the v1.1.0 release and running the examples and tapping into the margins example?

I can't replicate the crash on my end…

robertjpayne avatar Sep 21 '17 10:09 robertjpayne

@robertjpayne updated issue to include results of running the example Margins and a test project

CristianoCastro avatar Sep 21 '17 12:09 CristianoCastro

@CristianoCastro If I had to bet I'd say it's Cocoapods and Xcode 9, are you using static libraries or frameworks with Cocoapods?

robertjpayne avatar Sep 21 '17 12:09 robertjpayne

@robertjpayne it also happens with XCode 8.3.3. I'm not using frameworks.

Another difference I've noticed is that the Example Margins uses [UIView bottomMargin] and not [UIView mas_bottomMargin] as I am:

make.bottom.equalTo(lastView.bottomMargin);

Still, if I change the Example Margins to use mas_bottomMargin it does not crash...

CristianoCastro avatar Sep 21 '17 12:09 CristianoCastro

Updated issue to include sample project that crashes

CristianoCastro avatar Sep 21 '17 12:09 CristianoCastro

@CristianoCastro hm yea so if you don't use_frameworks! with Cocoapods it doesn't load all the symbols. I'll have to see why these symbols are not being loaded via static lib

robertjpayne avatar Sep 21 '17 13:09 robertjpayne

So it appears if you use:

#if TARGET_OS_IPHONE || TARGET_OS_TV

The symbols are exported in a framework and a static lib properly. However if you use:

#if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 80000) || (__TV_OS_VERSION_MIN_REQUIRED >= 9000)

The symbols are not properly exported in a static lib.

The work around right now is to use_frameworks!

robertjpayne avatar Sep 21 '17 13:09 robertjpayne

I'm not 100% sure how to work around this - the reason the API's were changed is due to new warnings Xcode gives around the use of potentially unavailable attributes

robertjpayne avatar Sep 21 '17 13:09 robertjpayne

unfortunately for me I can't use_frameworks! because some pods don't play nice with it. I will see if I can find a better way

CristianoCastro avatar Sep 21 '17 14:09 CristianoCastro

updated issue with a workaround other than use_frameworks!

CristianoCastro avatar Sep 21 '17 15:09 CristianoCastro

@CristianoCastro Interesting, I wonder why Cocoapods is setting deployment targets to iOS 6…

robertjpayne avatar Sep 22 '17 13:09 robertjpayne

Probably because we have it in the pod spec, but Cocoapods should override this to whatever is higher :(

It must be doing that for frameworks and hence why it works with use_frameworks!

robertjpayne avatar Sep 22 '17 13:09 robertjpayne

These links below may explain CocoaPods's behaviour. It seems like it does something different with use_framework!. CocoaPods/CocoaPods#3454 CocoaPods/CocoaPods#4320

teerapap avatar Sep 28 '17 10:09 teerapap

@teerapap yea seems like a Cocoapods bug more than anything, I don't get why it isn't setting the min deployment target to the main app target…

robertjpayne avatar Sep 28 '17 11:09 robertjpayne

Can people please try to use master and let me know if this resolves the issue(s)? I reverted some availability macros (stuff may crash now rather than not work) and used Xcode 9's new NS_AVAILABLE macros where possible to allow for warnings.

robertjpayne avatar Sep 28 '17 13:09 robertjpayne

@robertjpayne the test project is working now when using the master branch, tested in XCode 9 on iOS 10 & 11. Though I have warnings about some enumerations in masonry being partial (I don't recall if they are new or not)

screen shot 2017-09-28 at 14 33 38

CristianoCastro avatar Sep 28 '17 13:09 CristianoCastro

cocoapods Masonry Version | 1.1.0
iOS Simulator 8.4 && 11.0 Xcode 8.3.3 + Xcode9.0

Podfile use setting blow

post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '8.0' end end end

It works well

hhyymm avatar Oct 23 '17 03:10 hhyymm