swift2 - Swift 2.0 new 'perform changes' of PHPPhotoLibrary won't work -


i downloaded xcode 7 beta 2 , trying use knowledge of swift make app deletes photo user's camera roll. know how swift 1.2, can't seem in swift 2.0. tried searching through documentation learn how use 'performchange' function in swift 2.0, won't work. here's swift :

phphotolibrary.sharedphotolibrary().performchanges({     phassetchangerequest.deleteassets(arraytodelete) }, completionhandler: { (success, error) -> void in     nslog("finished deleting asset. %@", (success ? "success" : error)) }) 

here's error:

cannot invoke performchanges argument list of type (() -> _, completionhandler: (_, _) -> void)

any appreciated!!

the swift compiler has issues reporting correct root cause of type-checking failure in complex expression. rather show correct form of code, i'll walk through how found way there, can reuse process future debugging. (skip down tldr if must.)


first, you've got error of form:

cannot invoke 'function' argument list of type 'params'

that means function call has failed type-check. because you're calling function parameters include closures, you'll need @ behavior of closures narrow down type-checking issues.

let's start making closures explicitly return void:

phphotolibrary.sharedphotolibrary().performchanges({     phassetchangerequest.deleteassets(arraytodelete)     return }, completionhandler: { (success, error) -> void in     nslog("finished deleting asset. %@", (success ? "success" : error))     return }) 

what's going on here? you've declared type of completion handler returning void, why return statement? swift type checking works both bottom-up , top-down, , if there's error along either way, can't make assumptions other. here, have 2 single-expression closure, swift has consider each one's single expression an implicit return statement.

if 1 of statements has type-checking error, statement's return type becomes <<error type>>, , because it's single-statement closure, closure's return type becomes <<error type>>, , therefore function call closure parameter fails, because function expecting closure returns void, not closure returns <<error type>>.

indeed that's what's happening — once make above change, different error, on nslog statement (with "success" highlighted):

'_' not convertible 'stringliteralconvertible'

that's bit unclear still, we're closer root of problem. if replace (success ? "success" : error) part of log statement static (say, "success"), compiles. so, let's separate , dissect ternary operation see what's going wrong inside it.

let successstring = "success" let report = (success ? successstring : error) nslog("finished deleting asset. %@", report) 

this gets new error, on ? of ternary operator:

'nsstring' not subtype of 'nserror'

huh? automatic conversion of swift.string nsstring, maybe? let's make conversion explicit sure:

let successstring = "success" nsstring let report = (success ? successstring : error) 

type of expression ambiguous without more context

now reach crux of matter. what, indeed, type of report supposed be? if success true, it's nsstring, if false, it's nserror? (the type of error, inferred declaration of performchanges(_:completionhandler:)). sort of type hand-waviness fly in c, swift more strict such things. (someone wise once said, "incomplete type specification leads unclear memory layout, unclear memory layout leads undefined behavior, undefined behavior leads suffering." or that.)

the supertype of both nsstring , nserror? any, , swift reluctant infer type. (because if infer can anything, type information worthless.) , if try use type manually, errors when try pass nslog:

let report: = (success ? successstring : error) nslog("finished deleting asset. %@", report) 

cannot invoke 'nslog' argument list of type '(string, any)'

expected argument list of type '(string, [cvarargtype])'

those errors take off down rabbit hole of c vararg functions, let's step bit — type nslog want argument? nslog objc function, format string substitution (the %@ business) built on nsstring stringwithformat. per docs, when use %@ token, nsstring looks object in corresponding parameter , calls description method. because implementation objc , part of cocoa frameworks (dating before dinosaurs wiped out), not swift thing, stands reason pure-swift type any won't work here.

nsobject cocoa type pass nslog function. however, declaring type of report won't fly, either — can't implicitly convert both branches of ternary operator nsobject. error parameter optional — inferred type nserror?, remember? , that's swift type, not cocoa type.

so that's final problem — have ternary operator that's trying have 1 branch sensible object, , other branch still-wrapped optional. indeed, force-unwrapping optional clears compiler errors:

let report = (success ? successstring : error!) // report type-infers nsobject nslog("finished deleting asset. %@", report) 

now we've fixed everything, can put wheels on , collapse down...


tldr: unwrap optionals.

phphotolibrary.sharedphotolibrary().performchanges({     phassetchangerequest.deleteassets(arraytodelete) }, completionhandler: { success, error in     nslog("finished deleting asset. %@", (success ? "success" : error!)) }) 

we know it's safe force-unwrap here because of api contract: if success true, error nil, if success false, there an error.

(this may have worked without unwrapping on previous sdk versions because closure type in performchanges(_:completionhandler:) have used implicitly-unwrapped optional before apple audited apis nullability.)


Comments

Popular posts from this blog

toolbar - How to add link to user registration inside toobar in admin joomla 3 custom component -

linux - disk space limitation when creating war file -

How to provide Authorization & Authentication using Asp.net, C#? -