Alamofire 3.0 and swift 2.0 broke my APIWrapper - api

I recently updated to swift 2.0 and it destroyed my alamofire serializer and API wrapper.
extension Alamofire.Request {
class func authResponseSerializer() -> Serializer {
return {request, response, data in
if data == nil {
return (nil, nil)
}
var jsonError: NSError?
let jsonData:AnyObject?
do {
jsonData = try NSJSONSerialization.JSONObjectWithData(data!, options: [])
} catch var error as NSError {
jsonError = error
jsonData = nil
} catch {
fatalError()
}
if jsonData == nil || jsonError != nil {
return (nil, jsonError)
}
let json = JSON(jsonData!)
if json.error != nil || json == nil {
return (nil, json.error)
}
var auth:Authorization = Authorization(json: json)
return (auth, nil)
}
}
func responseAuthorization(completionHandler: (NSURLRequest, NSHTTPURLResponse?, Result<Authorization>) -> Void) -> Self {
return response(responseSerializer: Request.authResponseSerializer(), completionHandler: completionHandler)
}
in the request extension i get the error
and in the second func responseAuthoriztion
Use of undeclared type 'Serializer'
I get the error generic type Result specialized with too few type parameters (got 1, but expected 2)
How do i migrate my code to alamofire 3.0 and swift 2.0? I've been reading the migration guides and can't figure this out, many other people I'm sure are dealing with this same problem.

Related

iOS Swift5 how can I check if an object is of type declared in array of types [Class.Type]?

I'm experimenting with error handling and am interested in what I can do with an array of class types.
Is there a way for me to check if an object is of type declared in the array of [Class.Type] ?
The "is" operator refuses to work with the type extracted from an array. How can I check if an object can be cast to that type or is an instance of that type?
class FooError: NSError { ... }
class BarError: NSError { ... }
protocol ErrorHandling {
var types: [NSError.Type] { get }
func handle(error: NSError)
}
class ErrorHandler: ErrorHandling {
var types = [FooError.self, BarError.self]
func handle(error: NSError) {
for errorType in types {
if error is errorType {
}
}
}
}
The Swift operator for this is is see example below
if object is Class.Type {
// object is of type Class.Type
}
It turns out I needed to use equality and type(of:) function
public func handle(error: NSError) {
for errorType in types {
if type(of: error) == errorType {
print("Handling: \(error), \(errorType)")
return
}
}
print("Could not handle: \(error))")
}
let api = ErrorHandler()
api.handle(error: FooError())
api.handle(error: BarError())
api.handle(error: NSError(domain: "test", code: 0, userInfo: nil))
Handling: Error Domain=test Code=0 "(null)", FooError
Handling: Error Domain=test Code=0 "(null)", BarError
Could not handle: Error Domain=test Code=0 "(null)")

Accessing Objective-C Pointers in Swift

