Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Kallikrates
Jul 7, 2002
Pro Lurker
Not swift related, but if you have same sized images, or same sized groups of images you should look into Fast Image Cache from Path, its a cool library. We pull very large images out of it with zero latency.

Adbot
ADBOT LOVES YOU

Doh004
Apr 22, 2007

Mmmmm Donuts...

Kallikrates posted:

Not swift related, but if you have same sized images, or same sized groups of images you should look into Fast Image Cache from Path, its a cool library. We pull very large images out of it with zero latency.

Fully aware of good, proven, image caches out there, definitely. Decision was to run our own so I do as I'm told!

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

Doh004 posted:

Fully aware of good, proven, image caches out there, definitely. Decision was to run our own so I do as I'm told!

Rolling your own cache is never, ever, not a bad idea.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
Nevermind, that's what I get for only looking at Swift documentation, and not double-checking against Objective-C methods that have been deprecated.

Axiem fucked around with this message at 21:29 on Mar 8, 2015

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Is there any intention of allowing us to create C function pointers? I started down a horrible, horrible road using libffi that technically allows one to bounce blocks to C function pointers from Swift and it technically works, but dear God it's gross.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
We're actually looking at that, yes.

Does the API really need a pure C function pointer? It can't take a context or anything? That's unfortunate.

duck monster
Dec 15, 2004

ultramiraculous posted:

What you mean scalaz's ★ operator doesn't mean "monad transformer" or whatever to most people?

Scala broke my brain. I honestly haven't felt like its been too long since I was at uni, until I tried to teach myself Scala. And I don't mean "Hard math solving" like Haskel. Haskel makes sense to me because I understand its meant for people who can still remember all there com-sci algorithm theory poo poo. But Scala isn't even that. Its just loving broken in the same way Perl is broken. Its just ugly and weird and non intuitive.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
So, serialization.

I've got an object with a dictionary of structs. I'd like to serialize that dictionary of structs such that the next time I run the application, I can load it in and get the same thing. You know, basic serialization.

Where I'm running into trouble is trying to figure out how to actually serialize those structs. I can make the class that owns the dictionary NSCoding-compliant, but I don't have any good way of serializing a dictionary of structs. If it were just one struct, I could encode the values necessary to re-create it--but to my knowledge, there's no easy way to do a set of structs en masse like that.

At the moment, my solution is to turn my structs into classes and have them also conform to NSCoding, but that doesn't feel right to me, since they're supposed to be structs. But at the moment, I don't see any particularly good way of doing this. Trying to find anything on google doesn't get me very far, though a lot of people have figured out how to turn JSON into Swift structs/objects (which doesn't help me, as I'd need the inverse).

Does my problem make sense? Have other people solved something like it? Is there a recommended approach? Is this something that might get addressed with a future version of Swift? Am I missing something obvious?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
It's the same basic concept, you just don't get the benefit of helpful framework support or reflection. Write a function that maps your structs into primitives, serialize the primitives as JSON or plists or whatever, and you're all set in that direction.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
You'll note that none of the fancy Swift JSON frameworks say anything fancy about serializing.

I ran into the same thing; as far as I know, Swift doesn't have any way to require a certain struct layout in memory yet (not that it would necessarily be safe anyway). It doesn't have much in the way of reflection support either, otherwise we could ask for the list of fields and their types in the struct, then recursively break them down or use extensions to define the serialization format.

So basically just write it all by hand.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
My cold, performance-optimizing heart doesn't want me to tell you this, but I am fairly certain that end-users can call reflect.

Doctor w-rw-rw-
Jun 24, 2008

rjmccall posted:

My cold, performance-optimizing heart doesn't want me to tell you this, but I am fairly certain that end-users can call reflect.

Serializable in Java is the worst, though. Combining reflection and saving objects to cold storage is pitfall city. IMO Swift-native NSCoding-like serialization would be ideal, not unlike Parcelable on Android, one of their good ideas.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

