IOS::How to get the MPMediaquery Songsquery Artwork - ios7

I'm using this code for getting the Artwork, but it's not workout for me. What's the wrong in this code.Suggest me.
Thanks.
MPMediaQuery *mySongsQuery = [MPMediaQuery songsQuery];
NSArray *SongsList = [mySongsQuery collections];
for (MPMediaItemCollection *SongsArt in SongsList) {
NSArray *songs = [SongsArt items];
for (MPMediaItem *song in songs) {
if ([(MPMediaItem*)item valueForProperty:MPMediaItemPropertyAssetURL] != nil) {
CGSize artworkImageViewSize = CGSizeMake(40, 40);
MPMediaItemArtwork *artwork = [song valueForProperty:MPMediaItemPropertyArtwork];
UIImage * image = [artwork imageWithSize:artworkImageViewSize];
if (image!= nil)
{
imgv_songImageView.image = image;
}
else
{
imgv_songImageView.image = [UIImage imageNamed:#"musicD-jpeg.png"];
}
}
}

I assume you just want to loop through all songs in the music library so I don't see a need for collections:
MPMediaQuery *mySongsQuery = [MPMediaQuery songsQuery];
for (MPMediaItem *item in mySongsQuery.items) {
if (![[item valueForProperty:MPMediaItemPropertyIsCloudItem]boolValue]) {
CGSize artworkImageViewSize = CGSizeMake(40, 40);
MPMediaItemArtwork *artwork = [song valueForProperty:MPMediaItemPropertyArtwork];
UIImage *image = [artwork imageWithSize:artworkImageViewSize];
if (image) {
imgv_songImageView.image = image;
} else {
imgv_songImageView.image = [UIImage imageNamed:#"musicD-jpeg.png"];
}
}
}
I'm not sure why you want to check for the Asset URL but I've left it in.

Here i am posting the code to get the tracks and sorting them alphabetically. Its written in swift3.
/// Get all the songs in the device and display in the tableview
///
func getAllSongs() {
let query: MPMediaQuery = MPMediaQuery.songs()
let allSongs = query.items
allSongItems?.removeAll()
guard allSongs != nil else {
return
}
var index = 0
for item in allSongs! {
let pathURL: URL? = item.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
if pathURL == nil {
print("#Warning!!! Track : \(item) is not playable.")
} else {
let trackInfo = SongItem()
trackInfo.index = index
trackInfo.mediaItem = item
let title = item.value(forProperty: MPMediaItemPropertyTitle) as? String ?? "<Unknown>"
let artistName = item.value(forProperty: MPMediaItemPropertyArtist) as? String ?? "<Unknown>"
trackInfo.songName = title
trackInfo.artistName = artistName
trackInfo.isSelected = false
trackInfo.songURL = item.value(forProperty: MPMediaItemPropertyAssetURL) as? URL
allSongItems?.append(trackInfo)
index += 1
}
}
// Sort the songs alphabetically
let sortedArray: [SongItem]? = allSongItems?.sorted {
$0.songName!.localizedCompare($1.songName!) == .orderedAscending
}
allSongItems?.removeAll()
if let arr = sortedArray {
allSongItems?.append(contentsOf: arr)
}
}

Related

Convert subscript function from Objective C to Swift

I am trying to convert some Objective C code to Swift and can't manage to do it right with subscripting.
This is the method I am trying to migrate to Swift:
- (NSArray *)rangesOfSubstringAlphaNumeric:(NSString *)substring rangesLimit:(NSUInteger)rangesLimit {
NSAssert(rangesLimit, #"A range limit grather than 0 must be specified");
if (!substring.length) {
return nil;
}
static NSCharacterSet * restrictedCharacters = nil;
if (!restrictedCharacters) {
restrictedCharacters = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
}
NSArray * substrings = [substring componentsSeparatedByCharactersInSet:restrictedCharacters];
NSMutableArray * allRanges = [NSMutableArray array];
NSString *searchedString = self;
for (NSString *stringToMatch in substrings) {
if (![stringToMatch isEqualToString:#""]) {
NSRange aRange;
NSUInteger lastLocation = 0;
NSUInteger foundRanges = 0;
while (foundRanges++ < rangesLimit &&
(aRange = [searchedString localizedStandardRangeOfString:stringToMatch]).location != NSNotFound) {
searchedString = [searchedString substringFromIndex:aRange.location + aRange.length];
aRange.location = aRange.location + lastLocation;
lastLocation = aRange.location + aRange.length;
[allRanges addObject:[NSValue valueWithRange:aRange]];
}
}
}
return allRanges.count ? [allRanges copy] : nil;
}
I got stuck on the subscripting part since it seems I cannot assign integer values to Indexes and conversion from Index to Int is out of hand for me I'm kind of stuck, this is what I managed to do:
func rangesOfAlphanumeric(substring: String, limit: UInt) -> [Range<String.Index>] {
guard limit > 0, !substring.isEmpty else {
if limit == 0 {
assert(false, "limit must be greather than 0")
}
return []
}
var searchedString = self
let substrings = substring.components(separatedBy: NSCharacterSet.restricted)
for stringToMatch in substrings {
if !stringToMatch.isEmpty {
// var aRange: Range<String.Index>?
// var lastLocation: UInt = 0
// var foundRanges: UInt = 0
// while foundRanges < limit,
// let tempRange = searchedString.localizedStandardRange(of: stringToMatch),
// !tempRange.isEmpty {
//
// searchedString = String(searchedString[tempRange.upperBound...])
// if let lastLocation = lastLocation {
// aRange = temp
// }
// }
}
}
}
UPDATE: Solution below.
Managed to resolve the issue using the ranges function posted here:
func rangesOfAlphanumeric(substring: String) -> [Range<String.Index>] {
var searchedString = self
let substrings = substring.components(separatedBy: NSCharacterSet.restricted)
return substrings.compactMap { (stringToMatch) -> [Range<String.Index>]? in
guard !stringToMatch.isEmpty else {
return nil
}
let ranges = searchedString.ranges(of: stringToMatch, options: [
.diacriticInsensitive,
.caseInsensitive
])
if let lastRange = ranges.last {
searchedString = String(searchedString[index(after: lastRange.upperBound)])
}
return ranges
}.flatMap{$0}
}
I created this repo with swift 5 is very easy to use
all is already set up. you have just to change the IAP ids
The Github repo

FSInteractiveMap Objective-C to Swfit translate

i want to use FSInteractiveMap in swift
but documentations are only is Objective-C and i can't Translate click Handler in swift.
NSDictionary* data = #{ #"asia" : #12,
#"australia" : #2,
#"north_america" : #5,
#"south_america" : #14,
#"africa" : #5,
#"europe" : #20
};
FSInteractiveMapView* map = [[FSInteractiveMapView alloc] initWithFrame:self.view.frame];
[map loadMap:#"world-continents-low" withData:data colorAxis:#[[UIColor lightGrayColor], [UIColor darkGrayColor]]];
in swift working with:
let map: FSInteractiveMapView = FSInteractiveMapView()
map.frame = self.view.frame
var mapData = [String: Int]()
mapData["IR-01"] = 0
mapData["IR-02"] = 10
var mapColors = [UIColor]()
mapColors.append(UIColor(red:0.26, green:0.112, blue:0.0, alpha:1.0))
mapColors.append(UIColor(red:0.45, green:0.132, blue:0.0, alpha:1.0))
map.loadMap("iranHigh", withData:mapData, colorAxis:mapColors)
view.addSubview(map)
view.setNeedsDisplay()
its working correctly but i cant add click Handler
here is documentation in Objective-C:
FSInteractiveMapView* map = [[FSInteractiveMapView alloc] initWithFrame:CGRectMake(16, 96, self.view.frame.size.width - 32, 500)];
[map loadMap:#"usa-low" withColors:nil];
[map setClickHandler:^(NSString* identifier, CAShapeLayer* layer) {
if(_oldClickedLayer) {
_oldClickedLayer.zPosition = 0;
_oldClickedLayer.shadowOpacity = 0;
}
_oldClickedLayer = layer;
// We set a simple effect on the layer clicked to highlight it
layer.zPosition = 10;
layer.shadowOpacity = 0.5;
layer.shadowColor = [UIColor blackColor].CGColor;
layer.shadowRadius = 5;
layer.shadowOffset = CGSizeMake(0, 0);
}];
OR:
[map setClickHandler:^(NSString* identifier, CAShapeLayer* layer) {
self.detailDescriptionLabel.text = [NSString stringWithFormat:#"Continent clicked: %#", identifier];}];
how can i do it in Swift?
add some code, looks like that
override func viewDidLoad() {
super.viewDidLoad()
let map: FSInteractiveMapView = FSInteractiveMapView()
weak var oldClickedLayer = CAShapeLayer()
var mapData = [String: Int]()
mapData["asia"] = 12
mapData["australia"] = 2
mapData["north_america"] = 5
mapData["south_america"] = 14
mapData["africa"] = 5
mapData["europe"] = 20
var mapColors = [UIColor]()
mapColors.append(UIColor.lightGray)
mapColors.append(UIColor.darkGray)
map.frame = self.view.frame
map.clickHandler = {(identifier: String? , _ layer: CAShapeLayer?) -> Void in
if (oldClickedLayer != nil) {
oldClickedLayer?.zPosition = 0
oldClickedLayer?.shadowOpacity = 0
}
oldClickedLayer = layer
// We set a simple effect on the layer clicked to highlight it
layer?.zPosition = 10
layer?.shadowOpacity = 0.5
layer?.shadowColor = UIColor.black.cgColor
layer?.shadowRadius = 5
layer?.shadowOffset = CGSize(width: 0, height: 0)
print("clicked")
}
let mapName: String! = String("world-continents-low")
map.loadMap(mapName, withData:mapData, colorAxis:mapColors)
view.addSubview(map)
view.setNeedsDisplay()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
that worked for me.
Don't forget to import library

How to access data "deep" inside a NSDictionary?

I am getting a JSON response from a web service as follows into a NSDictionary
NSDictionary *fetchAllCollectionsJSONResponse = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
If I dump the output of the NSDictionary it looks correct like this
2017-10-06 10:11:46.097698+0800 NWMobileTill[396:33294] +[ShopifyWebServices fetchAllCollections]_block_invoke, {
data = {
shop = {
collections = {
edges = (
{
cursor = "eyJsYXN0X2lkIjo0NTI4NTY3MTcsImxhc3RfdmFsdWUiOiI0NTI4NTY3MTcifQ==";
node = {
description = "";
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1Mjg1NjcxNw==";
};
},
{
cursor = "eyJsYXN0X2lkIjo0NTI4NTkwODUsImxhc3RfdmFsdWUiOiI0NTI4NTkwODUifQ==";
node = {
description = "Test Collection 1";
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1Mjg1OTA4NQ==";
};
},
{
cursor = "eyJsYXN0X2lkIjo0NTU0OTMwMDUsImxhc3RfdmFsdWUiOiI0NTU0OTMwMDUifQ==";
node = {
description = Sovrum;
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1NTQ5MzAwNQ==";
};
},
{
cursor = "eyJsYXN0X2lkIjo0NTU0OTMzODksImxhc3RfdmFsdWUiOiI0NTU0OTMzODkifQ==";
node = {
description = Badrum;
id = "Z2lkOi8vc2hvcGlmeS9Db2xsZWN0aW9uLzQ1NTQ5MzM4OQ==";
};
}
);
pageInfo = {
hasNextPage = 0;
};
};
};
};
}
I need to access the "description" attribute deep inside this structure and I cannot figure out how to do it.
I tried the following but it crashes
for (NSDictionary *dictionary in fetchAllCollectionsJSONResponse) {
NSLog(#"jongel %#", [dictionary objectForKey:#"data"]);
}
#Bilal's answer is right. This might be a bit easier to read:
NSArray *edges = fetchAllCollectionsJSONResponse[#"data"][#"shop"][#"collections"][#"edges"];
for (NSDictionary *edge in edges) {
NSString *description = edge[#"node"][#"description"];
NSLog(#"description = %#", description);
}
fetchAllCollectionsJSONResponse is a Dictionary not an Array. Try this.
NSDictionary *fetchAllCollectionsJSONResponse = nil;
NSDictionary *data = fetchAllCollectionsJSONResponse[#"data"];
NSDictionary *shop = fetchAllCollectionsJSONResponse[#"shop"];
NSDictionary *collections = fetchAllCollectionsJSONResponse[#"collections"];
NSArray *edges = fetchAllCollectionsJSONResponse[#"edges"];
// Or a shorter version
// NSArray *edges = fetchAllCollectionsJSONResponse[#"data"][#"shop"][#"collections"][#"edges"];
for (NSDictionary *edge in edges) {
NSString *cursor = edge[#"cursor"];
NSDictionary *node = edge[#"node"];
}

Attach array of photos with mailcore

I need to attach an array of photos to an email using MailCore. I found the following code in another question, however I'm not sure how to apply this to the photos taken with the camera in my app.
My guess is that I have to get the filename of the photos and save them as strings to an array, and then attach the strings to the email by using the snippet of code.
NSArray *allAttachments = [NSArray arrayWithObjects:#{#"FilePathOnDevice": #"/var/mobile/etc..", #"FileTitle": #"IMG_0522.JPG"}, nil];
for (int x = 0; x < allAttachments.count; x++) {
NSString *attachmentPath = [[allAttachments objectAtIndex:x] valueForKey:#"FilePathOnDevice"]];
MCOAttachment *attachment = [MCOAttachment attachmentWithContentsOfFile:attachmentPath];
[msgBuilder addAttachment:attachment];
}
This is how I'm getting the photo using the camera
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){
imagePicker.sourceType = .Camera
imagePicker.dismissViewControllerAnimated(true, completion: nil)
var photo = info[UIImagePickerControllerOriginalImage] as? UIImage
bedroomCells[lastSelectedIndex!.row].image = photo
tableView.reloadData()
}
Thank you for your help!
I ended up saving the image to the documents directory and using that file path to attach the image to mailcore.
Here is my code for the image picker:
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject : AnyObject]){
imagePicker.sourceType = .Camera
imagePicker.dismissViewControllerAnimated(true, completion: nil)
var photo = info[UIImagePickerControllerOriginalImage] as? UIImage
bedroomCells[lastSelectedIndex!.row].image = photo
var photoLabel = bedroomCells[lastSelectedIndex!.row].text
tableView.reloadData()
//save photo to document directory
var imageData = UIImageJPEGRepresentation(photo, 1.0)
var imageFilePath = fileDirectory[0].stringByAppendingPathComponent("\(photoLabel!).jpg")
var imageFileURL = NSURL(fileURLWithPath: imageFilePath)
imageData.writeToURL(imageFileURL!, atomically: false)
}
and the code for my mailcore method:
MCOMessageBuilder * builder = [[MCOMessageBuilder alloc] init];
NSString *documentsDirectory = [fileDirectory objectAtIndex:0];
NSArray *allAttachments = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:documentsDirectory error:nil];
for (int x = 0; x < allAttachments.count; x++) {
NSString *attachmentPath = [documentsDirectory stringByAppendingPathComponent:[allAttachments objectAtIndex:x]];
MCOAttachment *attachment = [MCOAttachment attachmentWithContentsOfFile:attachmentPath];
[builder addAttachment:attachment];
}
In swift code:
var dataImage: NSData?
dataImage = UIImageJPEGRepresentation(image, 0.6)!
var attachment = MCOAttachment()
attachment.mimeType = "image/jpg"
attachment.filename = "image.jpg"
attachment.data = dataImage
builder.addAttachment(attachment)

Programmatically create a group in contacts

How to programmatically add a new group to the iPhone contact using AddressBook framework?
First look and see if it exists, and if not, create it:
bool foundIt = NO;
// Protective - did we just not find it, or lose it?
CFArrayRef groups = ABAddressBookCopyArrayOfAllGroups(addrBook);
CFIndex numGroups = CFArrayGetCount(groups);
for(CFIndex idx=0; idx<numGroups; ++idx) {
ABRecordRef groupItem = CFArrayGetValueAtIndex(groups, idx);
CFStringRef name = (CFStringRef)ABRecordCopyValue(groupItem, kABGroupNameProperty);
//NSLog(#"Look at group named %#", name);
bool isMatch = [newName isEqualToString:(NSString *)name];
CFRelease(name);
if(isMatch) {
// NSLog(#"FOUND THE GROUP ALREADY!");
groupNum = [NSNumber numberWithInt:ABRecordGetRecordID(groupItem)];
[self setObject:groupNum forKey:kGroupID];
foundIt = YES;
break;
}
}
CFRelease(groups);
if(!foundIt) {
// lets create one
ABRecordRef groupItem = ABGroupCreate();
ABRecordSetValue(groupItem, kABGroupNameProperty, (CFStringRef *)newName, &error);
if(!error) {
ABAddressBookAddRecord (addrBook, groupItem, &error); // bool ret =
ABAddressBookSave(addrBook, &error);
groupNum = [NSNumber numberWithInt:ABRecordGetRecordID(groupItem)];
//NSLog(#"FIRST groupNumber: %#", groupNum);
[self setObject:groupNum forKey:kGroupID];
}
CFRelease(groupItem);
}