Swift 2 NSMutableArray() value don't shows in variable - ios

Swift 2 NSMutableArray() value don't shows in variable
My codes here.
var detail_desc : NSMutableArray! = NSMutableArray()
when i added this code gives me
label.text = self.detail_desc.description
And my array output
{
{
"cat_img" = "http://asdasd.com/asd.jpg";
"cat_name" = Good;
id = 45;
"is_active" = 3;
"last_update" = "2015-11-21 15:32:42";
}
}
I want to use array item to variable ;
label.text = cat_img
label2.text = cat_name
any idea ?

There's a lot wrong with what you have, I'll try to tackle it one by one:
Underscore
Underscore naming isn't common in cocoa and reads very strange. Change detail_desc to detailDesc.
Note: There are situations in which we use the underscore, one of which is extensions on core classes. In these cases, it is prefix - underscore - name. ie: my_specialFunctionOrVariable
NSMutableArray
NSArray and NSDictionary classes shouldn't be used in Swift unless absolutely necessary. They behave slightly differently, and you lose all of the type safety that makes swift so great.
Naming
In general, naming schemes like label, label2, and detailDescription are very confusing. They don't tell me anything about what each represents. Try something like catImageUrlLabel, and catNameLabel to be more specific. Also, detailDescription could be catInformation
Single Object Encapsulated In Array
You really have a dictionary as the single object in an array, I think you should just have the dictionary reference. (unless there could be more in the future). I'll move forward assuming there won't be.
How it might look
Change your variable to something like this:
var detailDescription: [String : AnyObject] = ...
Then, in your UI setting code, do something like this:
label.text = detailDescription["cat_img"] as? String
label2.text = detailDescription["cat_name"] as? String
Modelling Objects
Json is dirty and we prefer not to deal with it as much as possible. Consider modeling your Cat json to a Cat object:
struct Cat {
let imageUrl: String
let name: String
let id: Int
// etc.
}
Then parse the json into this model when you receive it and pass that to your view controller.
Then our code might look like this:
nameLabel.text = cat.name
imageUrlLabel.text = cat.imageUrl
// etc.
This is very clear what everything represents, and will make for a more readable, and more maintainable code base.
Hope this gets you off on the right track.

Related

How to find value difference of two struct instances in Swift

I have two instances from the same struct in Swift. I need to find out key-values that have the same keys but different values.
For example:
struct StructDemo {
let shopId: Int
let template: String?
}
let a = StructDemo(shopId: 3, template: "a")
let a = StructDemo(shopId: 3, template: "different a")
// My expectation is to return the change pairs
let result = [template: "different a"]
My approach is as show below but comes errors.
static func difference(left: StructDemo, right: StructDemo) -> [String: Any]{
var result:[String: Any] = [:]
for leftItem in Mirror(reflecting: left).children {
guard let key = leftItem.label else { continue }
let value = leftItem.value
if value != right[key] { // This is the problem. Errror message: Protocol 'Any' as a type cannot conform to 'RawRepresentable'
result[key] = right[key]
}
}
}
Appreciate for any suggestion and solutions.
Thank you
The problem that you are seeing is that you referred to
right[key]
but right is a StructDemo and is not subscriptable. You can't look up fields given a runtime name. Well, you can with Mirror which you correctly used for left, but you did not mirror right.
Using Mirror will lead to other issues, as you will have expressions with static type Any where Equatable will be required in order to compare values.
IMHO, your best bet is to avoid a generic, reflective approach, and just embrace static typing and write a custom difference functions that iterates all the known fields of your type. Hard coding is not so bad here, if there is only one struct type that you are trying to diff.
If you have a handful of struct types each needing diffs then that might be a different story, but I don't know a good way to get around the need for Equatable. But if you have a ton of diffable types, maybe you want dictionaries to begin with?

How to Make a Struct Version of the NSCountedSet Class?

I am developing an app in which I need to take two arrays, both holding the same custom data type, MenuItem.
I need to compare them and find the common elements of both arrays.
I compare the two arrays by converting them both to sets and then using the compare function of the set struct.
However, I then need to convert the array of common elements to a Counted Set so that I can find how many of each element exist in the group of common elements.
The problem I am having is with converting the the array of common elements to a Counted Set. In Swift, there is an NSCountedSet class but no CountedSet struct like there are for most built-in swift Data Types:
let groups = Array(self.menu.keys)
//menu and cart are dictionaries the structure [MenuGroup: [MenuItem]]
let cartGroups = Array(self.cart.keys)
let group = groups[indexPath.section]
if cartGroups.contains(group) {
let items = menu[group] as [MenuItem]!
let cartItems = cart[group]
let itemsSet = Set<MenuItem>(items!)
let cartItemsSet = Set<MenuItem>(cartItems!)
let similarSet = itemsSet.intersection(cartItemsSet)
let similarArray = NSMutableArray(Array(similarSet))
let similarCounterSet = NSCountedSet(array: similarArray)
}
I want to create a struct based off the NSCountedSet class so that I can convert the array of common elements to a counted set.
The if statement is for something else, it does not pertain to this question.
Any thoughts on how to do this? If anybody has a different approach to this problem feel free to mention that too.
Thanks,
Simon
Thanks to Martin R I Found An Example of How to do This:
There are various CountedSet implementation available, e.g. https://github.com/0x7fffffff/CountedSet.

