Swift: Cannot access methods from declared library - ios

On a side-note: I would like to apologize if the title is misleading. Couldn't find a better title for this question.
I imported the NDHTMLtoPDF library to my Xcode application.
In the demo of the library, this is how they use the library:
class NDViewController :UIViewController, NDHTMLtoPDFDelegate
{
var PDFCreator:NDHTMLtoPDF?
[...]
#IBAction func generatePDFUsingDelegate( sender:AnyObject ){
self.resultLabel?.text = "loading..."
let tt:NSString = ("~/Documents/delegateDemo.pdf" as NSString).stringByExpandingTildeInPath
self.PDFCreator = NDHTMLtoPDF.createPDFWithURL(NSURL(string:"http://edition.cnn.com/2012/11/12/business/china-consumer-economy/index.html?hpt=hp_c1")!, pathForPDF:tt, delegate: self, pageSize: CGSizeMake(595.2,841.8), margins:UIEdgeInsetsMake(10, 5, 10, 5)) as? NDHTMLtoPDF;
}
}
In my application, I do the same thing: I declare the PDFCreator variable as an NDHTMLtoPDF? type, I added NDHTMLtoPDFDelegate at the class declaration where I use the library instance, and I wrote the following code in my method:
let tt:NSString = ("~/Documents/delegateDemo.pdf" as NSString).stringByExpandingTildeInPath
self.PDFCreator = NDHTMLtoPDF!.createPDFWithHTML("Hello", pathForPDF: tt, pageSize: CGSizeMake(595.2,841.8), margins:UIEdgeInsetsMake(36, 36, 36, 36))
Every time I type self.PDFCreator = NDHTMLtoPDF!., I only get autocompletes for the following methods:
createPDFWithHTML(self:NDHTMLToPDF)
createPDFWithURL(self:NDHTMLToPDF)
If I type self.PDFCreator = NDHTMLtoPDF., Xcode complains that this is an ambiguous reference to member <insert_member_here>.
However, if I do self.PDFCreator., I suddenly get createPDFWithURL( URL:NSURL ,pathForPDF PDFpath:NSString ,delegate:AnyObject ,pageSize:CGSize ,margins pageMargins:UIEdgeInsets ) as an autocomplete option. I attempted to run my code with that only, but it turns out the method is never called (I checked by adding print calls in the methods).
I am seriously at a loss.
Thank you for any help you may provide!
If you need any extra code, let me know.

So after fiddling with it some more, I figured it out. The solution is simple: update the code to the latest Swift 2.0 syntax.
I took the liberty of forking the repository and fixing it myself. I made a pull request, but if you want to get a copy of it before they merge it into the official master branch, go grab it here.

Related

How can I cast UnsafePointer<UnsafeMutablePointer<Float>>? to UnsafeMutablePointer<UnsafeMutablePointer<Float>?>!

I have an C API I need to interact with in Swift.
One of the function takes an array of pointers as argument, which is imported by Swift as
`UnsafeMutablePointer<UnsafeMutablePointer<Float>?>! `
The corresponding input on the Swift side is AVAudioPCMBuffer.floatChannelData, which is defined as
UnsafePointer<UnsafeMutablePointer<Float>>?
I am having trouble casting between the two.
I tried to make it mutable by doing following:
UnsafeMutablePointer<UnsafeMutablePointer<Float>>(AVAudioPCMBuffer.floatChannelData)
And that did not work. The casting between Swift pointer types are very frustrating. Any help will be really appreciated.
Thanks
var testPtr : UnsafeMutablePointer<UnsafeMutablePointer<Float>?>! = nil
var testPtr2 : UnsafePointer<UnsafeMutablePointer<Float>>? = nil
testPtr = unsafeBitCast( testPtr2, to: UnsafeMutablePointer<UnsafeMutablePointer<Float>?>!.self)
As per excellent #easytarget suggestion since XCode 13.3 use modern syntax instead (not generating a warning):
testPtr = UnsafeMutablePointer(mutating: testPtr2)

Grails 3 Entity not saved when properties set in EntityClass

