IOS SWIFT PARSE : Pfcloud.callFunction - parse-platform

i have an old app in objective C using cloudcode to send pushes to back4app platform.
The app manage to send correctly the pushes and this is the code :
- (IBAction)inviaPush:(UIButton *)sender {
NSString *canale;
for (int i=0; i<=4; i++) {
switch (i) {
case 0:canale=#"TraduzioniEDI";
break;
case 1:canale=#"NavFtpYM";
break;
case 2:canale=#"InvioMailFTP";
break;
case 3:canale=#"VermasMto";
break;
case 4:canale=#"EdiAltova";
break;
default:
break;
}
NSString *testoPush =[NSString stringWithFormat:#"%# Test Invio %#", canale,[NSDate date]];
[PFCloud callFunctionInBackground:#"push"
withParameters:#{#"channels": #[canale], #"data": #{#"alert": testoPush,#"badge":#"Increment"}}
block:^( NSString *result, NSError *error) {
if (!error) {
NSLog(#"Risultato: %#",result);
} else{
NSLog(#"Errore %#",error);
}
}];
}
}
Running the code i receive the 5 pushes and in the info of back4app dashboard i find :
2020-03-02T01:14:53.533Z - Ran cloud function push for user undefined with:
Input: {"channels":["VermasMto"],"data":{"alert":"VermasMto Test Invio 2020-03-02 01:14:52 +0000"}}
Result: "Sent!!"
i tried to convert the program in swift
the code to send push is :
func inviaPush (){
var canale :String = ""
for i in 0...4
{
switch i {
case 0: canale = "TraduzioniEDI"
case 1: canale = "NavFtpYM"
case 2: canale = "InvioMailFTP"
case 3: canale = "VermasMto"
case 4: canale = "EdiAltova"
default: canale=""
}
let testoPush = "\(canale) Test invio - Swift"
PFCloud.callFunction(inBackground: "push", withParameters: ["channels": canale, "data": ["alert": testoPush,"badge":"Increment"]], block: {
(result: Any?, error: Error?) -> Void in
if error != nil {
if let descrip = error?.localizedDescription{
print(descrip)
}
}else{
print(result as! String)
}
})
}
}
in this case i receive no pushes, and in the info i find following :
2020-03-02T01:17:25.505Z - Ran cloud function push for user undefined with:
Input: {"channels":"NavFtpYM","data":{"alert":"NavFtpYM Test invio"}}
Result: "Sent!!"
2020-03-02T01:17:25.504Z - Can't count installations for PushStatus hm5hbCzDvd: bad $in value
Comparing the info shown in the dashboard i see a difference in input
in ojective C (Working) the in input the channel have a square bracket :
Input: {"channels":["VermasMto"],
while when sent from swift they have not
Input: {"channels":"NavFtpYM",
surely i'm calling the method PFCloud.callFunction in a wrong way.
Any suggestion ?
Fabrizio

the solution was simple ...
need to change
PFCloud.callFunction(inBackground: "push", withParameters: ["channels": canale, "data": ["alert": testoPush,"badge":"Increment"]], block: {
in
PFCloud.callFunction(inBackground: "push", withParameters: ["channels": [canale], "data": ["alert": testoPush,"badge":"Increment"]], block: {
Fabrizio

Related

Swift protocol extension: fatal error: can't unsafeBitCast between types of different sizes

I've defined a protocol with a protocol extension to simplify working with NSError.
protocol NSErrorConvertible: RawRepresentable {
var domain: String { get }
var localizedDescription: String { get }
}
extension NSErrorConvertible where RawValue == Int {
func generateError(parameters parameters: [String] = []) -> NSError {
let error = self.generateError(format: self.localizedDescription, parameters: parameters)
return error
}
func generateError(format format: String, parameters: [String] = []) -> NSError {
let description = String(format: format, arguments: parameters) // <-- BREAK
let error = NSError(domain: self.domain, code: self.rawValue, localizedDescription: description)
return error
}
}
extension NSError {
convenience init(domain: String, code: Int, localizedDescription: String) {
let userInfo = [NSLocalizedDescriptionKey : localizedDescription]
self.init(domain: domain, code: code, userInfo: userInfo)
}
}
Here's how the protocol is used:
enum DefaultEngineErrors: Int, NSErrorConvertible {
case ImagesNotSupported
case FooDoesNotHaveABar
case NilBar
var domain: String { return "DefaultEngineErrors" }
var localizedDescription: String {
switch self {
case .ImagesNotSupported: return "%s: Images are not supported."
case .FooDoesNotHaveABar: return "%s: Foo does not have a bar."
case .NilBar: return "%s: The bar is nil."
}
}
}
And here is how the protocol extension methods are called:
let error = DefaultEngineErrors.FooDoesNotHaveABar.generateError(parameters: ["\(foo.id)"])
When this code is run, the debugger breaks on the line that builds the description in the second generateError extension function and the following message is displayed in the debugger console:
fatal error: can't unsafeBitCast between types of different sizes
Note that if I replace the call to String(format:) with just format, everything works fine.
Q: What is wrong with what I've done here?
In addition to this, I can't examine the parameters in the protocol extension. The following message is displayed when I try:
(lldb) po format
error: <EXPR>:1:1: error: non-nominal type '$__lldb_context' (aka 'Self') cannot be extended
extension $__lldb_context {
^ ~~~~~~~~~~~~~~~
<EXPR>:15:5: error: value of type 'DefaultEngineErrors' has no member '$__lldb_wrapped_expr_54'
$__lldb_injected_self.$__lldb_wrapped_expr_54(
^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~
Swift string Array is not compatible with CVarArgType... or [CVarArgType]
try using.
extension NSErrorConvertible where RawValue == Int {
func generateError(format format: String) -> NSError {
let error = NSError(domain: self.domain, code: self.rawValue, localizedDescription: format)
return error
}
func generateError(args : CVarArgType...) -> NSError {
let returnString = NSString(format: self.localizedDescription, arguments: getVaList(args)) as String
// let returnString = withVaList(args) {
// NSString(format: self.localizedDescription, arguments: $0)
// } as String
let error = generateError(format: returnString)
return error
}
}
enum DefaultEngineErrors: Int, NSErrorConvertible {
case ImagesNotSupported
case FooDoesNotHaveABar
case FooWithMultiPar
case NilBar
var domain: String { return "DefaultEngineErrors" }
var localizedDescription: String {
switch self {
case .ImagesNotSupported: return "%#: Images are not supported."
case .FooDoesNotHaveABar: return "%#: Foo does not have a bar."
case .FooWithMultiPar: return "%#:%# Foo does not have a bar."
case .NilBar: return "%#: The bar is nil."
}
}
}
print(DefaultEngineErrors.FooDoesNotHaveABar.generateError("test"))
print(DefaultEngineErrors.FooWithMultiPar.generateError("test1","test2"))
Check this

Completion handler giving: Type of expression is ambiguous without more context, after updating to swift 2

I'm using the SODA Client for swift (Created by Socrata), I just updated to XCode 7 and swift 2 and found some troubles. The one I haven't been able to solve is the completion handler case when it finds an error, it's not accepting the line "syncCompletion(.Error (reqError))" that supposedly should get the error and return to main thread.
I've seen many errors with the same description here "Type of expression is ambiguous without more context", but not in completion handlers, I saw one using do - catch that is different. I'm don't know enough of swift to find out the way to change this.
Some answers suppose you should rewrite the code because some types could have change in swift 2, but I wouldn't know where to start rewriting.
Thanks in advance for your help.
var task = session.dataTaskWithRequest(request, completionHandler: { data, response, reqError in
// We sync the callback with the main thread to make UI programming easier
let syncCompletion = { res in NSOperationQueue.mainQueue().addOperationWithBlock { completionHandler (res) } }
// Give up if there was a net error
if reqError != nil {
syncCompletion(.Error (reqError))
return
}
// Try to parse the JSON
// println(NSString (data: data, encoding: NSUTF8StringEncoding))
var jsonError: NSError?
var jsonResult: AnyObject!
do {
jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
} catch var error as NSError {
jsonError = error
jsonResult = nil
} catch {
fatalError()
}
if let error = jsonError {
syncCompletion(.Error (error))
return
}
// Interpret the JSON
if let a = jsonResult as? [[String: AnyObject]] {
syncCompletion(.Dataset (a))
}
else if let d = jsonResult as? [String: AnyObject] {
if let e : AnyObject = d["error"] {
if let m : AnyObject = d["message"] {
syncCompletion(.Error (NSError(domain: "SODA", code: 0, userInfo: ["Error": m])))
return
}
}
syncCompletion(.Dataset ([d]))
}
else {
syncCompletion(.Error (NSError(domain: "SODA", code: 0, userInfo: nil)))
}
})
Solved, I replaced:
if reqError != nil
With
if let error = reqError
and:
syncCompletion(.Error (reqError))
with
syncCompletion(.Error (error))

Why doesn't this function get called?

Im following the Ray Wenderlich tutorial and converted most of the code to Swift. Im on part two but this function never gets called. I followed the tutoral but im not sure where to call it. I dont think its a delegate function also so I know that im supposed to call it somewhere but not sure where. Has anyone ever tried this tutorial and got it to work on Swift? Thanks!
Heres the link: http://www.raywenderlich.com/60998/game-center-tutorial-how-to-make-a-simple-multiplayer-game-with-sprite-kit-part-2
func match(theMatch: GKMatch, didReceiveData data: NSData, fromPlayer playerID: String) {
let message = UnsafePointer<Message>(data.bytes).memory
if(message.messageType == MessageType.kMessageTypeRandomNumber) {
let messageRandomNumber = UnsafePointer<MessageRandomNumber>(data.bytes).memory
println("Received random number: \(messageRandomNumber.randomNumber)")
var tie = false
if(messageRandomNumber.randomNumber == _ourRandomNumber) {
println("Tie")
tie = true
_ourRandomNumber = arc4random()
self.sendRandomNumber()
}
else {
var dictionary = ["\(playerIDKey)":"\(playerID)", "\(randomNumberKey)":"\(messageRandomNumber.randomNumber)"]
self.processReceivedRandomNumber(dictionary)
}
if(_receivedAllRandomNumbers) {
_isPlayer1 = self.isLocalPlayerPlayer1()
}
if(!tie && _receivedAllRandomNumbers) {
if(_gameState == GameState.kGameStateWaitingForRandomNumber) {
_gameState = GameState.kGameStateWaitingForStart
}
self.tryStartGame()
}
}
else if(message.messageType == MessageType.kMessageTypeGameBegin) {
println("Begin game message received")
_gameState = GameState.kGameStateActive
self.delegate?.setCurrentPlayerIndex(self.indexForLocalPlayer())
}
else if(message.messageType == MessageType.kMessageTypeMove) {
println("Move message received")
let messageMove = UnsafePointer<MessageMove>(data.bytes).memory
self.delegate?.movePlayerAtIndex(self.indexForPlayerWithId(playerIDKey))
}
else if(message.messageType == MessageType.kMessageTypeGameOver) {
println("Game over message received")
let messageGameOver = UnsafePointer<MessageGameOver>(data.bytes).memory
self.delegate?.gameOver(messageGameOver.player1Won)
}
}
The delegate method match:didReceiveData:fromPlayer: has been deprecated. Use match:didReceiveData:fromRemotePlayer: instead.
Make sure you set the delegate, doing something like:
func matchmakerViewController(viewController: GKMatchmakerViewController, didFindMatch match: GKMatch) {
theMatch = match
match.delegate = self
...
}
That is the viewController:didFindMatch delegate for GKMatchmakerViewControllerDelegate.
You need to delegate from both GKMatchmakerViewControllerDelegate and GKMatchDelegate.
Yeah, I know this is an old thread, but the OP hasn't had any success yet.
match:didReceiveData:fromPlayer: is a GKMatchDelegate optional method which will trigger when the match received data sent from the player.
So please don't try to call it directly. It will be called by GameKit when data is received from a player.
#protocol GKMatchDelegate <NSObject>
#optional
// The match received data sent from the player.
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromRemotePlayer:(GKPlayer *)player NS_AVAILABLE(10_10, 8_0);
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID NS_DEPRECATED(10_8, 10_10, 4_1, 8_0, "use match:didReceiveData:fromRemotePlayer:");
#end;
This also is declared in GameKitHelper.h class as a GameKitHelperDelegate
#protocol GameKitHelperDelegate
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data
fromPlayer:(NSString *)playerID;
#end
This delegate method is calling from the below method when the match received data sent from the player
#pragma mark GKMatchDelegate
// The match received data sent from the player.
- (void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID {
if (_match != match) return;
[_delegate match:match didReceiveData:data fromPlayer:playerID];
}

How can I call a text from a random switch case?

- (IBAction)postToTwitter:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#"This is the text which should be called from switch case"];
[self presentViewController:tweetSheet animated:YES completion:nil];
}
}
////And here is my switch case just to give an idea to you
-(IBAction) random {
int text = arc4random() % 3;
switch (text) {
case 0:
textview.text = #"Text example 1";
break;
case 1:
textview.text = #"Text example 2";
break;
case 2:
textview.text = #"Text example 3";
break;
default:
break;
}
}
Just I want to input Text example 1, Text example 2 and Text example 3 to my Twit content while my switch case is changing.
Help please!!! :'(
Simply replace it with
[controller setInitialText:textview.text];

Cannot invoke '==' with an argument list of type '($T2, OSStatus)' in Xcode 6.1

When i was on Xcode version 6, the class i was using for accessing the Keychain was working but now in version 6.1 it is not working
Here is a part of the Keychain access class:
class func setData(value: NSData, forKey keyName: String) -> Bool {
var keychainQueryDictionary: NSMutableDictionary = self.setupKeychainQueryDictionaryForKey(keyName)
keychainQueryDictionary[kSecValueData as String] = value
// Protect the keychain entry so it's only valid when the device is unlocked
keychainQueryDictionary[kSecAttrAccessible as String] = kSecAttrAccessibleWhenUnlocked
let status: OSStatus = SecItemAdd(keychainQueryDictionary, nil)
if Int(status) == errSecSuccess { //I GET THE ERROR HERE
return true
} else if Int(status) == errSecDuplicateItem {
return self.updateData(value, forKey: keyName)
} else {
return false
}
}
It is not the only place where it is doing it here is another part of the code:
class func removeObjectForKey(keyName: String) -> Bool {
let keychainQueryDictionary: NSMutableDictionary = self.setupKeychainQueryDictionaryForKey(keyName)
//Delete
let status: OSStatus = SecItemDelete(keychainQueryDictionary);
if Int(status) == errSecSuccess { //GET ERROR HERE
return true
} else {
return false
}
}
It look likes the problem is with errSecSuccess can somebody help me please
OSStatus is an alias for Int32, so I think you solve that by removing the conversion to Int, like in:
if status == errSecSuccess {
Side note: your multiple if/elseif/else can be replaced by a switch:
switch (status) {
case errSecSuccess:
...
case errSecDuplicateItem:
...
default:
...
}
more readable in my opinion

Resources