Bundle.main.url cannot find file - ios

I tried several answers from different posts but none of them solved my problem.
Situation I am in:
The project is called XcodeTests and the only target it has is XcodeTests
I have a my_file.txt file at <ProjectRoot>/XcodeTests/res/
Upon creating my_file.txt, I made sure that target XcodeTests was selected
Both res folder and my_file.txt exists in storage directories confirmed by Finder
In Build Phase of XcodeTests, CopyBundleResources does include my_file.txt
The following code throws Fatal error: Couldn't find requested file:
import Foundation
guard let myFileURL = Bundle.main.url(forResource: "my_file", withExtension: "txt")
else
{
fatalError("Couldn't find requested file")
}
What should I do so that Bundle.main.url can find my_file.txt?

Turns out it's because the target itself is a command line program and does not support Copy Bundle Resources. Even tho resources can be listed there, none of them will be copied.

Related

Module build failed (from ./node_modules/#ngtools/webpack/src/index.js):

I have created an application on angular 7 and ionic 4.
I tried to edit app.routing.ts file, setting path and component. From then on I am getting this error below:
ERROR in ./src/app/department/department.module.ts
[ng] Module build failed (from ./node_modules/#ngtools/webpack/src/index.js):
[ng] Error: ENOENT: no such file or directory, open 'C:\Users\x\department\department.module.ts'
[ng] at Object.openSync (fs.js:436:3)
[ng] at Object.readFileSync (fs.js:341:35)
[ng] at Storage.provideSync (C:\Users\x\node_modules\enhanced-resolve\lib\CachedInputFileSystem.js:98:13)
Make sure department component exist, check the templateUrl that corresponds to the file name you are referencing. You may have also modified the path unknowingly during modification of app.routing.ts file.
C:\Users\x\department\department.module.ts
This error occurs when your component can't be found with your app.module settings.
Follow these steps to solve your problem:
Check if the module.ts file exists.
Check the relative path.
The path is case sensitive (maybe the .ts file is Department).
Both answer are useful from #trustidkid and #vinay sharma. If there is someone has been facing the same problem;
1-Go to to the file that the error has occurred in. (To go directly to the file, click the error line shortly [CTRL+Click] (CMD+Click on MacOS):
ERROR in ./src/app/department/department.module.ts
Then check the path address if it is exactly true pointing the file. Most of these problems are having similar solutions. Just be sure about the path address of the file you want to point and the address mentioned in the other file which the error occurred.
This problem happens when you delete a component but forgot to delete its import from module.ts.
For example: TestComponent is deleted so you have to also delete:
import { TestComponent } from './test.component'
If you have a folder mapping on a windows machine like me, do not try to build it from a mapped folder, go to the original folder and build it from there.
Mapped Folder has a small icon like this:
In my case I had prime ng version that did not support a particular module, I simply commented it out and it worked.

Xcode 10: Load the same .xml file in project target and unit test target

I try to load the same .xml file in project target and unit test target.
It seems to be a similar problem like this question: Xcode. Image resources added to a test target are not copied into the tests bundle
In project target, this code snipped worked fine. I just have to add the "xmlString.xml" file to "Copy Files" (see image 1).
func parseFile() {
let stringPath = Bundle.main.path(forResource: "xmlString", ofType: "xml")
let url = NSURL(fileURLWithPath: stringPath!)
...
}
If I run the code snipped in unit test target, I get an error because the .xml file can not be found. I tried to add the .xml file to the "Copy Bundle Resources" without any success (see image 2).
The only way to get it working is to use the absolute path
func parseFile() {
let stringPath: String? = "/Users/.../Documents/Git/.../.../.../.../xmlString.xml"
let url = NSURL(fileURLWithPath: stringPath!)
...
}
Is there a way to use the Bundle.main.path(forResource: "xmlString", ofType: "xml") function instead of the absolute path?
Thanks in advance!
You can get the bundle for your project like this:
let projectBundle = Bundle(for: AnyClassInMyProject.self)
where you replace AnyClassInMyProject with the name of an actual class in your project.
You can then get the path to your .xml file like this:
let stringPath = projectBundle.path(forResource: "xmlString", ofType: "xml")

native zlib inflate/deflate for swift3 on iOS

I'd like to be able to inflate/deflate Swift3 Data structs. I found GzipSwift, but it's not clear how I make that available to my iOS app. The naive things I've tried include:
Copying the Data+Gzip.swift file into my own project. This then complains about the import zlib at the top of said file. I think that has something to do the with the modulemap files in the zlib directory of the same sources. But I'm not sure what or how to recreate those in my own project.
Cloned the repository from github, opened XCode and built in (pressed the run button basically). Then tried to add that as a linked library or framework to my own project. I'm pretty sure just selecting the top level directory of the repository is not what I want to do, but I didn't know what else to try.
I've found some other code out there, but it seems dated and relative to Swift2.
Swift 5 implementation using Compression.
Took me a few days to realise I had to drop the first 2 bytes of the compressed data.
Hope it can help somebody else.
import Foundation
import Compression
func decompress(_ data: Data) -> String {
let size = 8_000_000
let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: size)
let result = data.subdata(in: 2 ..< data.count).withUnsafeBytes ({
let read = compression_decode_buffer(buffer, size, $0.baseAddress!.bindMemory(to: UInt8.self, capacity: 1),
data.count - 2, nil, COMPRESSION_ZLIB)
return String(decoding: Data(bytes: buffer, count:read), as: UTF8.self)
}) as String
buffer.deallocate()
return result
}
I just recently had to add that exact library and file to my project, and after a lot of troubleshooting finally got it working, so let me walk you through the steps!
Okay
1) Go to the top level directory of your project in finder, and create a new folder called Swiftzlib or whatever you want the name of the module that you will be importing to be. (What we will do is add the zlib library as a module, so think of it as importing Foundation or some such other module). To clarify, this Swiftzlib directory will end up as a child directory of the same directory that contains your *.xcodeproj and *.xcworkspace files.
2) Inside the folder you created, make two files.
include.h
module.modulemap
3) In your include.h file, enter the following:
#include<zlib.h>
4) In your module.modulemap file, enter the following:
module Swiftzlib [system] {
header "include.h"
export *
}
Where Swiftzlib is the same as the name of the folder that you created.
5) Open your Xcode project, and select your target
5a) In Build Phases -> Link Binary with Libraries, add libz.tbd
5b) In Build Settings -> Swift Compiler - Search Paths, add $(PROJECT_DIR)/Swiftzlib non-recursively to the import paths
5c) In Build Settings -> Other Linker Flags, add -lz as a flag
6) Select your project in Xcode (may not be necessary, but I've done it in my project and it works)
6a) In Build Settings -> Swift Compiler - Search Paths, add $(PROJECT_DIR)/Swiftzlib non-recursively to the import paths
7) In Data+Gzip.swfit, add import Swiftzlib to the top of the file
8) Clean, Build, and Run!
I maintain a small Swift 3+ wrapper around Apples native libcompression framework at:
https://github.com/mw99/DataCompression
Usage example for gzip:
let data: Data! = "https://www.ietf.org/rfc/rfc1952.txt".data(using: .utf8)
let gzipped: Data! = data.zip()
let gunzipped: Data? = gzipped.unzip()
assert(data == gunzipped)
But if you are only interested in classic inflate and deflate you may use the .inflate() and .deflate() methods instead. That will save 18 bytes because the gzip header won't be added.
I made a small spm extension inspired by #vauxhall 's answer
https://github.com/mezhevikin/Zlib
import Zlib
// Decompressed data
print(data.decompressed)
// Decompressed string
print(data.decompressedString)

