How can I set the default device to emulate in Ionic? - ios

I'm using Ionic to build an iOS app. Right now I'm testing how it behaves in an iPad 2, but doing this requires me to constantly need to write:
ionic emulate ios --target="iPad-2"
Is there a way to hard-code this somewhere in the ionic.project file or somewhere else so I can stop manually doing this? Thanks

I was going through the same issue and even though this question is a year old but it was the first thing I got through google and couldn't find the answer anywhere else. Here's what I did just because I don't want to use --target="iPhone-7" everytime.
To be clear for anyone who lands here wanting to just run on a specific ios device use the following:
ionic run ios --target="iXXX-X"
The iXXX-X would be one of the names you get from running
ios-sim showdevicetypes
for example:
ionic run ios --target="iPhone-7"
I wanted to have a solution to make iPhone-7 my default, so running the following would target iPhone-7 (My original default target is iPhone-SE):
ionic run ios
It seems like the default is hardcoded and so must be changed in the code.
I found this file: /platforms/ios/cordova/lib/run.js
In there you'll find a function called deployToSim, I changed it as follows:
function deployToSim(appPath, target) {
// Select target device for emulator. Default is 'iPhone-6'
if (!target) {
return require('./list-emulator-images').run()
.then(function(emulators) {
if (emulators.length > 0) {
target = emulators[0];
}
emulators.forEach(function(emulator) {
// this is the original condition
// if (emulator.indexOf('iPhone') === 0)
// change "iPhone" to the specific model you want, in my case it's iPhone-7
// Notice the comma in iPhone7, without comma it will take iPhone-7-plus instead
if (emulator.indexOf('iPhone-7,') === 0) {
target = emulator;
}
});
events.emit('log', 'No target specified for emulator. Deploying to ' + target + ' simulator');
return startSim(appPath, target);
});
} else {
return startSim(appPath, target);
}
}

Related

iOS Asynchronous Unit Testing (waitForExpectations failing) in Xcode 8 / Swift 3

I'm updating my Cocoapod that I developed to use Swift 3. Before I upgraded, all of my asynchronous unit tests were working perfectly fine. But now after upgrading, every single one of them immediately fail and I have no idea why. Here is what each one is structured like:
override func setUp() {
super.setUp()
validationExpectation = expectation(description: "Validation")
}
.
.
.
func testSymbolRequest(){
_ = MyCocoapod.makeSymbolRequest(symbol: "ABC", success: { (symbolObject) in
self.validationExpectation.fulfill()
XCTAssert(true)
}) { (error) in
self.validationExpectation.fulfill()
XCTFail(error.description)
}
waitForRequestToFinish()
}
.
.
.
func waitForRequestToFinish(){
waitForExpectations(timeout: 60.0) { (error) in
if let error = error {
XCTFail(error.localizedDescription)
}
}
}
The waitForExpectations function isn't waiting at all. It immediately fails after being called. I have also confirmed that is has nothing to do with my actual networking code and the requests work perfectly fine in my Cocoapod example project. I'm using Alamofire. I don't think that's the problem but I thought it might be worth mentioning. The error message that is printed out is "unknown error".
If you are trying to test your CocoaPod that you are developing, for some reason, the default testing target that it creates makes the waitForExpectations() function not work properly for that particular testing target. I was able to get it to finally work by doing these steps in order:
Delete the current testing target
Create a new testing target
Run a pod install and make sure the pod file is updated accordingly
Following these steps, I was able to get the waitForExpectations() to finally work within my network requests.

How do you hide the warnings in React Native iOS simulator?