I have this Objective-C Code fragment, which I want to express in Swift
CFArrayRef windowList;
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute, (CFTypeRef *)&windowList);
if ((!windowList) || CFArrayGetCount(windowList)<1)
continue;
AXUIElementRef windowRef = (AXUIElementRef) CFArrayGetValueAtIndex( windowList, 0);
CFTypeRef role;
AXUIElementCopyAttributeValue(windowRef, kAXRoleAttribute, (CFTypeRef *)&role);
The first thing I´m not sure about: Who allocates the memory behind the windowListPointer.
I tried with this fragment:
var windowListPointer : UnsafeMutablePointer<Optional<AnyObject>>
AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, windowListPointer );
But that does not even compile: It complains, the windowListPointer is not initialised.
What Object I could create, to let the WindowListPointer point to?
If you pass an UnsafeMutablePointer<Optional<AnyObject>> as the last
argument to AXUIElementCopyAttributeValue() then you must
initialize it by allocating (and ultimately releasing) memory:
var resultPtr: UnsafeMutablePointer<Optional<AnyObject>> = UnsafeMutablePointer.allocate(capacity: 1)
resultPtr.initialize(to: nil)
let result = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, resultPtr)
// ...
resultPtr.deinitialize()
resultPtr.deallocate(capacity: 1)
It is easier
to pass the address of an Optional<AnyObject> variable
with &. Then conditionally
cast the received object to the expected type, in this case an
array of AXUIElement:
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(appRef, kAXWindowsAttribute as CFString, &value)
if result == .success, let windowList = value as? [AXUIElement] {
// use `windowList`
}
and similarly:
if let window = windowList.first {
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(window, kAXRoleAttribute as CFString, &value)
if result == .success, let role = value as? String {
// use `role` ...
}
}
One could define a generic utility function which encapsulates
all the casting:
func axUICopyAttributeValue<T>(of element: AXUIElement, attribute: String, as type: T.Type) -> T? {
var value: AnyObject?
let result = AXUIElementCopyAttributeValue(element, attribute as CFString, &value)
if result == .success, let typedValue = value as? T {
return typedValue
}
return nil
}
Example usage:
if let windowList = axUICopyAttributeValue(of: appRef, attribute: kAXWindowsAttribute, as:[AXUIElement].self) {
for window in windowList {
if let role = axUICopyAttributeValue(of: window, attribute: kAXRoleAttribute, as: String.self) {
// ...
}
}
}
CFArray is the Foundation C version of NSArray (since C doesn't understand Objective C NSObjects). Swift papers over both NSArray and CFArray for you so you don't need to use a pointer; you should just be able to cast it to a Swift array of the appropriate type with as?

How do I stub sqlmock to never return error?

I can not test the function NewDao that uses a database arbitrarily. I want to check whether the returned Dao have neither nil client nor nil product.
type Dao struct {
client ClientDao
product ProductDao
}
func (d *Dao) Client() ClientDao {
return d.client
}
func (d *Dao) Product() ProductDao {
return d.product
}
func NewDao(db *sql.DB) (*Dao, error) {
if db == nil {
return nil, errors.New("Can't create a dao from nil database")
}
client, err := newClientDao(db) // Uses db arbitrarily
if err != nil {
return nil, err
}
product, err := newProductDao(db) // Uses db arbitrarily
if err != nil {
return nil, err
}
return &Dao{client, product}, nil
}
I test NewDao() using sqlmock but it always fails because I don't know what the mock needs to expect.
func TestNewDao(t *testing.T) {
db, mock, err := sqlmock.New()
if err != nil {
t.Fatal("Can't create database for test dao")
}
// How to set mock to expect anything and never fail?
// mock.ExpectQuery(any) ?
dao, err := NewDao(db)
// err is never nil, because mock has no expectations
if err != nil {
t.Fatal("Can't create dao for test dao.User %q", err)
}
if dao.User() == nil {
t.Fatalf("User dao is nil")
}
if dao.Client() == nil {
t.Fatalf("Client dao is nil")
}
}
Does any one know how to stub the sqlmock for achieving my purpose? Or can appoint an alternative to sqlmock lib?
You are missing the second item in your last return in NewDao:
return &Dao{client, product}
should be:
return &Dao{client, product}, nil
Return statements have to "return" all the things declared in the function header.
Your Dao.Client and Dao.Product methods themselves make no calls to any dependency and because of that there is nothing for you to mock. There is no point in using a mock for testing these two methods.
And although testing one liners like these may not be the most sensible thing to do, if you want to test them anyway you just need to make sure that the value they return equals the value of the field that they're supposed to return.
func TestDaoClient(t *testing.T) {
var client ClientDao // TODO: prepare a client dao value for test
tests := []struct{
name string
dao *Dao
want ClientDao
}{{
name: "should return client dao",
dao: &Dao{client: client},
want: client,
}, {
name: "should return nil",
dao: &Dao{client: nil},
want: nil,
}}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.dao.Client(); !reflect.DeepEqual(got, tt.want) {
t.Errorf("client got=%v, want=%v", got, tt.want)
}
})
}
}
Now you can do the same for the Dao.Product method.