Scanning the contents of a directory which is stored in an Xcode project in swift

This seems to be a problem which is very difficult to explain. I am trying to read data from a folder full of files and the way I am trying to do this is by scanning the whole directory for all of the files. The file in question is stored in my Xcode project in the same directory as the view controllers and storyboards. Like so:
I would like to be able to scan the contents of the "data" folder. Consider the following code:
var tmpDir = NSTemporaryDirectory()
var error: NSError?
let filesInDirectory: [String]! = fileManager.contentsOfDirectoryAtPath(tmpDir, error: &error) as? [String]
This scans the contents of the app's local folder and returns it as an array of the file names. I would like to be able to do this with the "data" folder in my Xcode project. The following code will find the contents of a single file which is stored in the same directory as the "data" folder.
let files = NSBundle.mainBundle().pathForResource("sampleFile", ofType: "csv")
var contents = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)!
Is there a way in which I can combine the capabilities of the two in order to scan the contents of the "data" folder in the Xcode project and then return the file names as an array?
Add the data folder to Copy Bundle Resources in Build Phases of your target.
Then you'll be able to read the path as it's within the same sandbox scope. (Assuming you are applying sandbox.) If not, just use absolute path/URL and you can access it directly without the copying process.
You might want to have a look here: Cocoa contents of directory

Xcode writing to file in a unit test

I understand that when a unit test executes, it is in the sandbox environment of Xcode.
In a unit test, I need to write and read data to a file.
Since the project resides in a git repository, this must be done completely from within code (i.e. no special manual test setup of directories is possible)
For all my searching and trying today, I cannot find a way to write to a file from within the unit test.
Does anybody know of a method to write to a file under these conditions?
Edit: This is the problematic code:
let dirPath = NSTemporaryDirectory()!
var filePath = dirPath.stringByAppendingPathComponent("unittest.json")
if !NSFileManager.defaultManager().isWritableFileAtPath(filePath) {
return (nil, "Directory missing or write access not granted for \(path)")
}
You should be able to use the temporary directory: NSTemporaryDirectory() and have it reliably point to a safe place to read and write. I'd suggest making sure you clean up any created files.
let dirPath = NSTemporaryDirectory()
To see whether a file can be created (per the updated question), check the directory for write permissions:
let canCreate = NSFileManager.defaultManager().isWritableFileAtPath(dirPath)

Resources