rjmccall posted:

My cold, performance-optimizing heart doesn't want me to tell you this, but I am fairly certain that end-users can call reflect.

Look, if you break someone's heart too many times they eventually give up.

code:
Welcome to Swift version 1.2. Type :help for assistance.
  1> struct PayMe { 
  2.     var myFuckingMoney:String? 
  3. }    
  4> let inst = PayMe()
inst: PayMe = {
  myFuckingMoney = nil
}
  5> let x = reflect(inst)
  6> let isString = x[0].1.value is String
isString: Bool = false
  7> let isString = x[0].1.value is String?
repl.swift:8:29: error: cannot downcast from 'Any' to a more optional type 'String?'

8> let ttt:Any.Type = Optional<String>.self
ttt: Any.Type = Swift.Optional
 9> let wargle = x[0].1.valueType == ttt
repl.swift:12:21: error: binary operator '==' cannot be applied to two Any.Type operands

 10> let bargle = x[0].1.valueType
bargle: Any.Type = Swift.Optional
First, you have to have an instance. Reflecting the type yields a mirror with zero tuples in it.

Second, the compiler refuses to let you discover the type. Even though NSNumber.self (or any other type really) is totally a valid Any.Type, you aren't allowed to compare them. You can unsafeBitCast but class clusters and inheritance make that super dicy, though in some scenarios it does "work".

To be fair the scenario where you already have an instantiated object and properly massage it by fetching the reflected values then casting with "as?" does work to discover the types. It's just useless for a serializer.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
:patriot: That will make an excellent set of bugs, thank you, I'll take care of it.

Sorry for the run-around.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
I agree that not being able to inspect the type abstractly is unfortunate.

You should also be able to just use == with metatype values, but as a workaround — a more general one, maybe, that supports subclassing properly — you can also test type equality by casting metatype values to concrete metatypes, i.e. x[0].1.valueType is Optional<String>.Type.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

rjmccall posted:

I agree that not being able to inspect the type abstractly is unfortunate.

You should also be able to just use == with metatype values, but as a workaround — a more general one, maybe, that supports subclassing properly — you can also test type equality by casting metatype values to concrete metatypes, i.e. x[0].1.valueType is Optional<String>.Type.

Well poke me in the eye; I always forget about X.Type vs X.self...


Is it fair to say that Optional<String>.self is the type which itself is an instance of the Optional<String>.Type metatype? In other words are the Swift types themselves instances of metatypes like Objective-C? If not, what's the difference between the "value" in self vs Type?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Ender.uNF posted:

Is it fair to say that Optional<String>.self is the type which itself is an instance of the Optional<String>.Type metatype? In other words are the Swift types themselves instances of metatypes like Objective-C? If not, what's the difference between the "value" in self vs Type?

The runtime representation of a type — the type's runtime descriptor — is a value of the corresponding metatype. For most types, it it the only value of the metatype, and so the metatype actually requires no storage at runtime, just like an empty tuple type. But for class types, their metatypes, their meta-metatypes, etc., the metatype includes the corresponding values of subclasses as well.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
With fiddling with NSJSONSerialization, I've been able to do some custom stuff around serializing structs, which makes sense. Thanks, thread!

But now I'm beset by a bit more of a design-pattern-theory question. In the general case, what is preferred: that an object knows how to serialize/deserialize itself, or that another object (/function) knows how to do it, and why?

To a certain extent, I can see arguments for both sides, and I know the Foundation way is for objects to do it themselves, but I don't know why that's the case, or if another method is now preferred in language design.

I kind of figure that now that Swift is all new and shiny, we should consider going with the preferred paradigm instead of slavishly following Foundation just because.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I think the standard approach is something like make a JSONSerializable protocol and extend your types with implementations of toJSON(). The protocol aids you in making helpers for e.g. collections of JSONSerializable instances.