SWIFT2.0: function returns before task is completed

I'm pretty sure this is easy for most of you, but i'm a beginner and i cannot figure this one out.
I build a function to parse a JSON file online. That function should returns a String once the file has been parsed, but it does not wait for the task to be completed before "return". Therefore, i always end up with a wrong value.
my function:
func getJsonDataFromPath(path: String) -> String {
var videoId: String
videoId = "++ empty ++"
let url = NSURL(string:path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if let httpResponse = response as? NSHTTPURLResponse {
print("HTTP RESPONSE: \(httpResponse.statusCode)")
} // END OF if let httpResponse = response as? NSHTTPURLResponse
let json = JSON(data: data!)
// print(json)
if (json.count > 0) {
videoId = json[0]["videoId"].string!
print("videoId is: \(videoId)")
}
}
task.resume()
return videoId
}
and its call:
override func viewDidLoad() {
super.viewDidLoad()
let test = getJsonDataFromPath("http://coulon.xyz/JobX/APIs/getListOfJobs.php")
print("Value returned by getJsonDataFromPath: \(test)")
}
I always get the output in the wrong order:
Value returned by getJsonDataFromPath: ++ empty ++
HTTP RESPONSE: 200
videoId is: kzv1NQGdsyk
How can i make sure task.resume is completed before returning the value ?
Thank a lot in advance,
Regards,
Julien
You should implement Swift closure like that:
func getJsonDataFromPath(path: String, completion: (item: String)-> Void){
var videoId: String
videoId = "++ empty ++"
let url = NSURL(string:path)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
if let httpResponse = response as? NSHTTPURLResponse {
print("HTTP RESPONSE: \(httpResponse.statusCode)")
} // END OF if let httpResponse = response as? NSHTTPURLResponse
let json = JSON(data: data!)
// print(json)
if (json.count > 0) {
videoId = json[0]["videoId"].string!
print("videoId is: \(videoId)")
completion(item: videoId)
}
}
task.resume()
}
And its call:
override func viewDidLoad() {
super.viewDidLoad()
getJsonDataFromPath("http://coulon.xyz/JobX/APIs/getListOfJobs.php") { (test) -> Void in
print("Value returned by getJsonDataFromPath: \(test)")
}
}

Swift pass block from Objective-C to Swift

I have a method in Objective-C that takes a parameter and returns a result in a block. How do I return this result through a bridging header to a swift block? Note I have other non-block functions returning and this works fine.
Objective-C
- (void)performMethod:(NSString*)myString
{
[self.class
doSomething:myString
onSuccess:^(NSArray * results) {
// Return results
}
onFailure:^(NSError * error) {
// Return error
}];
}
Bridging header
?
Swift
class.performMethod(myString:String)->(results) in NSArray {
}
the trouble is that your Objective C function return void, not some block
how to deal with block in swift ? see the example below
// this block takes an Int as parameter and returns an Int
let myBlock: (Int)->Int = { i in
return i
}
let i = myBlock(10)
print(i) // 10
// this block takes no parameters and return an empty Array<Int>
let myBlock2: ()->Array<Int> = { Void in
return [Int]()
}
print(myBlock2.dynamicType) // () -> Array<Int>
let arr = myBlock2()
print(arr, arr.dynamicType) // [] Array<Int>
from what i can see in your code, you try to do something like
import Foundation
func bar(str: String, onSucces: ()-> NSArray, onError: ()->NSError) {
// do something with str
if str == "alfa" {
// success
let arr = onSucces()
print(arr)
} else {
let err = onError()
print(err)
}
}
func foo(str: String) -> Void {
bar(str, onSucces: { () -> NSArray in
return NSArray(array: [str])
}) { () -> NSError in
return NSError(domain: "error", code: -1, userInfo: nil)
}
}
foo("alfa")
/*
(
alfa
)
*/
foo("")
/*
Error Domain=error Code=-1 "(null)"
*/