Obj C codebase and unit test cases in Swift - swift

I have an objective c code base and I am writing snapshot test cases in swift. I have certain functions and variable which are declared in .m class. How I can access those variables from swift test class.

Use a bridging header to expose the Objective-C entities that you want to use in your Swift tests. You may already have one set up (as explained in the link, Xcode offers to create one when you add a Swift file to an Objective-C project); if so, you may just need to update the file to add headers that aren't currently included. If you don't have one, the link I provided will show you how to create one.

Related

Generating Swift files from templates

My goal is to create (find if exist) a tool which can produce swift files from templates.
For example, let’s say I need to create new ViewController with UITableView. It should be based on MVVM architecture with dependency injection. Let’s name this View “PersonsList”.
So, for this task I need to produce:
PersonListViewController
PersonListViewModel
PersonListViewModelProtocol
PersonCell
VM for cell and protocol for VM
Lots of files.
I want to say to my tool something like that
create tableview-template Person
and as a result get generated files. Files should contain empty implementation of each classes.
How should I do that? I am thinking about simple console app but I don’t know which language I should use. Maybe there is a better idea? Maybe there is a ready tool? Any help? :)
You could manually create the templates yourself and then write a short script (in Python / bash / swift etc) that goes through and replaces keywords with arguments you've passed in.

Why would identical code throw an error in one location but not another?

I'm currently starting up work on a project, and my first task is decomposing a God Object that someone else created out of the AppDelegate. I've started by copying code related around managing location out, in the intention of delegating calls to that code into the new object.
I have two statements that are driving me nuts however.
New file:
if locationManager?.location?.horizontalAccuracy > horizontalAccuracyCheck{...}
Old file:
if locationManager?.location?.horizontalAccuracy > horizontalAccuracyCheck{...}
You'll notice the code is identical. In both cases self.locationManager? is defined as:
var locationManager: CLLocationManager?
But in the new file, I'm getting a warning about 'value of optional type no unwrapped' -- why? Exact duplicate code, copied & pasted, what would make this different?
Changing the code to unwrap it fixes things:
if (locationManager?.location?.horizontalAccuracy)! > horizontalAccuracyCheck{...}
I can wrap my head around why I need to explicitly unwrap a potentially optional return. But... why only in one place?
The reason is that we're talking here about two quite different languages. One file is Swift 2, the other file is Swift 3.
In Swift 2, you can compare an Optional representing a number with another number using the greater-than or less-than operator. In Swift 3, you can't do that.
Here's a simpler example of the same thing:
let optint : Int? = 7
let ok = optint < 42
That code is legal in Swift 2 but illegal in Swift 3.
As discussed in this Q&A – the Swift migrator will insert a custom fileprivate operator overload in order to allow for optional comparisons to work in Swift 3 the same way they did in Swift 2. Because this overload is fileprivate, you won't be able to use it from any other source files in your project that don't also define it, thus why your comparison fails to compile in the new source file.
Therefore one solution is just to copy it over to your new file. Another is to remove the fileprivate access modifer. The overload will default to internal, and therefore be accessible to other Swift files in your module.
Although really I would just recommend removing the overload entirely and instead write your own explicit logic for optional comparison when it arises – the overload can be too easily misused (as demonstrated by the Swift evolution proposal to remove it).

.swift file name containing plus sign

I opened an XCode project produced as a tutorial by Apple ("Auto Layout Cookbook"), when I found two files with a strange naming:
Recipe+Loading.swift
Recipe+Storyboards.swift
Both contain an extension called Recipe. I was not able to find any docs about this kind of naming.
Is there any reason why they named the files this way?
The naming comes from Objective-C where every extension for a class needed a name. For example, a class Recipe could have extension:
#interface Recipe (Loading)
#end
which contained methods related to "Loading".
Such extensions were commonly put into files named Recipe+Loading.h (that is, class Recipe extended with Loading methods).
In Swift extensions don't have a name but old habits die hard. They used the same naming for files.
This is a common naming convention from Objective-C. As you surmised it basically contains extensions to Recipe that pertain to loading and storyboards respectively. It's primarily a way to break up large source files or label extensions to system classes (String, Array, etc.)

what approach for adding custom methods to Core Data managed objects in separate files?

what approach for adding custom methods to Core Data managed objects in separate files? In particular the requirements would be I guess:
don't want to touch the XCode4 generated classes (i.e. so can regenerator them anytime and not have to redo changes within them)
can effectively add methods to the generated classes (assumption is the class names don't change)
Note - I'm aware of mogenerator but I'm not happy with it entirely at the moment noting https://github.com/rentzsch/mogenerator/issues/55
Would the simple and best answer be just Objective-C: Categories?
Fixing mogenerator would be the best answer :-).
mogenerator uses subclasses, so you could always do that, but categories would work as well.
I just tried... What do you think about a simple #include "included_dataStuff" and putting all your extra code into the "included_dataStuff" file.
There are two possibilities:
create a new ClassFile, delete the include "header.h", (delete the header.h), put the extra code there. It compiles but brings the two warnings: (which are understandable)
[WARN]warning: no rule to process file '$(PROJECT_DIR)/Classes/../included_dataStuff' of type text for architecture armv6
[WARN]warning: no rule to process file '$(PROJECT_DIR)/Classes/../included_dataStuff' of type text for architecture armv7
create a new "empty" file and put the extra code there. This does not produce any warnings.
The difference between 1 and 2 is that while the code formatting remains in the first alternatve (having to accept the 2 warnings) in the second all the code format is lost and its treated like normal text (but there is no warning)
I guess I would prefer the first. Of course, the only modification to the generated code file would be the #include statement.
What do you think about that?

Application constants used at compilation time

I have many constants in my application used by many classes of my project. These constants have to be set at compilation time (they are not modified later).
For now, I use #define statements at the top of each classe that requires the constant. The problem is that I have to repeat these statement in each classe which requires the constant.
I plan to define all these constants in my main.m or in another .h imported by main.m but I think it is not a good idea.
-> Is there a XCODE / IOS mechanic or file made for that purpose ?
-> If not, is it a good idea to define the constants in my main. ?
Thanks for you help
kheraud
You can write all constants in any .h file , then you can import that file in your projectname_Prefix.pch file .
then you don't need to import file in any other source file . its directly get imported .
you can save them in your *_Prefix.pch then they will apply for all classes without importing another class.
Generally the best way to handle shared constants is to declare them extern in one or more dedicated .h files, and then define them in corresponding implementation files. That way you'll be guaranteed to only have one copy of each constant in your binary, unlike with a #define.
You can provide target-wide compiler defines in Xcode by adding them to the Preprocessor Macros build setting. For example, this might let you create a free Lite version of your application by creating a target for it within your project, then adding a LITE define in the Preprocessor Macros.
See this question for more on this.