What's Wrong with My #If Target_Os_Simulator Code for Realm Path Definition

What's wrong with my #if TARGET_OS_SIMULATOR code for Realm path definition?

TARGET_IPHONE_SIMULATOR macro doesn't work in Swift.
What you want to do is like the following, right?

#if arch(i386) || arch(x86_64)
let device = false
let RealmDB = try! Realm(path: "/Users/Admin/Desktop/realm/Realm.realm")
#else
let device = true
let RealmDB = try! Realm()
#endif

How to detect if app is being built for device or simulator in Swift

Update 30/01/19

While this answer may work, the recommended solution for a static check (as clarified by several Apple engineers) is to define a custom compiler flag targeting iOS Simulators. For detailed instructions on how to do to it, see @mbelsky's answer.

Original answer

If you need a static check (e.g. not a runtime if/else) you can't detect the simulator directly, but you can detect iOS on a desktop architecture like follows

#if (arch(i386) || arch(x86_64)) && os(iOS)
...
#endif

After Swift 4.1 version

Latest use, now directly for all in one condition for all types of simulators need to apply only one condition -

#if targetEnvironment(simulator)
// your simulator code
#else
// your real device code
#endif

For more clarification, you can check Swift proposal SE-0190


For older version -

Clearly, this is false on a device, but it returns true for the iOS Simulator, as specified in the documentation:

The arch(i386) build configuration returns true when the code is compiled for the 32–bit iOS simulator.

If you are developing for a simulator other than iOS, you can simply vary the os parameter: e.g.

Detect the watchOS simulator

#if (arch(i386) || arch(x86_64)) && os(watchOS)
...
#endif

Detect the tvOS simulator

#if (arch(i386) || arch(x86_64)) && os(tvOS)
...
#endif

Or, even, detect any simulator

#if (arch(i386) || arch(x86_64)) && (os(iOS) || os(watchOS) || os(tvOS))
...
#endif

If you instead are ok with a runtime check, you can inspect the TARGET_OS_SIMULATOR variable (or TARGET_IPHONE_SIMULATOR in iOS 8 and below), which is truthy on a simulator.

Please notice that this is different and slightly more limited than using a preprocessor flag. For instance you won't be able to use it in place where a if/else is syntactically invalid (e.g. outside of functions scopes).

Say, for example, that you want to have different imports on the device and on the simulator. This is impossible with a dynamic check, whereas it's trivial with a static check.

#if (arch(i386) || arch(x86_64)) && os(iOS)
import Foo
#else
import Bar
#endif

Also, since the flag is replaced with a 0 or a 1 by the swift preprocessor, if you directly use it in a if/else expression the compiler will raise a warning about unreachable code.

In order to work around this warning, see one of the other answers.

Xcode building for iOS Simulator, but linking in an object file built for iOS, for architecture 'arm64'

Basically, you have to exclude arm64 for the simulator architecture, both from your project and the Pod project.

  • To do that, navigate to Build Settings of your project and add Any iOS Simulator SDK with value arm64 inside Excluded Architecture.

    Sample Image

OR

  • If you are using custom XCConfig files, you can simply add this line for excluding simulator architecture.

    EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64

    Then

    You have to do the same for the Pod project until all the Cocoa pod vendors are done adding following in their Podspec.

    s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
    s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }

    You can manually add the Excluded Architecture in your Pod project's Build Settings, but it will be overwritten when you
    use pod install.

    In place of this, you can add this snippet in your Podfile. It will write the necessary Build Settings every time you run pod install.

    post_install do |installer|
    installer.pods_project.build_configurations.each do |config|
    config.build_settings["EXCLUDED_ARCHS[sdk=iphonesimulator*]"] = "arm64"
    end
    end

iOS app with framework crashed on device, dyld: Library not loaded, Xcode 6 Beta

In the target's General tab, there is an Embedded Binaries field. When you add the framework there the crash is resolved.

Reference is here on Apple Developer Forums.

Should I use methods deprecated in 7.0 if the user's iOS version is below 7.0?

Use the older method. Method B won't be available under older versions of iOS. Deprecated methods rarely (never so far?) actually go away. The only example is the UIDevice uniqueIdentifier but even that didn't go away, it simply returns garbage now.

Of course you could do something like:

if ([someClass resondsToSelector(someNewerMethodSelector)]) {
// call the new method
} else {
// call the old method
}

Code like that will run the newer method if it exists or the old method if not. Similar checks can be made for newer classes too.

BTW - why spend the effort to support iOS 4.3 or even 5.x? Support iOS 7 and maybe iOS 6.x if you have a good reason. Unless you have a specific need or requirement, supporting 4.3 and 5.x is not worth your effort.

And if you do keep support for 4.3, you better test your app thoroughly on a device with 4.3 to be sure you don't accidentally call and 5.0+ APIs.

Command CompileSwiftSources failed with a nonzero exit code XCode 13

I had this problem surface in Xcode 13.0.

Mohamed Tarek's solution worked for me, but…

I was using cocoapods, so I needed a solution not blown away by pod install; or more specifically fixed with pod install.

Adding the following to the bottom of the Podfile resolved it.

post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
# some older pods don't support some architectures, anything over iOS 11 resolves that
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '12.0'
end
end
end

Error while creating realm object in swift

You need to define a migration block and perform a migration due to the fact that you have changed one of your Realm model classes. You don't actually need to do anything in the migration block, Realm can handle the migration itself, you just need to increase your schema version by 1.

In AppDelegate.swift, define the migration inside the didFinishLaunchingWithOptions function:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let config = Realm.Configuration(
// Set the new schema version. This must be greater than the previously used
// version (if you've never set a schema version before, the version is 0).
schemaVersion: 1,
// Set the block which will be called automatically when opening a Realm with
// a schema version lower than the one set above
migrationBlock: { migration, oldSchemaVersion in
// We haven’t migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// Nothing to do!
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
}
})

// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config

// Now that we've told Realm how to handle the schema change, opening the file
// will automatically perform the migration
let realm = try! Realm()
return true
}

The code is copied from the official documentation of Realm.

SpringBoot 2 the elements were left unbound

The problem is that you are using the @ConfigurationProperties in a wrong way. You use either @ConfigurationProperties or @Value but not both.

The solution either fix your class to be usable for @ConfigurationProperties or remove the @ConfigurationProperties annotation.

@Getter
@Setter
@Component
@ConfigurationProperties(prefix = "simulator.geo",ignoreUnknownFields = false)
public class VendorSimulatorProperties {

private String host = "http://localhost:8080/";
private String b12;
private String b13;
private String b21;
private String c6;

}

You need to fix the prefix it should be simulator.geo and your properties should be named after the keys in your file. You will also require setter next to the getter. However this will also need to change the rest of your configuration, to use the newly generated getters.

For you it is probably easier to remove @ConfigurationProperties as you weren't really using them in the first place.



Related Topics



Leave a reply



Submit