Calling ZipZap's updateEntries method causes a crash in Swift - ios

I've been trying to create an archive using the ZipZap library (https://github.com/pixelglow/zipzap) and to be more specific the 8.0 release. The library is consumed in Swift code.
I've read that when calling:
newArchive.updateEntries(archiveItems, error: error)
Requires the "archiveItems" to be NSMutableArray and it is defined as such. At this point I tried creating an archive that contains just one directory so the array looks like:
var archiveItems = NSMutableArray()
archiveItems.addObject(ZZArchiveEntry(directoryName: "\(archiveName)/"))
"newArchive" is created the following way:
var newArchive = ZZArchive(URL: NSURL(fileURLWithPath: archivePath), error: error)
The error I see is: EXC_BREAKPOINT(code=1, subcode=0x1001bc998)
And I've also seen: EXC_BREAKPOINT(code=1, subcode=0x100100998)
In case I do not call the updateEntries method the code does not crash. So my assumption is that the crash happens inside this method.

At the end it was me not reading the spec as it is written in the example on GitHub.
After a help from Glen Low (pixelglow) the issue was that I am actually trying to create a new file without sending an option to create the file in case it does not exist.
So a massive thanks goes to pixelglow for his help and the great library!
The proper way to call the init when you need to create the file is:
var newArchive = ZZArchive(URL: NSURL(fileURLWithPath: archivePath), options: [ZZOpenOptionsCreateIfMissingKey: true], error: &archiveError)

Related

Error initialize AZSCloudStorageAccount Swift 3

I tried link to my account with this code
let storageAccount : AZSCloudStorageAccount;
try! storageAccount = AZSCloudStorageAccount(fromConnectionString: config.getAzureConnection())
let blobClient = storageAccount.getBlobClient()
var container : AZSCloudBlobContainer = (blobClient?.containerReference(fromName: config.getContainer()))!
the "config.getAzureConnection()" contains the right path because i used the same for android app.
In this line try! storageAccount = AZSCloudStorageAccount(fromConnectionString: config.getAzureConnection()) the app crash without error, only (lldb) .
Can someone help me.
Does your error look like this?
fatal error: 'try!' expression unexpectedly raised an error: Error Domain=com.Microsoft.AzureStorage.ErrorDomain Code=1 "(null)": file /Library/Caches/com.apple.xbs/Sources/swiftlang/swiftlang-802.0.53/src/swift/stdlib/public/core/ErrorType.swift, line 182
(lldb)
Code=1 is AZSEInvalidArgument, which means that your connection string is invalid. I am a bit confused why you said "the right path", since fromConnectionString takes the string directly, not the path to a file. To see an example of what a correct connection string looks like, please refer to the Getting Started Guide. Basically it looks like this:
"DefaultEndpointsProtocol=https;AccountName=your_account_name_here;AccountKey=your_account_key_here"
We will document the error codes properly very soon. Sorry for the confusion!
the app crash without error, only (lldb) .
I am sorry for that SWIFT blob client haven't provide error-handling code whatsoever currently. I will provide some clues to track your issue based on your code.
Before building the storage code, make one change in the project. Go to 'Azure Storage Client Library' -> Build Settings, search for the "Defines Module" setting, and change it to 'YES'.
Please check whether the issue is caused by bad network connection.
You could get error code of this issue by putting your code in a do-catch code block.
do {
//put your code here
} catch let error as NSError {
print("Error code = %ld, error domain = %#, error userinfo = %#", error.code, error.domain, error.userInfo);
}
The SWIFT blob sample has been tested and work well targeting iOS 9.0 and using XCode 7. If you have a different setup, the sample may not run properly. I suggest you use Blob Storage REST API as a workaround.

Could not cast value of type 'SPTSession' (0x110afab98) to 'SPTSession' (0x10f17f638)