Multidimensional Array Looping in cellForRowAtIndexPath Swift

I have a multidimensional array that I want to display the values of onto one UILabel in each respective cell.
My arrays look like this:
var arrayExample = [["beverages", "food", "suppliers"]["other stuff, "medicine"]]
I'm looping through these values in the cellForRowAtIndexPath in order for it to display on different cells (on a UILabel) the appropriate values:
if let onTheLabel: AnyObject = arrayOfContactsFound as? AnyObject {
for var i = 0; i < objects!.count; i++ {
cell?.contactsUserHas.text = "\(onTheLabel[indexPath.row][i])" as! String
print("arrayOfContactsFound Printing! \(onTheLabel)")
}
}
When printing to the console I get:
arrayOfContactsFound Printing! (
(
beverages,
"supply chain",
pharmacuticals
)
)
But on my label I get "beverages". That's it. How can I get the other 2 values (or X amount if there are more or less than 3 values)?
My for in loop is obviously not doing the trick. Assuming I can optimize/fix that to display all the values?
Thanks in advance.
In your loop you're setting the text of your label multiple times. Each time you set it it doesn't accumulate, it completely replaces the current text with the new text. You'll want something like this:
// Remove the cast and the loop in your code example, and replace with this
let items = arrayOfContactsFound[indexPath.row]
let itemsString = items.joinWithSeparator(" ")
cell?.contactsUserHas.text = itemsString
Another thing to note is your cast doesn't quite make a lot of sense.
var arrayExample = [["beverages", "food", "suppliers"]["other stuff, "medicine"]]
So arrayExample is of type [[String]]. I'm assuming each cell in your table view represents one of the arrays of strings in your array. So each cell represents one [String]. So your items should be arrayExample[indexPath.row]. The cast to AnyObject doesn't make too much sense. If anything you'd be casting it to [[AnyObject]], but there's no reason to because the compiler should already know it's [[String]].

Generating unique uibutton tags

I think this is impossible but I'm hoping someone knows a work around to use a unique int or string as a uibutton tag
Ideally I want something like this:
let uuid = NSUUID().UUIDString
myBTN.tag = uuid.toInt()!
It's frustrating swift only allows int as tags
If you'd like to assign a unique integer to the tag of the view as you've described you can do something like this:
myButton.tag = Int(arc4random())
That will give you a very random tag which is unlikely to collide.
This is almost certainly a poor solution to the broader context though. If adding a UUID is actually correct, consider subclassing UIButton and adding a unique identifier property instead of using the tag.
Consider, as #dimpiax suggests, storing references to your buttons as properties, most likely an array of buttons, rather than using identifiers and going back to find the related button later.
You can do a trick with a helper class and then, do it like this;
let uuid:Int = NSUUIDI.UUIDInt; // NSUUIDI() Not required here
myBTN.tag = uuid;
//Reverse (String value from tag)
println(NSUUIDI.UUIDStringFromInt(myBTN.tag));
Helper Class here;
//NSUUIDI.swift
class NSUUIDI:NSObject {
private static var _uUIDs:[String] = [String]();
class var UUIDInt:Int {
get {
let uUIDInt:Int = NSUUIDI._uUIDs.count;
NSUUIDI._uUIDs.append(NSUUID().UUIDString);
return uUIDInt;
}
}
class func UUIDStringFromInt(uUID:Int) -> String {
return (uUID < NSUUIDI._uUIDs.count) ? NSUUIDI._uUIDs[uUID]:"\(uUID)";
}
}

Swift Int is not convertible to DictionaryIndex?

I'm trying to convert this piece of ojb-c code:
MPMovieFinishReason finishReason = [notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey] integerValue];
to swift, and as such I have this:
var finishReason: MPMovieFinishReason = notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey.integerValue];
However this gives me the error in the title.
What am I doing wrong here?
You have a few problems, first of all in your direct translation:
var finishReason: MPMovieFinishReason = notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey.integerValue];
The ] is in the wrong place, so you're trying to call integerValue on MPMoviePlayer... instead of on the dictionary lookup.
var finishReason: MPMovieFinishReason = notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey].integerValue;
This is still failing because userInfo is an NSDictionary and not a Dictionary, so it gets mapped to [AnyObject:AnyObject] It seems like the automatic morphing is failing you, so it's falling back to a CFString which isn't mappable to AnyObject.
The process becomes a little clearer if we break it up more:
// Recover the original dictionary, and cast is by input and output, to it
// all makes sense. This will allow String as a parameter and return an NSNumber
// as a result.
let userInfo = notification.userInfo as [String:NSNumber]
// From the userInfo, let's extract the raw NSNumber using lookup
let reason = userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]
// Convert the NSNumber into an MPMovieFinishReason enum. Note that it's
// 0215 and I'm on ambien so I don't care about the force unwrapping that
// should be optional unwrapping
let finishReason = MPMovieFinishReason.fromRaw(reason!.integerValue)
Many problems can be broken down into much simpler problems if you just take it a single step at a time. Modern compilers aren't even too bothered by it as the can recognize when variables are no longer in use and do proper reclamation. Also note using let instead of var for those temporary values since they shouldn't be reused anyway.
Try the type-casting function Int()
ie.,
var finishReason = Int(notification.userInfo[MPMoviePlayerPlaybackDidFinishReasonUserInfoKey]) as MPMovieFinishReason;

Resources