Also Foundation has kind of a hybrid approach with NSCoder and NSCoding, I wouldn't say it's left entirely up to the serialized objects.

Kallikrates
Jul 7, 2002
Pro Lurker
In obj-c I never found/saw "one true way". You have a lot of object mappers (restkit, objectmapper, etc), man hand parsed objects the JSON.

In swift right now the least impactful I've found is to/fromJSON methods with some private structs that handle mapping of nested structures. Right now the service layer of our app is an obj-c framework.

I don't trust those crazy swift JSON libraries (yet?). In my opinion they just create DSL's around optional unwrapping, and I don't like DSLs.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Kallikrates posted:

I don't trust those crazy swift JSON libraries (yet?). In my opinion they just create DSL's around optional unwrapping, and I don't like DSLs.

These were the first thing I thought of when rjmccall mentioned "functional cargo-culting" upthread.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
They're a great exploration into what's possible, but there's a few steps in between that and a library you should actually use in real applications.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
I'm using SwiftyJSON for parsing my JSON into objects, and I haven't had any problems with it. Certainly, I'd much rather something standard from Apple, but I like this much more than futzing with NSJSONSerialization and NSObjects.

On another note, today I spent a good hour trying to figure out some of my serializing-into-JSON stuff before I discovered that you can't cast an array of Swift objects into an array of Swift protocols.

Namely, if class Foo conforms to protocol Bar, if you have x: [Foo] and y: [Bar], trying to assign x into y will cause a crash with the very unhelpful message that the array can't be bridged from Objective-C.

Apparently you can do some voodoo to make it work if you sprinkle @objc around in places, but I am trying very hard to be pure Swift, and not be beholden to any Objective-C things like that.

I'm probably crazy :shrug:

Honestly, though, while I love Swift, I have a guy at my workplace that wants to start having us write new classes in Swift, and I'm just not quite there yet. Personal project with no timeline, sure. Major piece of software for major client? I'm just a little wary.



...but I really do look forward to seeing what cool new stuff gets revealed at WWDC. I imagine (hope) there'll be a major version release then.

Though still, at the top of my wishlist is for Refactor -> Rename to work in Xcode.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
I now want constrained extensions for generic types. In C# you can write extensions for specific generic specializations but in practice that's not horribly limiting because C# interfaces (protocols) support generic parameters.

I tried to add contains as an extension to Array and realized that I was being ridiculous because T is not constrained to be comparable and there's no way to say "introduce contains on any Array containing comparables".

brap
Aug 23, 2004

Grimey Drawer
Isn't contains a top level function for sequences in swift?

Kallikrates
Jul 7, 2002
Pro Lurker
It is but he said constrained, so maybe he wants to contain by type, instead of value or predicate, and test for Comparable instead of Equatable.

Any such function would need to be defined globally on SequenceType or CollectionType and their respective element types. Where the element type is a comparable.

Something like contains(domain, $0 > 1) currently doesn't work because of the current definition.

+1 for type array by protocol. I really hope there is a plan to support:

swift:
let barables: [Any<Bar>] = [Foo<Bar>(), Baz<Bar>()]

Ala obj-c

id barables = @[[Foo<Bar> new], [Baz<Bar> new] ]

Without all the @obj-c's


Also IBOutlets one day supporting non NSObject types, Swift needs <Coding> and AwakefromNib

But the it would be nice to not have to pass through NSObject to get NSCoding/Archiving, and Nib support. Hard to create pure swift projects without that.

The code to bind to a swift class that implements UITableViewDelegate has alot of unneeded @obj-c.

Kallikrates fucked around with this message at 18:31 on Mar 22, 2015

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Kallikrates posted:

It is but he said constrained, so maybe he wants to contain by type, instead of value or predicate, and test for Comparable instead of Equatable.

Any such function would need to be defined globally on SequenceType or CollectionType and their respective element types. Where the element type is a comparable.

Something like contains(domain, $0 > 1) currently doesn't work because of the current definition.