I am using the Spotify iOS SDK and I am storing a session using NSKeyedUnarchiver
However the following code causes an error(some code omitted just for clarity's sake):
sptSession = NSKeyedUnarchiver.unarchiveObjectWithData(sessionData as! NSData)
let auth = SPTAuth.defaultInstance()
auth.session = sptSession as! SPTSession
The last line of code is throwing the error Could not cast value of type 'SPTSession' (0x110afab98) to 'SPTSession' (0x10f17f638). I read that error as somehow there are two different types of SPTSessions but I'm not sure why or how to resolve the issue.
the answer seems to be related to this SO post:
Swift only way to prevent NSKeyedUnarchiver.decodeObject crash?
I have added an issue to the GH repo for Spotify's iOS SDK (https://github.com/spotify/ios-sdk/issues/759), and posted this temporary workaround as a comment on the issue:
for the time being, I have found a workaround - I can simply write NSKeyedArchiver.setClassName("SPTSession", for: SPTSession.self) before I archive the session, and write NSKeyedUnarchiver.setClass(SPTSession.self, forClassName: "SPTSession") before unarchiving.
While this fixes the crash, I will leave the issue open as I am not sure if a change can be made in the underlying library to fix this

Unable to open a realm at path

I am trying to use a bundled realm file without success. I know that my realm file was copied successfully to my application’s Directory but I ca not read it.
fatal error: 'try!' expression unexpectedly raised an error: "Unable
to open a realm at path
'/Users/…/Library/Developer/CoreSimulator/Devices/…/data/Containers/Data/Application/…/Documents/default-v1.realm'.
Please use a path where your app has read-write permissions."
func fullPathToFileInAppDocumentsDir(fileName: String) -> String {
let paths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,NSSearchPathDomainMask.UserDomainMask,true)
let documentsDirectory = paths[0] as NSString
let fullPathToTheFile = documentsDirectory.stringByAppendingPathComponent(fileName)
return fullPathToTheFile
}
In didFinishLaunchingWithOptions:
let fileInDocuments = fullPathToFileInAppDocumentsDir("default-v1.realm")
if !NSFileManager.defaultManager().fileExistsAtPath(fileInDocuments) {
let bundle = NSBundle.mainBundle()
let fileInBundle = bundle.pathForResource("default-v1", ofType: "realm")
let fileManager = NSFileManager.defaultManager()
do {
try fileManager.copyItemAtPath(fileInBundle!, toPath: fileInDocuments)
} catch { print(error) }
}
And setting the configuration used for the default Realm:
var config = Realm.Configuration()
config.path = fileInDocuments
Realm.Configuration.defaultConfiguration = config
let realm = try! Realm(configuration: config) // It fails here!!! :-)
As the documentation suggests, I have tried as well to open it directly from the bundle path by setting readOnly to true on the Realm.Configuration object. I am not sure if this is something related to Realm or if I am overlooking something with the file system…. I have also tried to store the file in the Library folder.
Realm 0.97.0
Xcode Version 7.1.1
I tried to open the realm file using Realm's browser app and the file does not open anymore. It has now new permissions: Write only (Dropbox). So, I decided to change the file permission back to read/write using file manager’s setAttributes method. Here is how I did it:
// rw rw r : Attention for octal-literal in Swift "0o".
let permission = NSNumber(short: 0o664)
do {
try fileManager.setAttributes([NSFilePosixPermissions:permission], ofItemAtPath: fileInDocuments)
} catch { print(error) }
The realm file can now be open at this path.
That exception gets thrown whenever a low level I/O operation is denied permission to the file you've specified (You can check it out on Realm's GitHub account).
Even though everything seems correct in your sample code there, something must be set incorrectly with the file location (Whether it be the file path to your bundle's Realm file, or the destination path) to be causing that error.
A couple of things I can recommend trying out.
Through breakpoints/logging, manually double-check that both fileInDocuments and fileInBundle are being correctly created and are pointing at the locations you were expecting.
When running the app in the Simulator, use a tool like SimPholders to track down the Documents directory of your app on your computer, and visually ensure that the Realm file is being properly copied to where you're expecting.
If the Realm file is in the right place, you can also Realm's Browser app to try opening the Realm file to ensure that the file was copied correctly and still opens properly.
Try testing the code on a proper iOS device to see if the same error is occurring on the native system.
If all else fails, try doing some Realm operations with the default Realm (Which will simply deposit a default.realm file in your Documents directory), just to completely discount there isn't something wrong with your file system
Let me know how you go with that, and if you still can't work out the problem, we can keep looking. :)
This will occur if you have your realm file open in Realm Studio at same time you relaunch your app. Basically in this case Realm can't get write permissions if Studio already has them.
To add to the solution based on what I've discovered, make note of what error Realm reports when it throws the exception, as well as the type of Error that is passed.
As of writing, Realm documents their errors here:
https://realm.io/docs/objc/latest/api/Enums/RLMError.html
What this means is that you can find out if your Realm file has permissions problems and react to those based on Realm passing you a RLMErrorFilePermissionDenied. Or if the file doesn't exist with RLMErrorFileNotFound.
The tricky thing I'm finding is when you get a more generic RLMErrorFileAccess, but that's for another question on Stack Overflow...
I had the same issue and tried too many ways to fix it. The easiest way to fix this problem is manually creation of the folder XCode cannot reach '/Users/…/Library/Developer/CoreSimulator/Devices/…/data/Containers/Data/Application/…/Documents/...' as explained at https://docs.realm.io/sync/using-synced-realms/errors#unable-to-open-realm-at-path-less-than-path-greater-than-make_dir-failed-no-such-file-or-directory
Once you created this folder and run the project, XCode creates the Realm files inside this folder automatically.

Using reopened standard file descriptors in an iOS app with background capabilities?

I would like to be able to redirect my logging statements to a file so that I can retrieve them when my app runs standalone (i.e. is not attached to Xcode). I have discovered (thank you Stackoverflow) that freopen can be used to accomplish this.
If I create a new Xcode project and add the code to redirect stderr then everything works as expected.
However, when I add the redirection code to my existing, bluetooth project I am having trouble. The file is being created and I can retrieve it using iTunes or Xcode's Devices window, but it is of size 0. If I explicitly close the file then the text that I wrote actually makes it into the file. It is as though iOS is not flushing the file when the app is terminated. I suspect that the trouble stems from the fact that I have enabled background processing. Can anyone help me to understand this?
Here is my code:
let pathes = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true);
let filePath = NSURL(fileURLWithPath: pathes[0]).URLByAppendingPathComponent("Test.log")
freopen(filePath.path!, "a", stderr);
fputs("Hello, Samantha!\r\n", stderr);
struct StderrOutputStream: OutputStreamType {
static let stream = StderrOutputStream()
func write(string: String) {fputs(string, stderr)}
}
var errStream = StderrOutputStream.stream
print("Hello, Robert", toStream: &errStream)
fclose(stderr) // Without this the text does not make it into the file.
I'd leave this as a comment, but have you looked into NSFileHandle? It sounds like you just need a way to append data to the end of a text file, correct?
Once you have a handle with something like NSFileHandle(forWritingToURL:), you can use .seekToEndOfFile() and .writeData(_:). As a side note, you'll need to convert your String to Data before writing it.
Admittedly, this will probably end up being more lines of code, and you'll almost certainly need to take threading into consideration.

