I start a new project in swift with a workspace. I add a new package in the project called ApplicationCore by using File - New - Package. After i add the new package i see a a file in the package which is automatically created called ApplicationCore.swift with the following code.
//ApplicationCore.swift
public struct ApplicationCore {
public private(set) var text = "Hello, World!"
public init() {
}
}
Then i add another folder called Colors and inside this folder i create a new swift file called AppColors.swift. Here is the code...
//AppColors.swift
import Foundation
public struct AppColors {
public let greenColor = Color.green
}
So i need to access the struct AppColors from within the struct ApplicationCore which exists in the ApplicationCore.swift file. I use this code inside ApplicationCore
public private(set) var AppColorGreen = AppColors.greenColor
I get a message saying
Cannot find 'AppColors' in scope
What am i missing? I am new to swift so any help appreciated.
Actual Path: Sources/ApplicationCore/ApplicationCore.swift and Sources/Colors/AppColors.swift
The problem seems to be that you've put your Colors folder in the wrong place.
For a package that provides a single product (library, executable, etc...), if that product is called X, then you want all of the source code for X to be inside of Source/X. This is how SPM sets up a package initially.
In your case, you have a package, which I suppose is called ApplicationCore, which provides a product/target that is also called ApplicationCore. So all of your source code should go into Source/ApplicationCore.
You don't have to use the same name for the product as for the package, but that is the default for the Package.swift file SPM creates. To change it, you'd need to edit the products and targets arrays in Package.swift, and name the directory in Source to be whatever name you pick for the product.
Related
I have to access to a private method in a Class. I created a library with inside the Class, imported it but it can't still recognize. I have the same problem also with private variables.
Example:
file buffer.dart:
library buflib;
class Buffer{
void _record(){
[...]
}
}
in the same folder: engine.dart
import 'buffer.dart';
class Engine {
Buffer _buff = Buffer()
[...]
void myMethod(){
[...]
this._buff._record();
}
}
I have this error:
The method '_record' isn't defined for the type 'Buffer'.
Try correcting the name to the name of an existing method, or defining >a method named '_record'.dartundefined_method
Any suggestions?
By default, each separate .dart file is a separate library. Since private identifiers are private to the library, they won't be visible to other .dart files.
You can use the library and part of directives to group multiple .dart files into the same library, but those directives aren't documented.
u cant call private methods or variables from out there classes .... u should change it to public by removing "under score"
I have been asked to do testing in swift and I have no idea about swift
So, I was just reviewing the code and trying to make sense out of it.
I was in a file say xyzTests.swift where we wrote all the test case.
By going through the test cases written in the code, the first thing was something like this
func xyz() {
var failureMessage: String? = nil;
startSess(validity: 3)
}
In Javascript,one can only do something like this if
There is a function declared anywhere in the same file
if we are importing it from somewhere
So I searched in my file to find function declaration from startSess but wasn't able to find it. Then I clicked on jump to definition and found it some other file named utils.swift
internal func startSess(validity: Int = 1) {
}
I checked the file if there was at-least a reference of an import for at-least util but can't find any.
These are all the import statements in my code
import Foundation
#testable import session
Can someone explain me how we can use startSess?
I take it that the startSess is a function that is outside of any class then as it's being called in that way?
what #testable import session does is importing your entire workspace to be reachable from your test class. If you look in the right tab of the test file you can see that the target membership is only selected for tests (as it should be). And therefor it can't reach the rest of your code without the #testable import
See, There are various different methods to call a function from another file Some of them are as given below
(and Pardon me if I left any methods in this answer, I am open to edits :) )
As #Vollan said , importing the whole workspace , so you can access any function from any file anywhere in the project
Calling or Loading the file (in your case util.swift) and using the function in another file(xyz.swift)
ex: In xyz.swift,
func xyz() {
let a = util() //Loading the swiftfile
a.startSess(validity: 3) //using the function of swiftfile
}
making that function global which you want to use.
extension UIViewController { //In most cases UIViewController is used in all files so extending it helps
func startSess(validity: Int = 1) {
}
}
You can directly make that function global even if you are not using any extensions or any classes by using Foundation(As in any file Foundation is must imported in the Header of any SwiftFile)
Ex: - Make any SwiftFile say named abc.swift and in that file
import Foundation
func startSess(validity: Int = 1) {
//Your Code
}
Now, you can call this function by startSess(param) in any file in your whole project.
I am working on a dart package with includes over 200 models and at the moment i have to write manually one line of "export" for each model, to make the models available for everyone who uses this package.
I want the build runner to generate one dart file which contains every export definition.
Therefore I would create an annotation "ExportModel". The builder should search for each class annotated with this annotation.
I tried creating some Builders, but they will generate a *.g.dart file for each class that is annotated. I just want to have one file.
Is where a way to create a builder that runs only once and creates a file at the end ?
The short answer to your question of a builder that only runs once and creates a single file in the package is to use r'$lib$' as the input extension. The long answer is that to find the classes that are annotated you probably want an intermediate output to track them.
I'd write this with 2 builders, one to search for the ExportModel annotation, and another to write the exports file. Here is a rough sketch with details omitted - I haven't tested any of the code here but it should get you started on the right path.
Builder 1 - find the classes annotated with #ExportModel().
Could write with some utilities from package:source_gen, but can't use LibraryBuilder since it's not outputting Dart code...
Goal is to write a .exports file next to each .dart file which as the name of all the classes that are annotated with #ExportModel().
class ExportLocatingBuilder implements Builder {
#override
final buildExtensions = const {
'.dart': ['.exports']
};
#override
Future<void> build(BuildStep buildStep) async {
final resolver = buildStep.resolver;
if (!await resolver.isLibrary(buildStep.inputId)) return;
final lib = LibraryReader(await buildStep.inputLibrary);
final exportAnnotation = TypeChecker.fromRuntime(ExportModel);
final annotated = [
for (var member in lib.annotatedWith(exportAnnotation)) element.name,
];
if (annotated.isNotEmpty) {
buildStep.writeAsString(
buildStep.inputId.changeExtension('.exports'), annotated.join(','));
}
}
}
This builder should be build_to: cache and you may want to have a PostProcessBuilder that cleans up all the outputs it produces which would be specified with applies_builder. You can use the FileDeletingBuilder to cheaply implement the cleanup. See the FAQ on temporary outputs and the angular cleanup for example.
Builder 2 - find the .exports files and generate a Dart file
Use findAssets to track down all those .exports files, and write an export statement for each one. Use a show with the content of the file which should contain the names of the members that were annotated.
class ExportsBuilder implements Builder {
#override
final buildExtensions = const {
r'$lib$': ['exports.dart']
};
#override
Future<void> build(BuildStep buildStep) async {
final exports = buildStep.findAssets(Glob('**/*.exports'));
final content = [
await for (var exportLibrary in exports)
'export \'${exportLibrary.changeExtension('.dart').uri}\' '
'show ${await buildStep.readAsString(exportLibrary)};',
];
if (content.isNotEmpty) {
buildStep.writeAsString(
AssetId(buildStep.inputId.package, 'lib/exports.dart'),
content.join('\n'));
}
}
}
This builder should likely be build_to: source if you want to publish this file on pub. It should have a required_inputs: [".exports"] to ensure it runs after the previous builder.
Why does it need to be this complex?
You could implement this as a single builder which uses findAssets to find all the Dart files. The downside is that rebuilds would be much slower because it would be invalidated by any content change in any Dart file and you'd end up parsing all Dart code for a change in any Dart code. With the 2 builder approach then only the individual .exports which come from a changed Dart file need to be resolved and rebuilt on a change, and then only if the exports change will the exports.dart file be invalidated.
Older versions of build_runner also didn't support using the Resolver to resolve code that isn't transitively imported from the input library. Recent version of build_runner have relaxed this constraint.
I created a swift framework and now i want to import it in my application.
I did import BiometricAccessControl in my ViewController but xcode not recognizes my classes.
How can i solved it?
Thanks
Maybe it is a problem of access control policy.
By Default, your type(class,enum,struct) and their member(property,subscript,method)'s access control level is internal,which is visible inside your framework,if you want to expose it(namely,API) to other modules, you could try to add public modifier to your class or their member.For Example:
public class MySwiftComponent {
public var publicInt:Int?
private var privateInt:Int?
internal var internalInt:Int?
}
Totally, there are three access level : public ,internal and private (internal is default)
I created a bare-bones datagrid using web-ui for testing and had it working just fine. Then I decided to try to declare it as a component. I changed around the library references and now it is giving me the above error when I try to run the application. You can see my file structure below. The reason I am getting the "ambiguous reference" message when I try to run it is that when I went into the auto-generated DataGrid.dart file in the out directory, it had the following declaration
import 'DataGrid.dart';
...
import '../DataGrid.dart';
I am confused as to why the generated code imports them both. One thing that I considered is that it could be because the DataGridPage.html file instantiates my DataGrid component and my DataGridPage.dart file imports DataGrid.dart so that it can have references to DataGridColumn (it needs to set the columns for the DataGrid). In DataGridPage.dart, I also attach to certain DataGrid events such as SortColumnChanged and SelectionChanged so I need to request a copy of my DataGrid instance in DataGridPage.dart (I don't think there is a way to attach to events from the web component instantiation in DataGridPage.html).
Any ideas about what I am doing wrong?
Here is my file structure:
DataGrid.dart
--------------------------------------------
library datagrid;
...
part 'DataGridColumn.dart';
part 'DataGridRow.dart';
class DataGrid extends WebComponent{...}
DataGridRow.dart
--------------------------------------------
part of datagrid;
class DataGridRow {...}
DataGridColumn.dart
--------------------------------------------
part of datagrid;
class DataGridColumn {...}
DataGrid.html
--------------------------------------------
[contains the component declaration UI]
DataGridPage.html
-----------------------------------------
...
<div is="s-datagrid" id="myDataGrid" ItemsSource="{{app.Assets}}" Columns="{{app.Columns}}"></div>
...
DataGridPage.dart
--------------------------------------------
import 'DataGrid.dart';
import 'Asset.dart';
void main() {
}
DataGridApp _app;
DataGridApp get app {
if (_app == null) {
_app = new DataGridApp();
}
return _app;
}
class DataGridApp{
//provides ItemsSource and DataGridColumn data
}
jmesserly has answered this on the github site. He said that you need to remove the component import in your main dart file. So in my example I would remove the import 'DataGrid.dart' statement from the DataGridPage.dart. The IDE will give you a warning but you can ignore it because it will actually be run from the out folder.
GitHub Web-UI Issue 342