ios - 真正理解iOS中的NSData、NSMutableData、NSString应该学什么?

标签 ios swift

我是 iOS 开发的中级学生,我正在尝试制作一种将图像上传到服务器的方法。我了解 PHP 中的服务器端脚本。

但是当我按照教程在 Xcode 中上传图片时,我并没有真正掌握 NSData、NSObject、NSMutableData、NSString,看来该教程并没有真正了解 NSData、NSMutableData 的基本方面, NSString...

如果想要漂亮的展示,我应该学习自动布局、 Collection View 等。

那么,我应该学习iOS开发中的哪些主题才能真正了解这些东西呢?好像从来没有专门学过这些东西。我不知道从哪里开始。

上传图片的代码是这样的:

func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
        let body = NSMutableData();

        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString("\(value)\r\n")
            }
        }

                let filename = "user-profile.jpg"
                let mimetype = "image/jpg"

                body.appendString("--\(boundary)\r\n")
                body.appendString("Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
                body.appendString("Content-Type: \(mimetype)\r\n\r\n")
                body.appendData(imageDataKey)
                body.appendString("\r\n")



        body.appendString("--\(boundary)--\r\n")

        return body
    }



    func generateBoundaryString() -> String {
        return "Boundary-\(NSUUID().UUIDString)"
    }


}


extension NSMutableData {

    func appendString(string: String) {
        let data = string.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: true)
        appendData(data!)
    }
}

最佳答案

了解您所描述的对象可能意味着很多事情。如果您追求他们的能力,那么文档就足够了。但是,如果您更关心引擎盖下的内容以及我们为什么需要这些对象,那么我只能建议您研究一些较旧的语言,例如 C。

NSDataNSMutableDataNSString这几个对象都是数据容器,缓冲区。但是 NSObject 只是一个基类,所有其他对象都继承自该基类。

关于 NSDataNSMutableData 的一些信息: 在 C 语言中,当创建原始缓冲区时,您使用 malloc 它会在内存中保留一个 block ,您可以随意使用。完成后,您需要调用 free 来释放该内存,否则您将发生内存泄漏。

void *voidPointer = malloc(100); // Reserved 100 bytes of whatever data
int *intPointer = (int *)malloc(sizeof(int)*100); // Reserved enough bytes to fit 100 integers whatever their size may be
intPointer[13] = 1; // You may use these as normal array
free(voidPointer); // Free this memory
free(intPointer); // Free this memory

所以 NSData 基本上是一个包装器,并为您完成所有这些工作。您甚至可以通过在 NSData 对象上调用 bytes 来访问原始指针。 然后可变版本 NSMutableData 只是一个具有一些附加功能的子类。您实际上可以附加数据。从幕后追加数据并不是那么简单。您需要分配一个新的内存块,将旧数据复制到其中,复制新数据并释放之前的内存块。

void *currentData = malloc(100); // Assume we have some data
void *dataToAppend = malloc(100); // Another chunk of data we want to append
void *combinedData = malloc(200); // We need a larger buffer now
memcpy(combinedData, currentData, 100); // Copy first 100 bytes to new data
memcpy(combinedData+100, dataToAppend, 100); // Copy next 100 bytes to new data
free(currentData); // Free old data
free(dataToAppend); // Free old data
... use combinedData here ...
free(combinedData); // Remember to free combined data once done

这些都是非常简单的方法,但编写它们可能已经很痛苦,而且这样做很容易产生错误。所以 NSDataNSMutableData 甚至 Swift 中的 Data 都只是数据容器,让你的开发者的生活更轻松。在 Objective-C 中,从数据到 C 缓冲区的转换非常简单:

NSData *myData = [NSData dataWithBytes:myDataPointer length:myDataLength];
void *myRawPointer = [myData bytes];

NSString 并没有什么不同。在 C 语言中,我们再次拥有用作字符串的字符指针,因此我们可以这样写:

char *myText = "Some text";

这些有点特别,真的很方便。我们也可以这样做:

char *myText = (char *)malloc(sizeof(char)*100);

然后逐个字符填充数据:

myText[0] = 'S';
myText[1] = 'o';
myText[2] = 'm';
...
myText[9] = 't';
myText[10] = '\0'; // We even need to set a null terminator at the end

然后我们需要再次释放内存...但不要管 C 字符串,NSString 又是一个包装器,负责分配内存、分配数据并做任何你想做的事情它。它有许多方法,您可以简单地使用它们来让您的生活更轻松。

至于您发布的代码,它是两者的结合。在您的情况下,您的 API 接受图像作为多部分表单数据请求,您可以将其理解为原始图像文件,周围添加了一些文本,只是为了解释数据包含的内容。这是一种普遍使用的方式,但不是唯一的一种。您也可以只发布原始图像数据,或者您甚至可以发布包含 base64 字符串编码数据的 JSON。同样,这些文本通常表示为 utf8 编码数据。

最终它是一套普遍使用的标准,因此我们的计算机可以相互通信。你的图像很可能是由 png 或 jpg 的标准定义的,关于如何用字节串来呈现它,你的字符串是由 utf8 标准定义的,你的整个请求正文是由一些 HTTP 标准定义的(甚至不确定它的哪一部分就是它)。而你所使用和想要了解的对象,只是你达成结果的一些 helper 。在大多数情况下理解它们就像理解 Screwdriver 一样;在大多数情况下,您不需要这样做,但您确实需要知道它们的存在,并且需要知道何时使用它们。

您发布的代码本身相对较差,但应该可以完成它的工作。对于初学者来说,它甚至可能有点令人困惑。这个解决方案的更合乎逻辑的伪代码可能是这样的:

let imageData: Data // My image data
let headerString: String // Text I need to put before the image data
let footerString: String // Text I need to put after the image data

var dataToSend: Data = Data() // Generate data object
dataToSend.append(headerString.utf8Data) // Append header
dataToSend.append(imageData) // Append raw data
dataToSend.append(footerString.utf8Data) // Append footer

我希望这能澄清一些事情。

关于ios - 真正理解iOS中的NSData、NSMutableData、NSString应该学什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47825870/

相关文章:

ios - 如何通过单击单元格中的按钮来删除 tableView 中的单元格?使用核心数据

ios - 在 MacOS 上安装 TensorFlow-experimental 时出错 - curl : (60) SSL certificate

ios - 如何将水平分页捕捉到像 App Store 这样的多行 Collection View ?

objective-c - Retina 显示来自 URL 的图像

iOS 7 UIButtonBarItem 图像不着色

ios - 选择单元格时,UITableViewCell 中的 UISwitch 会卡住应用程序,不会在 UISwitch 切换时卡住

swift - Swift #availability 检查的最后一个参数

arrays - 如何使用搜索栏对字典数组进行排序

ios - 检查蓝牙状态 - Swift 4

ios - 核心数据 : error: Mutating a managed object after it has been removed from its context