I occure a problem which I do not understand. Following code does not work:
AccountingEntity accountingEntity = AccountingEntity.get(params.id);
accountingEntity.setLifecycleStatusToArchived();
accountingEntity.save(flush:true);
Where the method setLivecylceStatusToArchived looks like:
void setLifecycleStatusToArchived() {
this.lifecycleStatus = AccountingEntity.LIFECYCLE_ARCHIVED; //predefined static variable
this.considerForRankingJob = false;
this.dateArchived = new Date();
}
Problem is, that the entity is not updated.
No validation erros when I use accountingEntity.validate() in advance.
However, this code works:
AccountingEntity accountingEntity = AccountingEntity.get(params.id);
accountingEntity.setDateArchived(new Date());
accountingEntity.setConsiderForRankingJob(false);
accountingEntity.setLifecycleStatus(AccountingEntity.LIFECYCLE_ARCHIVED);
accountingEntity.save(flush:true);
The code did not work any more after update from Grails 3.2.9 to 3.3.0.RC1 (Gorm 6.1.5) unless I followed all the steps in the guide (http://docs.grails.org/3.3.x/guide/upgrading.html) and the rest of the code is working properly (also database accesses etc.)
Has anybody an idea? What the problem could be?
Thanks in advance and best regards!
The short answer is dirty checking. When you are setting properties inside the instance method Grails doesn't know they are dirty.
See the following github issue for how to resolve the problem:
https://github.com/grails/grails-data-mapping/issues/961
you have 2 options:
call markDirty every time you change an internal field. This will be
better for performance or as per
http://gorm.grails.org/latest/hibernate/manual/index.html#upgradeNotes
use
hibernateDirtyChecking: true

Zapier Scripting - Error: Cannot find module 'moment'

I'm trying to use Moment.js library in Zapier. The documentation says that it's available. However, when I add this line:
var moment = require('moment');
I keep getting this error:
Bargle. We hit an error creating a run javascript. :-( Error:
Error: Cannot find module 'moment'
If I remove the declaration, I get ReferenceError: moment is not defined
moment is not available in https://zapier.com/help/code/ - maybe you are thinking of https://zapier.com/developer/documentation/v2/scripting/?
I can understand how one could confuse the two - but one is a simple code step in a Zap, the other is how partners developer applications on Zapier.
Moment library is available in Zapier, no need to call(require) it. Here's a snippet of code where I have used it.
var date;
if (outbound.Date === undefined) {
var d = moment();
var n = d.format();
date = n.split('.');
outbound.Date = date[0];
}

Extraneous argument label 'localeID' in call (SwiftDate)

I am developing an iOs application with Swift and a total novice in application development. I use SwiftDate external library to deal with dates. SwiftDate is installed with CocoaPods and it is imported correctly in the project.
But I can't figure out why I get this error when I compile my project :
Extraneous argument label 'localeID' in call
For this code :
let now = NSDate()
let nowHere = now.toString() // E.g. 21-Dec-15 12:00 CET
let nowInFrench = now.inRegion(localeID: "fr_FR").toString()
I understand that's because the parameters are not formatted correctly, but this an exemple from the documentation so I am a little bit lost for this problem.
Thank's.
As Oliver mentioned, the first problem is the argument label in
let nowInFrench = now.inRegion(localeID: "fr_FR").toString()
to fix your
Extraneous argument label 'localeID' in call
error write it like this
let nowInFrench = now.inRegion("fr_FR").toString()
then you will come to the
Cannot convert value of type string to expect argument type Region
Error. This means you cannot simply give the function inRegion a String object. It wants a Region objects. The documentation says use create a region
let paris = DateRegion(timeZoneID: "CEST", localeID: "fr_FR")
let nowInFrench = now.inRegion(paris).toString()
The error is being flagged up because for the first argument in a function the label doesn't need to be written, only the ones after that.
If you just write:
let nowInFrench = now.inRegion("fr_FR").toString()
The error should go away.
I don't know why the example is written that way, maybe just for clarity.
Edit: having looked at the documentation I do think they have just included the labels to be clear as to what type they are using as an argument.

how do you iterate through elements in UI testing in Swift/iOS?

I understand how I could, for example look at one element in a table, but what's the correct way to simply iterate through all the elements, however many are found, to for example tap on them?
let indexFromTheQuery = tables.staticTexts.elementBoundByIndex(2)
Okay I succeeded in figuring out the simple syntax. I have just started working with Swift and so it took me sleeping on it to think of the answer.
This code works:
var elementLabels = [String]()
for i in 0..<tables.staticTexts.count {
elementLabels.append (tables.staticTexts.elementBoundByIndex(i).label)
}
print (elementLabels)
My guess is the answer is there is no way to do so.
The reason is because of my experience with one of the critical iOS components while making a number of UI tests: UIDatePicker.
If you record a test where you get the page up and then you spin the picker, you will notice that the commands are all non-specific and are screen related. In the case of the picker, however, community requests resulted in the addition of a method for doing tests: How to select a picker view item in an iOS UI test in Xcode?.
Maybe you can add a helper method to whatever controller contains this table. Also, keep in mind that you can easily add methods without polluting the class interface by defining them as extensions that are in test scope only.
For Xcode 11.2.1, SwiftUI and swift 5 based app, the following code works for testing a list, each element in this case appears as a button in the test code. The table is set up like this (for each row) :
NavigationLink(destination: TopicDetail(name: "Topic name", longDesc: "A description")) {
TopicRow(thisTopic: top).accessibility(identifier: "newTopicRow_\(top.name!)")
}
Then I catch the members of the table by getting the buttons into an array:
let myTable = app.tables.matching(identifier: "newTopicTable")
var elementLabels = [String]()
for i in 0..<myTable.buttons.count {
elementLabels.append (tablesQuery.buttons.element(boundBy: i).label)
}
print (elementLabels)
Finally, I deleted each member of the table by selecting the detail view where I have a delete button, again with
.accessibility(identifier: "deleteTopic"
I wanted to delete all members of the table:
for topicLabel in elementLabels {
let myButton = app.buttons[topicLabel]
myButton.firstMatch.tap()
app.buttons["deleteTopic"].tap()
}

Resources