creation of realm file in App-Group Folder does not work under WatchOS (WatchKit Extension)

The following code works under iOS-8.x / Swift-1.2 / WatchKit-1.0
// create Realm_DB-File in shared App-Groups Folder
let directory: NSURL = NSFileManager.defaultManager().containerURLForSecurityApplicationGroupIdentifier(AppConstants.APP_GROUP_IDENTIFIER_KEY)!
let realmPath = directory.path!.stringByAppendingPathComponent(AppConstants.REALM_FILENAME_KEY)
playerRealm = Realm.init(path: realmPath)
But it doesn't work under iOS-9.0.1 / Swift-2.0 / WatchOS-2.0
The two error messages are:
1.) 'stringByAppendingPatchComponent' is unavailable: Use URLByAppendingPathComponent on NSURL instead
2.) Call can throw, but it is not marked with 'try' and the error is not handled
Any help appreciated !
To fix your first issue, you need to cast:
directory.path as NSString
since the path is returning as a String, which in Swift doesn't offer the stringByAppendingPathComponent method.
Second, Swift 2.0 has new error handling, so methods that can throw an error are labeled throws. These methods then require you to add try before the call. See Apple's docs on this: Swift Error Handling
To disable the error handling if you know that the path is guaranteed to work you can simple write:
playerRealm = try! Realm(path: realmPath)

Resources