I think you will be happy sooner rather than later. For now, you can define a global function that does it.

Kallikrates posted:

+1 for type array by protocol. I really hope there is a plan to support:

swift:
let barables: [Any<Bar>] = [Foo<Bar>(), Baz<Bar>()]

Ala obj-c

id barables = @[[Foo<Bar> new], [Baz<Bar> new] ]

Without all the @obj-c's

Is Bar is a protocol? What are you asking for that you can't do with let barables: [Bar] = ...? I actually have no idea what you're trying to say with Foo<Bar>, because it apparently isn't either generic argument application or an Obj-C qualified class type. Nor do I have any idea what that supposed obj-c syntax is doing.

brap
Aug 23, 2004

Grimey Drawer
Oh, I defined an any() function like LINQ in .NET which iterates until it finds an element that returns true for the given predicate.

Kallikrates
Jul 7, 2002
Pro Lurker

rjmccall posted:

I think you will be happy sooner rather than later. For now, you can define a global function that does it.


Is Bar is a protocol? What are you asking for that you can't do with let barables: [Bar] = ...? I actually have no idea what you're trying to say with Foo<Bar>, because it apparently isn't either generic argument application or an Obj-C qualified class type. Nor do I have any idea what that supposed obj-c syntax is doing.

Guilty of psuedo coding the heck out of that but yes Bar is a protocol, that Foo and Baz conform to. Creating a "typed" array of Barables is whatever in obj-c because arrays are not typed so you can just assume by the variable name that it contains a collection of Bar implementing objects. Looks like I misread the question, and or that something has changed in swift since I last tried this: (around <1.0) works fine now but I swear I remember fighting obj-c interop around this.

Something I found while playing with this:

code:

protocol Bar {}
protocol Baz: Bar {}

class A: NSObject, Bar {}

class B: UIView, Bar {}

class C: Bar {
    init() {}
}

class D: Baz {
    init() {}
}

var foo: Array<Bar> = [A(), B(), C(), D()]
//sub type of bar
var frump: Array<Baz> = [D()]

foo = frump // should work?
It looks like when assigning typed arrays the types are only checked for strict equality, not type hierarchy?

Kallikrates
Jul 7, 2002
Pro Lurker

fleshweasel posted:

Oh, I defined an any() function like LINQ in .NET which iterates until it finds an element that returns true for the given predicate.

I think lots of swift projects have growing "Global" functions file that extend collections/sequences etc. Ours has some(), find() for collectionTypes with a predicate, and compress(): unwraps a sequence discarding nils.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Kallikrates posted:

It looks like when assigning typed arrays the types are only checked for strict equality, not type hierarchy?

I agree that this should work. It would generally require a full copy of the array, but sometimes that's acceptable. We'd probably want to work on high-level optimization before we committed to it, just so that simple things like creating an array on one line and then assigning it on the next to something that needed an element upcast didn't create an unnecessary intermediate array, but it's worth asking for it. In the meantime, you can use map(frump) { $0 }.

Kallikrates posted:

I think lots of swift projects have growing "Global" functions file that extend collections/sequences etc. Ours has some(), find() for collectionTypes with a predicate, and compress(): unwraps a sequence discarding nils.

These things are not completely unlikely to find themselves in the standard library if you bring them to our attention. Starting a thread on the developer forums ("Hey, what collection operations are you guys using? We've found these useful...") would be good enough.

compress is basically flatMap, though.

brap
Aug 23, 2004

Grimey Drawer
I did something similar to your compress() only I named it mapUnwrap. Maybe that's a dumb name though.
extension Array {
func mapUnwrap(transform: T -> U?) -> [U];
}

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do

rjmccall posted:

Is Bar is a protocol? What are you asking for that you can't do with let barables: [Bar] = ...?

There was a point where I had a class Foo that conformed to protocol Bar. Doing this code would consistently cause a crash:

code:
let x: [Foo] = /* generate an array of Foo things */
let y: [Bar] = x
With an error about being unable to bridge from Objective-C.

I am in Swift 1.1, not 1.2, so I'm a bit reticent to file a defect, because I can only imagine this is either a known bug or a feature that hasn't yet been implemented. It's just frustrating, though I found a different way of accomplishing what I wanted ultimately.

Kallikrates
Jul 7, 2002
Pro Lurker

rjmccall posted:

I think you will be happy sooner rather than later. For now, you can define a global function that does it.

We can't use 1.2 until we can do distributions via test flight with it. Hockey app looks more appealing and if we switch (yet again) maybe I can try 1.2 before a GM.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
If you were giving a quick presentation to some Objective C developers covering the basics of Swift, any resources or slide decks you'd use?

TwoDice
Feb 11, 2005
Not one, two.
Grimey Drawer
CoreBluetooth seems to be a bit busted in Swift on OS X - I can't combine CBCharacteristicProperties with | like I can in iOS (the following code works on iOS, doesn't compile on OS X because the .Read | .Notify is invalid):

code:
CBMutableCharacteristic(
                type: uuid,
                properties: .Read | .Notify,
                value: nil,
                permissions: .Readable)
The definitions of the two are different:

code:
OSX
enum CBCharacteristicProperties : Int {
    
    case Broadcast
    case Read
    case WriteWithoutResponse
    case Write
    case Notify
    case Indicate
    case AuthenticatedSignedWrites
    case ExtendedProperties
    case NotifyEncryptionRequired
    case IndicateEncryptionRequired
}
code:
iOS
struct CBCharacteristicProperties : RawOptionSetType {
    init(_ rawValue: UInt)
    init(rawValue: UInt)
    
    static var Broadcast: CBCharacteristicProperties { get }
    static var Read: CBCharacteristicProperties { get }
    static var WriteWithoutResponse: CBCharacteristicProperties { get }
    static var Write: CBCharacteristicProperties { get }
    static var Notify: CBCharacteristicProperties { get }
    static var Indicate: CBCharacteristicProperties { get }
    static var AuthenticatedSignedWrites: CBCharacteristicProperties { get }
    static var ExtendedProperties: CBCharacteristicProperties { get }
    static var NotifyEncryptionRequired: CBCharacteristicProperties { get }
    static var IndicateEncryptionRequired: CBCharacteristicProperties { get }
}
Is there some way I can easily combine these flags on OS X?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Well, first things first, please file a bug if you haven't already. The enum should clearly be imported the same way on both OSes; it's just that the Mac OS X SDK hasn't been annotated correctly.

It's a little bit gross, but imported enums always implement RawRepresentable, and you can use that to construct an arbitrary value. So this should work:

Swift code:
infix func |(lhs: CBCharacteristicProperties, rhs: CBCharacteristicProperties) -> CBCharacteristicProperties {
  return CBCharacteristicProperties(rawValue: lhs.rawValue | rhs.rawValue)
}

TwoDice
Feb 11, 2005
Not one, two.
Grimey Drawer
Thanks, I'll try that. (also bug filed as 20377231)

edit: That solution compiles, but crashes at runtime trying to unwrap the optional return type of CBCharacteristicProperties(rawValue:). It accepts any of the default values' rawValue, but not the | of any of them.

TwoDice fucked around with this message at 04:13 on Apr 1, 2015

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Hmm, it was working in my tests, but that doesn't mean much. You're probably stuck with unsafeBitCast.

Adbot
ADBOT LOVES YOU

TwoDice
Feb 11, 2005
Not one, two.
Grimey Drawer
code:
func | (lhs: CBCharacteristicProperties, rhs: CBCharacteristicProperties) -> CBCharacteristicProperties {
    return unsafeBitCast(lhs.rawValue | rhs.rawValue, CBCharacteristicProperties.self)
}
Works great; shame about the type safety.

  • Locked thread