I just upgraded my React Native and now the iOS simulator has a bunch of warnings. Besides fixing them, how do I hide these warnings so that I can see what's underneath?
According to React Native Documentation, you can hide warning messages by setting disableYellowBox to true like this:
console.disableYellowBox = true;
Update: React Native 0.63+
console.disableYellowBox is removed and now you can use:
import { LogBox } from 'react-native';
LogBox.ignoreLogs(['Warning: ...']); // Ignore log notification by message
LogBox.ignoreAllLogs();//Ignore all log notifications
to ignore all log notifications
A better way to selectively hide certain warnings (that indefinitely show up after an upgrade to the latest and greatest RN version) is to set console.ignoredYellowBox in a common JS file in your project. For example, after upgrading my project today to RN 0.25.1 I was seeing a lot of...
Warning: ReactNative.createElement is deprecated...
I still want to be able to see helpful warnings and error messages from React-Native, but I want to squash this particular warning because it's coming from an external npm library that hasn't yet incorporated the breaking changes in RN 0.25. So in my App.js I add this line...
// RN >= 0.63
import { LogBox } from 'react-native';
LogBox.ignoreLogs(['Warning: ...']);
// RN >= 0.52
import {YellowBox} from 'react-native';
YellowBox.ignoreWarnings(['Warning: ReactNative.createElement']);
// RN < 0.52
console.ignoredYellowBox = ['Warning: ReactNative.createElement'];
This way I still get other errors and warning helpful for my dev environment, but I no longer see that particular one.
To disable the yellow box place
console.disableYellowBox = true;
anywhere in your application. Typically in the root file so it will apply to both iOS and Android.
For example
export default class App extends React.Component {
render() {
console.disableYellowBox = true;
return (<View></View>);
}
}
add this line in your app main screen.
console.disableYellowBox = true;
for example:- in index.js file
import { AppRegistry } from 'react-native';
import './src/utils';
import App from './App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
console.disableYellowBox = true;
In your app.js file under any component's lifecycle method.like in componentDidmount()
you have to add both of these,excluding any will not work.
console.ignoredYellowBox = ['Warning: Each', 'Warning: Failed'];
console.disableYellowBox = true;
For me below lines worked currently I am using react native 0.64
import { LogBox } from 'react-native';
LogBox.ignoreLogs(['Warning: ...']); //Hide warnings
LogBox.ignoreAllLogs();//Hide all warning notifications on front-end
When adding your warning to specify exactly which warning to suppress, you need to exactly add the warning message, like so (random example)
LogBox.ignoreLogs([
'Warning: Failed prop type: Invalid props.style key `tintColor` supplied to `Text`.',
]);
Using single quotes instead of backticks around tintColor or Text, for example, will not work.
Add the following code in your index.js file
console.disableYellowBox = true;
import {AppRegistry} from 'react-native';
import App from './App';
import {name as appName} from './app.json';
console.disableYellowBox = true;
AppRegistry.registerComponent(appName, () => App);
If You're Trying to Quickly Demo the App.
If you want to hide them in a particular build because you're doing a demo or something, you can edit your Xcode scheme to make it a release build and these yellow warnings will not show up. Additionally, your app will run much faster.
You can edit the Scheme for your simulator and real device by doing the following:
In Project in XCode.
Product > Scheme > Edit Scheme...
Change Build Configuration from Debug to Release.
For those coming this way trying to disable red warnings from the console, that give absolutely useless information, as of feb/17, you can add this line of code somewhere
console.error = (error) => error.apply;
Disables all console.error
RN >= 0.62
import {LogBox} from 'react-native'
under the import, add
LogBox.ignoreLogs(['...']);
instead of '...',
you can write the warnings you want to hide.
For instance,
I had the warning VirtualizedLists should never be ....
then I can write as
LogBox.ignoreLogs(['VirtualizedLists']);
if you want to add another error, you can write as
LogBox.ignoreLogs(['VirtualizedLists','Warning:...']);
console.disableYellowBox = true;
this worked for application level Put it anywhere in index.js file
I found that even when I disabled specific warnings (yellow-box messages) using the above mentioned methods, the warnings were disabled on my mobile device, but they were still being logged to my console, which was very annoying and distracting.
To prevent warnings from being logged to your console, you can simply override the warn method on the console object.
// This will prevent all warnings from being logged
console.warn = () => {};
It is even possible to disable only specific warnings by testing the provided message:
// Hold a reference to the original function so that it can be called later
const originalWarn = console.warn;
console.warn = (message, ...optionalParams) => {
// Insure that we don't try to perform any string-only operations on
// a non-string type:
if (typeof message === 'string') {
// Check if the message contains the blacklisted substring
if (/Your blacklisted substring goes here/g.test(message))
{
// Don't log the value
return;
}
}
// Otherwise delegate to the original 'console.warn' function
originalWarn(message, ...optionalParams);
};
If you can't (or don't want to) use a Regular Expression to test the string, the indexOf method will work just as well:
// An index of -1 will be returned if the blacklisted substring was NOT found
if (message.indexOf('Your blacklisted substring goes here') > -1) {
// Don't log the message
return;
}
Be aware that this technique will filter all messages that go through the warn function regardless of where they originated from.
Because of this, be careful that you do not specify an overly generous blacklist that will suppress other meaningful errors that may originate from somewhere other than React Native.
Also, I believe that React Native uses the console.error method to log errors (red-box messages), so I'm assuming that this technique could be used to filter out specific errors as well.
Add in app.js
import LogBox from React Native
import {LogBox} from 'react-native';
and then..
LogBox.ignoreAllLogs()
To disable the yellow box place console.disableYellowBox = true; anywhere in your application. Typically in the root file so it will apply to both iOS and Android.
For get more details please check official document
console.disableYellowBox = true;
console.ignoredYellowBox = ['Warning: Each', 'Warning: Failed'];
In your AppDelegate.m file you can change this line :
jsCodeLocation = [NSURL URLWithString:#"http://localhost:8081/index.ios.bundle?platform=ios&dev=true"];
and replace dev=true by dev=false at the end.
Related: Suppress Xcode warnings from React Native library
(but not for your own code)
why: when initialising a new RN-app, the Xcode project contains closer to 100 warnings that is distracting noise (but probably harmless otherwise)
solution: set inhibit all warnings to yes under Build Settings for the relevant targets.
Disable warnings in Xcode from frameworks
https://github.com/facebook/react-native/issues/11736
I like to put the console.disableYellowBox = true on the file root, like App.
But this just when im on the development phase.
console.error = (error) => error.apply; // in the index.js
Some times rn 0.66 does not works Logbox. especially for VirtualizedLists should never be nested inside plain ScrollViews.
And also ignore red warnings.

XCode syntax highlighting in both conditions of preprocessor #if #else

My app uses a lib that won't build and/or run on a simulator so I effectively stubbed out the references to that lib by surrounding references with preprocessor directives like so:
#if !(TARGET_IPHONE_SIMULATOR)
//Do the real implementation
#else
//Do a dummy implementation for testing
XCode automatically checks to see what my current target is and evaluates the #if/#else which I guess is kind of nice. The problem is, it turns off syntax highlighting, autocomplete, etc for whichever condition is not going to be compiled. (For example if my current target is the simulator, the code inside the real implementation loses its highlighting)
My bad solution is changing the target so that whichever implementation I want to edit gets 'activated'. Is there a way to keep both of them highlighted at all times so I can seamlessly edit both?
If both implementations will compile for either target, then you could do something like this:
#if !(TARGET_IPHONE_SIMULATOR)
const bool simulator = false;
#else
const bool simulator = true;
#endif
if (simulator)
{
//Do a dummy implementation for testing
}
else
{
//Do the real implementation
}
Both branches will be compiled, although the optimizer should throw away the one which can never be used for a given target.
If code using the library can't even be built when the target is the simulator, you can do something like this:
#if !TARGET_IPHONE_SIMULATOR
if (true)
{
//Do the real implementation
}
else
#endif
{
//Do a dummy implementation for testing
}
In this case, the real implementation still won't be syntax colored or support completion when targeting the simulator, but both branches will have those when targeting the device.
You could also implement a dummy version of the library for the simulator. You would have it define all of the interfaces, but everything would just return failure or even throw exceptions. You would use #if TARGET_IPHONE_SIMULATOR around all of the code so that the library ends up completely empty for device builds. Then, you would link against that and use the first approach.

Using new features while supporting older iOS versions

I am developing an app using SDK 8.1, Apple LLVM 6.0 and Xcode 6.1.1. The deployment target is 6.0. I'm using NSOperationQueue and I want to use QoS whenever it's available.
The code I'm using is:
if ([self.operationQueue respondsToSelector:#selector(setQualityOfService:)]
&& (&NSOperationQualityOfServiceUserInitiated)) {
[self.operationQueue performSelector:#selector(setQualityOfService:) withObject: NSOperationQualityOfServiceUserInitiated];
} else {
//Other stuff not related to the scope of this question
}
The error I get is:
Use of undeclared identifier 'NSOperationQualityOfServiceUserInitiated'
I added the if (&NSOperationQualityOfServiceUserInitiated) part to check if this constant exists. This code worked with older versions of Xcode/Obj-C Compiler.
I am able to use selectors with performSelectorWithIdentifier but what about constants that do not have a defined value in the docs? The value of this constant is set by NSQualityOfServiceUserInitiated but there is no definition for this value that can be hardcoded.
How do I fix that?
There are several things wrong with the code.
NSOperationQualityOfServiceUserInitiated is a native type (NSInteger) so you can't use it the way that you are in either line.
The qualityOfService is a property of type NSQualityOfService. Your attempt to pass an argument to the qualityOfService method (getter method) makes no sense. If you are trying to set the quality of service, you need to call the setter but you can't use performSelector.
You want:
if ([self.operationQueue respondsToSelector:#selector(qualityOfService)]) {
self.operationQueue.qualityOfService = NSOperationQualityOfServiceUserInitiated;
} else {
//Other stuff not related to the scope of this question
}
This code will compile fine as long as your Base SDK is iOS 8.0 or later. The Deployment Target doesn't matter.
If you also want to build this code with Xcode 5 or earlier (a Base SDK of iOS 7 or earlier) then you need to wrap the code with the proper compiler directives to check for the Base SDK.

Titanium Ti.Android Undefined in ios

I am very new to Titanium Developer. I assigned an Titanium project for made UI changes to latest ios look and feel. When I run App I will always throwh exception like Ti.Android is undefined.
The previous version of the SDK is 3.0.2 but I am now configured the latest version 3.2.3GA
Current the app run without any error in Android only show error as undefined for Ti.Android in Ios only.
My Dough whether Ti.Android is strict to Android platform only or its for both ios and android or else its is deprecated for ios in latest version.
Please help.
As is mentioned in the docs Ti.Android is available only for Android (Ti > 1.5, see the logo on the right) http://docs.appcelerator.com/titanium/latest/#!/api/Titanium.Android however if you try to access only Ti.Android it should work and return undefined because Ti has no Android property. You shouldn't see any errors... ,but you are probably trying to access some other property for instance Ti.Android.XXX which obviously can't work.
You should check the platform first before using any platform-specific modules/function. You could add a function on your commonjs to check it.
var osname = Ti.Platform.osname;
function isAndroid() {
return osname === 'android';
}
function isIOS() {
return osname === 'iphone' || osname === 'ipad';
}
function isMobileWeb() {
return osname === "mobileweb";
}
On your controller, you then do something like this:
var fn = require('commonjs');
if (fn.isAndroid()) {
//the things you do for android only
} else if (fn.isIOS() {
} else if (fn.isMobileWeb()) {
}

Resources